如何通过Linux C中使用信号量semaphore实现两个进程的读写同步?

2026-05-25 12:571阅读0评论SEO问题
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计926个文字,预计阅读时间需要4分钟。

如何通过Linux C中使用信号量semaphore实现两个进程的读写同步?

这篇帖子主要记录了自己在使用信号量时遇到的困境。首先,需求是创建两个进程A和B。A进程向buffer中写,B进程从buffer中读。两个进程通过命名管道进行通信,并实现读写同步。具体来说,A进程写完内容后通知B进程读取,B进程读取完成后通知A进程继续写入。

这篇帖子主要是记录一下自己使用信号量遇到的坑。

首先是需求:创建两个进程A,B。A往buffer中写,B读。两个进程利用命名管道进行通信,并实现读写同步。即A写完后通知B读,B读完后通知A写。

如果A,B两个进程各自独立操作的话,很容易出现下列情况。 看哪个进程先抢占到这个buffer,由于write和read这个buffer都会阻塞另一个进程,所以可能会出现一个进程一直写数据,然后读进程会读到多条数据。

解决方案,利用linux POSIX中的semaphore完成读写同步。设置两个信号量semwr,semrd;semwr控制读,初始化值设置为1(in unlocked state),semrd控制写,初始化设置为0(in locked state)。并由读进程释放写锁,由写进程释放读锁。(一个信号量是无法完成读写同步的)。

读进程:

#include <fcntl.h> #include <sys/stat.h> #include <semaphore.h> #include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <errno.h> #include <string.h> #define MAXLINE 100 #define CONTEXT "HELLO WORLD" #define FILENAME "MY_FIFO" #define LOOP 200 #define SEMRD "sem_read" #define SEMWR "sem_write" int main(int argc,char *argv[]){ /* create the named pipe fifo*/ int fd; int ret; ret = mkfifo(FILENAME,0666); if(ret!=0){ perror("mkfifo"); } fd=open(FILENAME,O_RDONLY); if(fd<0){ perror("open fifo"); } /*open the semaphore*/ sem_t *semwr,*semrd; int pwr,prd; semwr=sem_open(SEMWR,O_CREAT,0666,1); semrd=sem_open(SEMRD,O_CREAT,0666,0); if(semwr==(void*)-1 ||semrd==(void*)-1){ perror("sem_open failure"); } printf("sem address\n"); printf("semwr=%p\n",semwr); printf("semrd=%p\n",semrd); /*get this value*/ sem_getvalue(semwr,&pwr); sem_getvalue(semrd,&prd); printf("wr value=%d\n",pwr); printf("rd value=%d\n",prd); /* communication period*/ int i=LOOP; while (i--){ /*lock*/ sem_wait(semrd); char recv[MAXLINE]={0}; read(fd,recv,sizeof(recv)); printf("read from my_fifo buf=[%s]\n",recv); sem_post(semwr); } /*close the file*/ close(fd); sem_close(semwr); sem_close(semrd); /* release resource*/ unlink(FILENAME); sem_unlink(SEMWR); sem_unlink(SEMRD); return 0; }

写进程:

#include <fcntl.h> #include <sys/stat.h> #include <semaphore.h> #include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <errno.h> #include <string.h> #define MAXLINE 100 #define CONTEXT "HELLO WORLD" #define FILENAME "MY_FIFO" #define LOOP 200 #define SEMRD "sem_read" #define SEMWR "sem_write" int main(int argc,char *argv[]){ /* create the named pipe fifo*/ int fd; int ret; ret = mkfifo(FILENAME,0666); if(ret!=0){ perror("mkfifo"); } fd=open(FILENAME,O_WRONLY); if(fd<0){ perror("open fifo"); } /*open the semaphore*/ sem_t *semwr,*semrd; int pwr,prd; semwr=sem_open(SEMWR,O_CREAT,0666,1); semrd=sem_open(SEMRD,O_CREAT,0666,0); if(semwr==(void*)-1 ||semrd==(void*)-1){ perror("sem_open failure"); } printf("sem address\n"); printf("semwr=%p\n",semwr); printf("semrd=%p\n",semrd); /*get this value*/ sem_getvalue(semwr,&pwr); sem_getvalue(semrd,&prd); printf("wr value=%d\n",pwr); printf("rd value=%d\n",prd); /* communication period*/ int i=LOOP; char send[MAXLINE]=CONTEXT; while (i--){ /*lock*/ sem_wait(semwr); write(fd,send,strlen(send)); printf("send to my_fifo buf\n",send); sem_post(semrd); } /*close the file*/ close(fd); sem_close(semwr); sem_close(semrd); /* release resource*/ unlink(FILENAME); sem_unlink(SEMWR); sem_unlink(SEMRD); return 0; }

需要注意的是,POSIX中的信号量是随内核持续的,如果信号量不sem_unlink的话,该命名信号量会常驻在kernel之中,即使进程结束了也会存在,而sem_open创建信号量时,如果该named semaphore存在内核中,你设置的初始化参数是无效的(一定要man 3 sem_open 看看参数的解释,别百度,垃圾文档太多,看官方的最好),所以用完之后需要统一释放资源。

gcc 编译的时候需要加上 -pthread

gcc XXXX.c -pthread -o xxx

由此实现了同步读写:

-----------------------------------------------------------------------------

该文章为原创,转载请注明出处。

-----------------------------------------------------------------------------

