使用使用信号灯实现互斥机制的文件写操作
#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]