关于信号量和共享内存的相关描述已经在前几篇提到过;

  • 信号量:即内核维护的一个正整数,可以使用内核提供的p/v接口进行该正整数的+/-操作,它主要用来表示系统中可用资源的个数,协调各个进程有序访问资源,防止发生冲突
  • 共享内存:操作系统从运行中的进程拥有的3G用户空间中提供一段用户态可以直接访问的内存块,并且该内存区域可以被其他进程共享

信号量在共享内存中的使用基本流程如下图:


两个信号量,一个用于控制读端进程对共享内存的访问,一个用于控制写端进程对共享内存的访问
当写端进程写入时,写信号量sem1 进程p操作,读信号量sem0进行v操作
当读端进程写入时,读信号量sem0进行p操作,写信号量sem1进程v操作

以下代码通过信号量实现了每次仅有一个进程操作共享内存
写端sem_write.c

#include<stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/types.h>union semnum {int val;struct semid_ds *buf;unsigned short int *array;struct seminfo *__buf;
};
int sem_id;//初始化信号量
void sem_init(int sem_id, int nsignum, int sem_value) {union semnum sem_union;sem_union.val = sem_value;if (semctl(sem_id,nsignum,SETVAL,sem_union) == -1) {printf("semctl failed\n");_exit(-1);}
}//对信号量进行p操作 -1
void sem_p(int sem_id, int nsignum) {struct sembuf sops;sops.sem_num = nsignum;sops.sem_op = -1;sops.sem_flg = SEM_UNDO;if (semop(sem_id, &sops,1) == -1) {printf("semop P failed \n");_exit(-1);}}
//对信号量进行v操作 +1
void sem_v(int sem_id, int nsignum) {struct sembuf sops;sops.sem_num = nsignum;sops.sem_op = 1;sops.sem_flg = SEM_UNDO;if (semop(sem_id, &sops,1) == -1) {printf("semop P failed \n");_exit(-1);}
}//打印信号量
void sem_print(int sem_id, int nsignum) {int sem_value;sem_value = semctl(sem_id, nsignum, GETVAL);printf("sem[%d] = %d \n",nsignum, sem_value);
}int main() {int shm_id;key_t shm_key = ftok("./",111);key_t sem_key = ftok("./",112);//创建共享内存,并将共享内存进行映射,获取映射后的共享内存地址shm_id = shmget(shm_key , 1028 , IPC_CREAT | 0666);char *shm_addr = shmat(shm_id, NULL , 0);sem_id = semget(sem_key,2,IPC_CREAT | 0666);//创建两个信号量if(sem_id == -1) {sem_id = semget(sem_key, 2 ,0666);}else {sem_init(sem_id,0,0); //初始化读端信号量sem_init(sem_id,1,1); //初始化写端信号量}while(1) {sem_p(sem_id,1); //由于接下来要写入共享内存,则对写端信号量进行p操作,-1fgets(shm_addr,1020,stdin);sem_v(sem_id,0);//由于读进程在阻塞读,则写完之后立即将读信号量进行v操作}return 0;
}

读端sem_read.c

