共享内存

共享内存主要用于实现进程间大量数据传输。

共享内存的数据结构定义:

系统对共享内存的限制:

共享内存与管道的对比:

可以看到,共享内存的优势:

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相关推荐

  1. linux 进程通信比较,浅析Linux进程通信的几种方式及其比较

    摘要:本文通过对Linux下几种主要通信方式进行概述,并结合Linux系统的系统调用对OS中的实现进行简要概述,并对其优缺点进行分析,阐述了在不同通信情况下应该选择何种通信方式进行选择. 关键词:Li ...

  2. linux进程通信发送方式,Linux服务器编程——Linux系统编程之进程通信

    进程通信又称IPC IPC方法 方法:管道(最简单) 信号(开销最小) 共享映射区/共享内存(无血缘关系) 本地套接字(最稳定) Linux文件类型: -   文件 d  目录 l   符号链接 s  ...

  3. linux进程通信核心态时间,Linux进程管理简谈

    Linux系统进程管理简谈 进程是什么? 进程是对处理器.主存和I/O设备的抽象表示. 进程是操作系统对一个正在运行的程序的一种抽象,在一个系统上可以同时运行多个进程,而每个进程都好像在独占的使用硬件 ...

  4. Linux进程通信的四种方式——共享内存、信号量、无名管道、消息队列|实验、代码、分析、总结

    Linux进程通信的四种方式--共享内存.信号量.无名管道.消息队列|实验.代码.分析.总结 每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须 ...

  5. linux 进程通信机制,LINUX内核进程高效通信机制研究

    摘要:进程间的通信是多任务.多用户操作系统必须考虑的重大问题,Linux继承了Unix的基本设计思想,其安全性和稳定性得到了人们的认可,但随着其应用领域的不断拓展,其通信机制已经不能满足用户的需求.本 ...

  6. 操作系统实验·Linux进程通信与内存管理

    预备知识 Linux进程的数据结构 在Linux中,进程用task_struct表示,所有进程被组织到以init_task为表头的双向链表中(见[include/linux/sched.h]SET_L ...

  7. linux进程管道通信缺点,Linux进程通信(IPC)的方式详解

    前言:Linux进程通信的方式 什么是进程通信?进程通信是指进程之间交换信息 进程通信方式共有6种: 管道(pipe),包括流管道(s_pipe)和有名管道(named pipe) 信号(signal ...

  8. Linux进程通信的试验

    1.实验目的 1.1了解Linux进程通信的概念. 1.2 掌握Linux进程通信的常用方法. 2.实验内容 创建admin用户,密码也是admin. 用admin登陆后,创建src目录,所有的源代码 ...

  9. Linux进程通信——匿名管道、命名管道、管道的特性和共享内存

    Linux进程通信--匿名管道.命名管道.管道的特性和共享内存 一.管道 1.1 什么是管道? 1.2 匿名管道 <1> 匿名管道参数说明 <2> fork共享管道原理 < ...

  10. 【操作系统实验】Linux进程通信—共享内存通信、管道通信

    Linux进程通信-共享内存通信.管道通信 一.实验目的: 二.实验题目: 1. 试设计程序利用共享内存完成如下进程通信 1.shmget函数 2.shmat函数 3.shmdt函数 4.shmctl ...

最新文章

  1. 2.2元组介绍+字符串操作
  2. javascript知识点
  3. inline-block在ie6中的经典bug
  4. HTML(三):表单元素
  5. 【计算机网络】网络层 : IP 组播 ( IP 数据报传输方式 | 组播 IP 地址 | 组播 MAC 地址 | IGMP 协议 | 组播路由选择协议 )
  6. 非标自动化企业前十名_非标设备的现状
  7. python爬虫 -- 正则表达式 与 Re模块的介绍
  8. Mysql水平分表-后端代码
  9. spring异常 java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderServlet
  10. http强缓存在firefox和chrome之间的差异
  11. c语言占用cpu的程序,Windows下用C语言获取进程cpu使用率,内存使用,IO情况
  12. 【C/C++】符号常量 常变量
  13. 计算机考苏州公务员考试,苏州公务员考试难度
  14. 面试失败总结,这 577 道 LeetCode 题 Java 版答案你值得拥有
  15. VS2005透过SourceOffSite访问VSS2005的设置方法
  16. python re模块下载_python re模块
  17. java删除某些段落word_Java 批量删除Word中的空白段落
  18. 黑苹果10.15.7使用
  19. 解决微信大字体下H5布局混乱
  20. Java 开发中遇到的印象深刻的问题

热门文章

  1. redis-cli批量删除时的坑
  2. secuteCRT的使用
  3. VS2012 ffmpeg 没有定义的lrint
  4. atime、ctime 和 mtime区别
  5. 献给1975-1985年出生的人们!!!!
  6. ZeroForums论坛正式开始测试运行
  7. 【主席树】bzoj1112: [POI2008]砖块Klo
  8. ThinkPHP5.0源码学习之框架启动流程
  9. C# A potentially dangerous 问题解决
  10. [python] ZZ 随机数生成