使用信号灯实现互斥机制的文件写操作

本文介绍了一种使用信号灯(semaphore)实现文件写操作的互斥机制。通过创建信号灯并初始化信号灯结构来控制对文件的并发写入,确保同一时间只有一个进程能够写入文件,从而避免数据冲突。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用使用信号灯实现互斥机制的文件写操作

#include <sys/sem.h>
#include <stdio.h>
#include <errno.h>

#define PERMS IPC_CREAT|IPC_EXCL|00666
#define MAX_CANON 10

void init_semaphore_struct(struct sembuf *sem,int semnum, int semop,int semflg)
{
    /* 初始话信号灯结构 */
    sem->sem_num=semnum;
    sem->sem_op=semop;
    sem->sem_flg=semflg;
}

int del_semaphore(int semid)
{
 
    /* 信号灯并不随程序的结束而被删除,如果我们没删除的话(将1改为0)
    可以用ipcs命令查看到信号灯,用ipcrm可以删除信号灯的
    */
    #if 1
    return semctl(semid,0,IPC_RMID);
    #endif
}

 

int main(int argc,char **argv)
{
    char buffer[MAX_CANON],*c;
    char buffer2[MAX_CANON];
    int i,n;
    int semid,semop_ret,status;
    pid_t childpid;
    struct sembuf semwait,semsignal;
    FILE *       ar_Fp;

    /* 使用IPC_PRIVATE 表示由系统选择一个关键字来创建 */
    /* 创建以后信号灯的初始值为0 */
    if((semid=semget(IPC_PRIVATE,1,PERMS))==-1)
    {
        fprintf(stderr,"[%d]:Acess Semaphore Error:%s/n/a",getpid(),(char *)strerror(errno));
        exit(1);
    }

    /* semwait是要求资源的操作(-1) */
    init_semaphore_struct(&semwait,0,-1,0);

    /* semsignal是释放资源的操作(+1) */
    init_semaphore_struct(&semsignal,0,1,0);

    /* 开始的时候有一个系统资源,如果不执行会进入无限等待状态 */
    if(semop(semid,&semsignal,1)==-1)
    {
        fprintf(stderr,"[%d]:Increment Semaphore Error:%s/n/a",
        getpid(),(char *)strerror(errno));
       
        if(del_semaphore(semid)==-1){
            fprintf(stderr,"[%d]:Destroy Semaphore Error:%s/n/a",
            getpid(),(char *)strerror(errno));
        }
        exit(1);
    }

    /* 创建一个进程链(4个进程) */
    for(i=0;i < 2; i++)
    {
        childpid=fork();
        if (childpid == 0) //child
        {
            sprintf(buffer, "%s  [i=%d]-->[Process=%d]-->[Parent=%d]-->[Child=%d]/n",
            "===Child  ",i,getpid(),getppid(),childpid);   
        }else
        {
            sprintf(buffer, "%s  [i=%d]-->[Process=%d]-->[Parent=%d]-->[Child=%d]/n",
            "===Para   ",i,getpid(),getppid(),childpid);   
        }
       
     }
    c=buffer;

    /* 这里要求资源,进入原子操作 */
    while(((semop_ret=semop(semid,&semwait,1))==-1)&&(errno==EINTR));
    if(semop_ret==-1)
    {
        fprintf(stderr,"[%d]:Decrement Semaphore Error:%s/n/a",
        getpid(),(char *)strerror(errno));
    }
    else
    {
        while(*c!='/0'){
            if( (ar_Fp = fopen("/home/test.txt", "a+" ) ) == NULL ){
                printf("fopen error/n");
            }
            sprintf(buffer2, "%s",c);
            c=c+strlen(c);
            fputs(buffer2,ar_Fp);
            fclose(ar_Fp);
     }
     
        /* 原子操作完成,赶快释放资源 */
        while(((semop_ret=semop(semid,&semsignal,1))==-1)&&(errno==EINTR));

        if(semop_ret==-1)
        fprintf(stderr,"[%d]:Increment Semaphore Error:%s/n/a",
        getpid(),(char *)strerror(errno));
    }

     /* 不能够在其他进程反问信号灯的时候,我们删除了信号灯 */
    while((wait(&status)==-1)&&(errno==EINTR));
        /* 信号灯只能够被删除一次的 */
        if(i==1)
        if(del_semaphore(semid)==-1)
        fprintf(stderr,"[%d]:Destroy Semaphore Error:%s/n/a",
        getpid(),(char *)strerror(errno));
        exit(0);
}

执行后文件的结果。
$ cat test.txt
===Child    [i=1]-->[Process=11823]-->[Parent=11822]-->[Child=0]
===Child    [i=1]-->[Process=11824]-->[Parent=11821]-->[Child=0]
===Para     [i=1]-->[Process=11822]-->[Parent=11821]-->[Child=11823]
===Para     [i=1]-->[Process=11821]-->[Parent=7646]-->[Child=11824]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值