利用信号量semaphore实现两个进程读写同步 Linux C
这篇帖子主要是记录一下自己使用信号量遇到的坑。
首先是需求:创建两个进程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
由此实现了同步读写:

-----------------------------------------------------------------------------
该文章为原创,转载请注明出处。
-----------------------------------------------------------------------------
利用信号量semaphore实现两个进程读写同步 Linux C的更多相关文章
- linux下的进程通信之信号量semaphore
概念: IPC 信号量和内核信号量非常相似,是内核信号量的用户态版本. 优点:每个IPC信号量可以保护一个或者多个信号量值的集合,而不像内核信号量一样只有一个值,这意味着同一个IPC资源可以保护多个独 ...
- linux内核剖析(十)进程间通信之-信号量semaphore
信号量 什么是信号量 信号量的使用主要是用来保护共享资源,使得资源在一个时刻只有一个进程(线程)所拥有. 信号量的值为正的时候,说明它空闲.所测试的线程可以锁定而使用它.若为0,说明它被占用,测试的线 ...
- GIL与普通互斥锁区别,死锁现象,信号量,event事件,进程池与线程池,协程
GIL与普通互斥锁区别 GIL锁和互斥锁的异同点 相同: 都是为了解决解释器中多个线程资源竞争的问题 异: 1.互斥锁是Python代码层面的锁,解决Python程序中多线程共享资源的问题(线程数据共 ...
- 并发编程~~~多线程~~~守护线程, 互斥锁, 死锁现象与递归锁, 信号量 (Semaphore), GIL全局解释器锁
一 守护线程 from threading import Thread import time def foo(): print(123) time.sleep(1) print('end123') ...
- Java基础教程:多线程基础(6)——信号量(Semaphore)
Java基础教程:多线程基础(6)——信号量(Semaphore) 信号量 信号量(Semaphore)由一个值和一个指针组成,指针指向等待该信号量的进程.信号量的值表示相应资源的使用情况.信号量S≥ ...
- linux信号量之进程间同步
概念 linux信号量: 允许多个线程同时进入临界区,可以用于进程间的同步. 和互斥锁(mutex)的区别: 互斥锁只允许一个线程进入临界区. 所在头文件: semaphore.h 主要函数 初始化函 ...
- 信号量 Semaphore
一.简介 信号量(Semaphore),有时被称为信号灯,是在多线程环境下使用,负责协调各个线程, 以保证它们能够正确.合理的使用公共资源. Semaphore可以控制某个资源可被同时 ...
- java笔记--对信号量Semaphore的理解与运用
java Semaphore 信号量的使用: 在java中,提供了信号量Semaphore的支持. Semaphore类是一个计数信号量,必须由获取它的线程释放, 通常用于限制可以访问某些资源(物理或 ...
- python 守护进程、同步锁、信号量、事件、进程通信Queue
一.守护进程 1.主进程创建守护进程 其一:守护进程会在主进程代码执行结束后就终止 其二:守护进程内无法再开启子进程,否则抛出异常:AssertionError: daemonic processes ...
随机推荐
- JAVA之G1垃圾回收器
概述 G1 GC,全称Garbage-First Garbage Collector,通过-XX:+UseG1GC参数来启用,作为体验版随着JDK 6u14版本面世,在JDK 7u4版本发行时被正式推 ...
- docker的安装以及使用命令
docker的安装 安装docker https://docs.docker.com/install/linux/docker-ce/centos/#set-up-the-repository 从 2 ...
- Flink 非对齐Unaligned的checkpoint(源码分析)
本文源码基于flink1.14 在帮助用户排查任务的时候,经常会发现部分task处理的慢,在Exactly once语义时需要等待快照的对齐而白白柱塞的情况 在flink1.11版本引入了非对齐的ch ...
- postman设置token等关联参数
登陆时登录成功后服务器会返回一个token,这个token作为第二步骤的入参:第二个步骤请求成功后服务器会返回一个新token,然后这个token作为第三步骤的入参!如此一来的话,要用postman做 ...
- 《剑指offer》面试题25. 合并两个排序的链表
问题描述 输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是递增排序的. 示例1: 输入:1->2->4, 1->3->4 输出:1->1->2-> ...
- [STM32F10x] 利用定时器测量频率
硬件:STM32F103C8T6 平台:ARM-MDk V5.11 原理 利用STM32F10x的定时器的捕获(Capture)单元测量输入信号的频率. 基本原理是通过两次捕获达到的计数器的差值,来计 ...
- 【刷题-LeetCode】228. Summary Ranges
Summary Ranges Given a sorted integer array without duplicates, return the summary of its ranges. Ex ...
- ☕【Java深层系列】「并发编程系列」让我们一起探索一下CyclicBarrier的技术原理和源码分析
CyclicBarrier和CountDownLatch CyclicBarrier和CountDownLatch 都位于java.util.concurrent这个包下,其工作原理的核心要点: Cy ...
- MySQL技术内幕(一)
MySQL技术内幕 2. InnoDB存储引擎 2.1 InnoDB存储引擎概述 特点:行锁设计.支持MVCC.支持外键.提供一致性非锁定读 2.2 InnoDB体系架构 2.2.1 后台线程 Inn ...
- ApacheCN Vue 译文集 20211115 更新
使用 GraphQL 构建 VueJS 应用 零.前言 一.数据绑定.事件和计算属性 二.组件.混合器和功能组件 三.设置我们的聊天应用--AWS Amplify 环境和 GraphQL 四.创建自定 ...