linux进程通信system v,【linux高级程序设计】(第十一章)System V进程间通信 4
共享内存
共享内存主要用于实现进程间大量数据传输。
共享内存的数据结构定义:
系统对共享内存的限制:
共享内存与管道的对比:
可以看到,共享内存的优势:
1.共享内存只需复制2次,而管道需要4次
2.共享内存不需要切换内核态与用户态,而管道需要。
共享内存效率高!
int shmget (key_t __key, size_t __size, int __shmflg) :创建共享内存
第一个参数:key值
第二个参数:欲创建的共享内存段的大小(字节)
第三个参数:shmflg创建标识,包括IPC_CREAT, IPC_EXCL, IPC_NOWAIT, SHM_R(可读), SHM_W(可写)
int shmctl (int __shmid, int __cmd, struct shmid_ds *__buf) :共享内存控制
第一个参数:要操作的共享内存标识符
第二个参数:要执行的操作,IPC_RMID, iPC_SET, IPC_STAT, IPC_INFO, 超级用户还有 SHM_LOCK(锁定共享内存段), SHM_UNLOCK(解锁共享内存段)
第三个参数:临时共享内存变量信息
void *shmat (int __shmid, __const void * __shmaddr, int __shmflg) : 挂载共享内存到当前进程,返回共享内存首地址
第一个参数:要操作的共享内存标识符
第二个参数:指定共享内存映射地址,如果是0,系统选择。
第三个参数:指定共享内存段的访问权限和映射条件,0表示可读可写
int shmdt (__const void *__shmaddr) :把共享内存与当前进程分离,参数为共享内存映射地址
测试,在只读共享内存中写信息:
#include#include#include#include#include#include#include
int main(int argc, char *argv[])
{
key_t key;intshm_id;char *ptr;
key= ftok("/", 10);
shm_id= shmget(key, 100, IPC_CREAT|SHM_R); //创建shm
printf("get the shm id is %d", shm_id); //打印id
if((ptr = (char *)shmat(shm_id, NULL, SHM_RDONLY)) == NULL) //只读方式挂载
{if(shmctl(shm_id, IPC_RMID, NULL) == -1) //如果失败则删除
perror("Failed to remove memory segment");
exit(EXIT_FAILURE);
}//打印挂载地址
printf("the attach add is %p", ptr);
printf("now try to write the memory");*ptr = 'd';
printf("*ptr =%c", *ptr);
shmdt(ptr);
shmctl(shm_id, IPC_RMID,0);
}
发生段错误:
父子进程间对共享内存的约定:
fork()的子进程继承父进程挂载的共享内存。
调用exec执行新程序,则共享内存被自动卸载。
如果调用了exit(),挂载的共享内存与当前进程脱离关系。
下面是一个应用的例子
实现两个没有亲缘关系进程的通信,一个负责写,另一个负责接收。用信号量实现同步,即写的时候不可读,读的时候不可写。用一元信号量实现,0表示可写,1表示可读
注意:在代码实现中,实际上是读写轮流操作的,即写一次,读一次。并没有达到真正多进程的效果。
代码经验证,可以使用
发送端代码:
#include#include#include#include#include#include#include#include#include
int main(int argc, char *argv[])
{int running = 1;intshid;intsemid;intvalue;void *sharem =NULL;structsembuf sem_b;
sem_b.sem_num= 0;
sem_b.sem_flg=SEM_UNDO;//创建信号量
if((semid = semget((key_t)123456, 1, 0666|IPC_CREAT)) == -1)
{
perror("semget");
exit(EXIT_FAILURE);
}//初始化信号量为0
if(semctl(semid,0,SETVAL,0) == -1)
{
printf("sem init error");if(semctl(semid, 0, IPC_RMID, 0) != 0)
{
perror("semctl");
exit(EXIT_FAILURE);
}
exit(EXIT_FAILURE);
}//创建共享内存
shid = shmget((key_t)654321, (size_t)2048, 0600|IPC_CREAT); //创建共享内存
if(shid == -1)
{
perror("shmget");
exit(EXIT_FAILURE);
}//挂载共享内存到当前进程
sharem = shmat(shid, NULL, 0);if(sharem ==NULL)
{
perror("shmat");
exit(EXIT_FAILURE);
}while(running)
{//测试信号量值,如果为0则可写
if((value = semctl(semid, 0, GETVAL)) == 0)
{
printf("write data operate");
printf("please input something:");
scanf("%s", sharem);
sem_b.sem_op= 1;//执行信号量加1操作,允许读
if(semop(semid, &sem_b, 1) == -1)
{
fprintf(stderr,"semaphore_p failed");
exit(EXIT_FAILURE);
}
}//比较是否是结束符号
if(strcmp(sharem, "end") == 0)
running--;
}
shmdt(sharem);return 0;
}
接收端代码:
#include#include#include#include#include#include#include#include#include
int main(int argc, char *argv[])
{int running = 1;intshid;intsemid;intvalue;void *sharem =NULL;structsembuf sem_b;
sem_b.sem_num= 0;
sem_b.sem_flg=SEM_UNDO;//创建信号量
if((semid = semget((key_t)123456, 1, 0666|IPC_CREAT)) == -1)
{
perror("semget");
exit(EXIT_FAILURE);
}//创建共享内存
shid = shmget((key_t)654321, (size_t)2048, 0600|IPC_CREAT); //创建共享内存
if(shid == -1)
{
perror("shmget");
exit(EXIT_FAILURE);
}//挂载共享内存到当前进程
sharem = shmat(shid, NULL, 0);if(sharem ==NULL)
{
perror("shmat");
exit(EXIT_FAILURE);
}while(running)
{//测试信号量值,如果为1则可读
if((value = semctl(semid, 0, GETVAL)) == 1)
{
printf("read data operate");
sem_b.sem_op= -1;//执行信号量减1操作,允许写
if(semop(semid, &sem_b, 1) == -1)
{
fprintf(stderr,"semaphore_p failed");
exit(EXIT_FAILURE);
}
printf("%s", sharem);
}//比较是否是结束符号
if(strcmp(sharem, "end") == 0)
running--;
}
shmdt(sharem);//删除共享内存
if(shmctl(shid, IPC_RMID, 0) != 0)
{
perror("shmctl");
exit(EXIT_FAILURE);
}//删除信号量
if(semctl(semid, 0, IPC_RMID, 0) != 0)
{
perror("semctl");
exit(EXIT_FAILURE);
}return 0;
}
linux进程通信system v,【linux高级程序设计】(第十一章)System V进程间通信 4相关推荐
- linux 进程通信比较,浅析Linux进程通信的几种方式及其比较
摘要:本文通过对Linux下几种主要通信方式进行概述,并结合Linux系统的系统调用对OS中的实现进行简要概述,并对其优缺点进行分析,阐述了在不同通信情况下应该选择何种通信方式进行选择. 关键词:Li ...
- linux进程通信发送方式,Linux服务器编程——Linux系统编程之进程通信
进程通信又称IPC IPC方法 方法:管道(最简单) 信号(开销最小) 共享映射区/共享内存(无血缘关系) 本地套接字(最稳定) Linux文件类型: - 文件 d 目录 l 符号链接 s ...
- linux进程通信核心态时间,Linux进程管理简谈
Linux系统进程管理简谈 进程是什么? 进程是对处理器.主存和I/O设备的抽象表示. 进程是操作系统对一个正在运行的程序的一种抽象,在一个系统上可以同时运行多个进程,而每个进程都好像在独占的使用硬件 ...
- Linux进程通信的四种方式——共享内存、信号量、无名管道、消息队列|实验、代码、分析、总结
Linux进程通信的四种方式--共享内存.信号量.无名管道.消息队列|实验.代码.分析.总结 每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须 ...
- linux 进程通信机制,LINUX内核进程高效通信机制研究
摘要:进程间的通信是多任务.多用户操作系统必须考虑的重大问题,Linux继承了Unix的基本设计思想,其安全性和稳定性得到了人们的认可,但随着其应用领域的不断拓展,其通信机制已经不能满足用户的需求.本 ...
- 操作系统实验·Linux进程通信与内存管理
预备知识 Linux进程的数据结构 在Linux中,进程用task_struct表示,所有进程被组织到以init_task为表头的双向链表中(见[include/linux/sched.h]SET_L ...
- linux进程管道通信缺点,Linux进程通信(IPC)的方式详解
前言:Linux进程通信的方式 什么是进程通信?进程通信是指进程之间交换信息 进程通信方式共有6种: 管道(pipe),包括流管道(s_pipe)和有名管道(named pipe) 信号(signal ...
- Linux进程通信的试验
1.实验目的 1.1了解Linux进程通信的概念. 1.2 掌握Linux进程通信的常用方法. 2.实验内容 创建admin用户,密码也是admin. 用admin登陆后,创建src目录,所有的源代码 ...
- Linux进程通信——匿名管道、命名管道、管道的特性和共享内存
Linux进程通信--匿名管道.命名管道.管道的特性和共享内存 一.管道 1.1 什么是管道? 1.2 匿名管道 <1> 匿名管道参数说明 <2> fork共享管道原理 < ...
- 【操作系统实验】Linux进程通信—共享内存通信、管道通信
Linux进程通信-共享内存通信.管道通信 一.实验目的: 二.实验题目: 1. 试设计程序利用共享内存完成如下进程通信 1.shmget函数 2.shmat函数 3.shmdt函数 4.shmctl ...
最新文章
- 2.2元组介绍+字符串操作
- javascript知识点
- inline-block在ie6中的经典bug
- HTML(三):表单元素
- 【计算机网络】网络层 : IP 组播 ( IP 数据报传输方式 | 组播 IP 地址 | 组播 MAC 地址 | IGMP 协议 | 组播路由选择协议 )
- 非标自动化企业前十名_非标设备的现状
- python爬虫 -- 正则表达式 与 Re模块的介绍
- Mysql水平分表-后端代码
- spring异常 java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderServlet
- http强缓存在firefox和chrome之间的差异
- c语言占用cpu的程序,Windows下用C语言获取进程cpu使用率,内存使用,IO情况
- 【C/C++】符号常量 常变量
- 计算机考苏州公务员考试,苏州公务员考试难度
- 面试失败总结,这 577 道 LeetCode 题 Java 版答案你值得拥有
- VS2005透过SourceOffSite访问VSS2005的设置方法
- python re模块下载_python re模块
- java删除某些段落word_Java 批量删除Word中的空白段落
- 黑苹果10.15.7使用
- 解决微信大字体下H5布局混乱
- Java 开发中遇到的印象深刻的问题