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

首先是需求:创建两个进程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的更多相关文章

  1. linux下的进程通信之信号量semaphore

    概念: IPC 信号量和内核信号量非常相似,是内核信号量的用户态版本. 优点:每个IPC信号量可以保护一个或者多个信号量值的集合,而不像内核信号量一样只有一个值,这意味着同一个IPC资源可以保护多个独 ...

  2. linux内核剖析(十)进程间通信之-信号量semaphore

    信号量 什么是信号量 信号量的使用主要是用来保护共享资源,使得资源在一个时刻只有一个进程(线程)所拥有. 信号量的值为正的时候,说明它空闲.所测试的线程可以锁定而使用它.若为0,说明它被占用,测试的线 ...

  3. GIL与普通互斥锁区别,死锁现象,信号量,event事件,进程池与线程池,协程

    GIL与普通互斥锁区别 GIL锁和互斥锁的异同点 相同: 都是为了解决解释器中多个线程资源竞争的问题 异: 1.互斥锁是Python代码层面的锁,解决Python程序中多线程共享资源的问题(线程数据共 ...

  4. 并发编程~~~多线程~~~守护线程, 互斥锁, 死锁现象与递归锁, 信号量 (Semaphore), GIL全局解释器锁

    一 守护线程 from threading import Thread import time def foo(): print(123) time.sleep(1) print('end123') ...

  5. Java基础教程:多线程基础(6)——信号量(Semaphore)

    Java基础教程:多线程基础(6)——信号量(Semaphore) 信号量 信号量(Semaphore)由一个值和一个指针组成,指针指向等待该信号量的进程.信号量的值表示相应资源的使用情况.信号量S≥ ...

  6. linux信号量之进程间同步

    概念 linux信号量: 允许多个线程同时进入临界区,可以用于进程间的同步. 和互斥锁(mutex)的区别: 互斥锁只允许一个线程进入临界区. 所在头文件: semaphore.h 主要函数 初始化函 ...

  7. 信号量 Semaphore

    一.简介         信号量(Semaphore),有时被称为信号灯,是在多线程环境下使用,负责协调各个线程, 以保证它们能够正确.合理的使用公共资源. Semaphore可以控制某个资源可被同时 ...

  8. java笔记--对信号量Semaphore的理解与运用

    java Semaphore 信号量的使用: 在java中,提供了信号量Semaphore的支持. Semaphore类是一个计数信号量,必须由获取它的线程释放, 通常用于限制可以访问某些资源(物理或 ...

  9. python 守护进程、同步锁、信号量、事件、进程通信Queue

    一.守护进程 1.主进程创建守护进程 其一:守护进程会在主进程代码执行结束后就终止 其二:守护进程内无法再开启子进程,否则抛出异常:AssertionError: daemonic processes ...

随机推荐

  1. JAVA并发-AQS知识笔记

    概述 AQS是AbstractQueuedSynchronizer的缩写,翻译成中文就是抽象队列同步器,AbstractQueuedSynchronizer这个类也是在java.util.concur ...

  2. XCTF(Web_php_unserialize)

    拿到题目,是个这, 我们来一波代码审计 1 <?php 2 class Demo { 3 private $file = 'index.php'; 4 public function __con ...

  3. 在字节,A/B 实验是这么做的!

    主要为大家介绍了为什么要做 A/B 测试.火山引擎的 A/B 测试系统架构及字节跳动内部 A/B 测试的最佳实践. 为什么要做 A/B 测试 首先我们看一个案例. 字节跳动有一款中视频产品叫西瓜视频, ...

  4. Go语言测试:testing

    学习参考来源:https://www.liwenzhou.com/posts/Go/16_test/ go test工具 必须导入包: import "testing" go te ...

  5. 前端禁止使用F12、禁止右键

    打开控制台直接跳转页面 //debug调试时跳转页面 var element = new Image(); Object.defineProperty(element,'id',{get:functi ...

  6. PaperRead - A Shader Framework for Rapid Prototyping of GPU-Based Volume Rendering

    PaperRead - A Shader Framework for Rapid Prototyping of GPU-Based Volume Rendering 目录 PaperRead - A ...

  7. linux文件权限全面解析

    目录 linux文件权限全面解析 一:linux文件的权限有哪些? 1,权限分为3个部分 2,权限位 3,每一个权限拥有一个数字编号 4,在添加权限的时候,可以将权限加起来 5,linux添加权限命令 ...

  8. Hexo博客(Snail主题)搭建回顾概览

    Hexo博客(Snail主题)搭建回顾概览 笔者搭建博客地址:https://saltyfishyjk.github.io 目录 Hexo博客(Snail主题)搭建回顾概览 Part 0 前言 写作背 ...

  9. 社交网络分析的 R 基础:(三)向量、矩阵与列表

    在第二章介绍了 R 语言中的基本数据类型,本章会将其组装起来,构成特殊的数据结构,即向量.矩阵与列表.这些数据结构在社交网络分析中极其重要,本质上对图的分析,就是对邻接矩阵的分析,而矩阵又是由若干个向 ...

  10. Tomcat多实例单应用部署方案 (转)

    一.Tomcat部署的场景分析 通常,我们对tomcat部署需求可以分为几种:单实例单应用,单实例多应用,多实例单应用,多实例多应用. 对于第一种场景,如果不要求周期性地维护tomcat版本,一般的做 ...