#include<stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/types.h>union semnum {int val;struct semid_ds *buf;unsigned short int *array;struct seminfo *__buf;
};
int sem_id;void sem_init(int sem_id, int nsignum, int sem_value) {union semnum sem_union;sem_union.val = sem_value;if (semctl(sem_id,nsignum,SETVAL,sem_union) == -1) {printf("semctl failed\n");_exit(-1);}
}void sem_p(int sem_id, int nsignum) {struct sembuf sops;sops.sem_num = nsignum;sops.sem_op = -1;sops.sem_flg = SEM_UNDO;if (semop(sem_id, &sops,1) == -1) {printf("semop P failed \n");_exit(-1);}}void sem_v(int sem_id, int nsignum) {struct sembuf sops;sops.sem_num = nsignum;sops.sem_op = 1;sops.sem_flg = SEM_UNDO;if (semop(sem_id, &sops,1) == -1) {printf("semop P failed \n");_exit(-1);}
}void sem_print(int sem_id, int nsignum) {int sem_value;sem_value = semctl(sem_id, nsignum, GETVAL);printf("sem[%d] = %d \n",nsignum, sem_value);
}int main() {int shm_id;key_t shm_key = ftok("./",111);key_t sem_key = ftok("./",112);shm_id = shmget(shm_key , 1028 , IPC_CREAT | 0666);char *shm_addr = shmat(shm_id, NULL , 0);sem_id = semget(sem_key,2,IPC_CREAT | 0666);if(sem_id == -1) {printf("semget failed\n");_exit(-1);}else {sem_init(sem_id,0,0); //初始化读端信号量sem_init(sem_id,1,1); //初始化写端信号量}while(1) {//对读端信号量进行p操作,-1,接下来要从共享内存读sem_p(sem_id,0);printf("from shm:%s\n",shm_addr);//读完之后将写端信号量进行v操作,+1,因为还有写端进程需要写入(p操作),防止信号量变为-1sem_v(sem_id,1);}return 0;
}

输入如下:

linux进程间通信:system V 信号量和共享内存实现进程间同步相关推荐

  1. 五十、进程间通信——System V IPC 之共享内存

    50.1 共享内存 50.1.1 共享内存的概念 共享内存区域是被多个进程共享的一部分物理内存 多个进程都可把该共享内存映射到自己的虚拟内存空间.所有用户空间的进程若要操作共享内存,都要将其映射到自己 ...

  2. QSharedMemory共享内存实现进程间通讯(IPC)及禁止程序多开

    版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:QSharedMemory共享内存实现进程间通讯(IPC)及禁止程序多开     本文地址:h ...

  3. 【Linux】进程间通信 —— 匿名管道 | 命名管道 | System V | 消息队列 | 共享内存

    进程间通信 0. 进程间通信 1. 管道 1.1 匿名管道 1.1.1 匿名管道原理 1.1.2 创建匿名管道pipe 1.1.3 基于匿名管道通信的4种情况5个特点 1.2 命名管道 1.2.1 创 ...

  4. Linux进程间通信源码剖析,共享内存(shmget函数详解)

    转至:http://blog.csdn.net/lanmanck/article/details/6092995 shmget int shmget(key_t key, size_t size, i ...

  5. System V IPC之共享内存

    共享内存是一种最为高效的进程间通信方式,进程可以直接读写内存, 而不需要任何数据的拷贝 共享内存在内核空间创建, 可以被进程映射到用户空间访问 由于多个进程可同时访问共享内存 , 因此需要同步和互斥机 ...

  6. Windows上C++使用共享内存进行进程间通讯

    共享内存 (也叫内存映射文件) 主要是通过映射机制实现的 , Windows 下进程的地址空间在逻辑上是相互隔离的 , 但在物理上却是重叠的 ; 所谓的重叠是指同一块内存区域可能被多个进程同时使用 , ...

  7. 共享内存实现进程间大数据的交换

    引言 进程间的数据交换和共享是一种非常重要和实用的技术.大.中型软件的开发设计多是由众多程序设计人员的合作完成,通常一个程序设计人员只负责其中一个或几个模块的开发,这些模块可以是动态链接库也可以是应用 ...

  8. Linux系统中消息队列,共享内存、信号和线程的基本操作使用方法

    Linux系统中消息队列,共享内存.信号和线程高级操作 第十一章 消息队列 10.1消息队列定义 10.2 消息队列特点 10.3 key值 10.4 创建消息队列 10.4.1 发送消息 10.4. ...

  9. linux使用共享内存进行进程通信

    一.什么是共享内存 共享内存就是允许两个不相关的进程访问同一个逻辑内存.共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式.不同进程之间共享的内存通常为同一段物理内存.使用共享内存进 ...

最新文章

  1. TP-LINK、迅捷等品牌路由器存在质量问题
  2. debian php redis,debian7.7环境下 源码安装redis以及phpredis扩展
  3. linux下载哪个python版本-修改linux下python的默认版本
  4. 多看看 leetcode 128. 最长连续序列
  5. 2015 年你在科研上有哪些值得分享的进展和感悟?
  6. docker(三) 制作自己的镜像
  7. 军职在线c语言程序设计答案,2018事业单位联考职测C真题与答案解析.docx
  8. 30 FI配置-财务会计-外币评估-准备外币评估的自动过账
  9. vue 常见错的可能原因
  10. mysql 8.0 java连接报错:Unknown system variable 'query_cache_size'
  11. 直播预告:WLS/WAS故障基本分析介绍
  12. 区块链研习 | 区块链的能力很大又很小
  13. 林肯android auto,林肯mkz仪表盘怎么设置中文
  14. linux下文本文件转换编码格式的方法
  15. javascrip对表格的操作(三)
  16. nginx防盗链功能
  17. 【图像算法】七种常见阈值分割代码(Otsu、最大熵、迭代法、自适应阀值、手动、迭代法、基本全局阈值法)...
  18. iOS开发之UILabel的使用
  19. python设计棋牌游戏
  20. 达芬奇--艺工结合先驱

热门文章

  1. Android 知识杂记(MVP模式)
  2. os.system() 和 os.popen()
  3. java为什么序列化不一致_java – 为什么Jackson多态序列化在列表中不起作用?
  4. android7.0图标反馈,android7.0 webview中 图标错位
  5. sources root pycharm 怎么设置_使用python语言开发ROOT之搭建环境方法探索
  6. php ajax formdata 进度,使用formdata使用ajax将数据发送到PHP
  7. ubuntu装java环境_Ubuntu安装Java环境
  8. mysql新建表96k_innodb表 手工导入导出
  9. java增加final,Java8增加功能--Effectively final 功能
  10. php7 数组与字符串,第7天 PHP字符串、数组