如何通过Linux C中使用信号量semaphore实现两个进程的读写同步?

本文共计926个文字,预计阅读时间需要4分钟。

如何通过Linux C中使用信号量semaphore实现两个进程的读写同步?

这篇帖子主要记录了自己在使用信号量时遇到的困境。首先,需求是创建两个进程A和B。A进程向buffer中写,B进程从buffer中读。两个进程通过命名管道进行通信,并实现读写同步。具体来说,A进程写完内容后通知B进程读取,B进程读取完成后通知A进程继续写入。

这篇帖子主要是记录一下自己使用信号量遇到的坑。

首先是需求:创建两个进程A,B。A往buffer中写,B读。两个进程利用命名管道进行通信,并实现读写同步。即A写完后通知B读,B读完后通知A写。

如果A,B两个进程各自独立操作的话,很容易出现下列情况。 看哪个进程先抢占到这个buffer,由于write和read这个buffer都会阻塞另一个进程,所以可能会出现一个进程一直写数据,然后读进程会读到多条数据。

解决方案,利用linux POSIX中的semaphore完成读写同步。设置两个信号量semwr,semrd;semwr控制读,初始化值设置为1(in unlocked state),semrd控制写,初始化设置为0(in locked state)。并由读进程释放写锁,由写进程释放读锁。(一个信号量是无法完成读写同步的)。

读进程:

#include <fcntl.h> #include <sys/stat.h> #include <semaphore.h> #include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <errno.h> #include <string.h> #define MAXLINE 100 #define CONTEXT "HELLO WORLD" #define FILENAME "MY_FIFO" #define LOOP 200 #define SEMRD "sem_read" #define SEMWR "sem_write" int main(int argc,char *argv[]){ /* create the named pipe fifo*/ int fd; int ret; ret = mkfifo(FILENAME,0666); if(ret!=0){ perror("mkfifo"); } fd=open(FILENAME,O_RDONLY); if(fd<0){ perror("open fifo"); } /*open the semaphore*/ sem_t *semwr,*semrd; int pwr,prd; semwr=sem_open(SEMWR,O_CREAT,0666,1); semrd=sem_open(SEMRD,O_CREAT,0666,0); if(semwr==(void*)-1 ||semrd==(void*)-1){ perror("sem_open failure"); } printf("sem address\n"); printf("semwr=%p\n",semwr); printf("semrd=%p\n",semrd); /*get this value*/ sem_getvalue(semwr,&pwr); sem_getvalue(semrd,&prd); printf("wr value=%d\n",pwr); printf("rd value=%d\n",prd); /* communication period*/ int i=LOOP; while (i--){ /*lock*/ sem_wait(semrd); char recv[MAXLINE]={0}; read(fd,recv,sizeof(recv)); printf("read from my_fifo buf=[%s]\n",recv); sem_post(semwr); } /*close the file*/ close(fd); sem_close(semwr); sem_close(semrd); /* release resource*/ unlink(FILENAME); sem_unlink(SEMWR); sem_unlink(SEMRD); return 0; }

写进程:

#include <fcntl.h> #include <sys/stat.h> #include <semaphore.h> #include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <errno.h> #include <string.h> #define MAXLINE 100 #define CONTEXT "HELLO WORLD" #define FILENAME "MY_FIFO" #define LOOP 200 #define SEMRD "sem_read" #define SEMWR "sem_write" int main(int argc,char *argv[]){ /* create the named pipe fifo*/ int fd; int ret; ret = mkfifo(FILENAME,0666); if(ret!=0){ perror("mkfifo"); } fd=open(FILENAME,O_WRONLY); if(fd<0){ perror("open fifo"); } /*open the semaphore*/ sem_t *semwr,*semrd; int pwr,prd; semwr=sem_open(SEMWR,O_CREAT,0666,1); semrd=sem_open(SEMRD,O_CREAT,0666,0); if(semwr==(void*)-1 ||semrd==(void*)-1){ perror("sem_open failure"); } printf("sem address\n"); printf("semwr=%p\n",semwr); printf("semrd=%p\n",semrd); /*get this value*/ sem_getvalue(semwr,&pwr); sem_getvalue(semrd,&prd); printf("wr value=%d\n",pwr); printf("rd value=%d\n",prd); /* communication period*/ int i=LOOP; char send[MAXLINE]=CONTEXT; while (i--){ /*lock*/ sem_wait(semwr); write(fd,send,strlen(send)); printf("send to my_fifo buf\n",send); sem_post(semrd); } /*close the file*/ close(fd); sem_close(semwr); sem_close(semrd); /* release resource*/ unlink(FILENAME); sem_unlink(SEMWR); sem_unlink(SEMRD); return 0; }

需要注意的是,POSIX中的信号量是随内核持续的,如果信号量不sem_unlink的话,该命名信号量会常驻在kernel之中,即使进程结束了也会存在,而sem_open创建信号量时,如果该named semaphore存在内核中,你设置的初始化参数是无效的(一定要man 3 sem_open 看看参数的解释,别百度,垃圾文档太多,看官方的最好),所以用完之后需要统一释放资源。

gcc 编译的时候需要加上 -pthread

gcc XXXX.c -pthread -o xxx

由此实现了同步读写:

-----------------------------------------------------------------------------

该文章为原创,转载请注明出处。

-----------------------------------------------------------------------------

如何通过Linux C中使用信号量semaphore实现两个进程的读写同步?