linux进程间通信之System V共享内存详解及代码示例

共享内存是最快最为高效的进程间通信方式,当共享内存映射到共享它的某个进程的地址空间后,进程间的数据传递就不再牵扯到内核,进程可以直接读取内核,不需要通过内核系统调用进行数据拷贝。一般使用情况,从共享内存中写入或读取数据的进程间需要做同步,例如通过信号量,互斥锁去同步。

共享内存有System V 共享内存和Posix共享内存,本文介绍System V 共享内存。
System V共享内存头文件及相关函数原型:
#include <sys/shm.h>

int shmget(key_t key, size_t size, int oflag);
功能:创建一个新的共享内存区,或者访问一个已存在的共享内存区。
返回值:若成功返回共享内存区的标识符,若出错返回-1
参数:key是键值,可以是用ftok生成,也可以用IPC_PRIVATE; size是以字节为单位指定的内存区大小,当创建一个新的共享内存区时,需指定不为0的size值,并且初始化这些size字节为0,当使用一个已存在的共享内存区时,size值需为0; oflag是读写权限,还可以与IPC_CREAT或IPC_CREAT|IPC_EXCL按位或。

void *shmat(int shmid, const void *shmaddr, int flag);
功能:把由shmget创建的共享内存区映射到调用进程的地址空间。
返回值:若成功返回映射区的起始地址,若出错返回-1。
参数:shmid是由shmget返回的标识符;shmaddr是指定地址指针,如果是一个空指针,系统会自动分配地址,这是可移植性最好用法,是推荐用法,如果shmaddr是一个非空指针,返回的映射区地址取决于第三个参数flag是否指定了SHM_RND,如果没有指定SHM_RND,映射地址附接到由 shmaddr参数指定的地址,如果指定了SHM_RND,映射地址附接到由shmaddr参数指定的地址向下舍一个SHMLBA常值;flag默认为0表示可读写,若为SHM_RDONLY表示只读访问。

int shmdt(const void *shmaddr);
功能:关闭这个共享内存区映射,当进程终止时,共享内存映射会自动关闭,但并不是删除,可以通过shmctl函数的IPC_RMID命令删除。
返回值:成功返回0,出错返回-1

int shmctl(int shmid, int cmd, struct shmid_ds *buf);
功能:操作共享内存区
返回值:成功返回0,出错返回-1。
参数: cmd参数有三个命令,IPC_RMID从系统中删除shmid标示的共享内存区,IPC_SET给所指定的共享内存区设置shmid_ds结构的三个成员shm_perm.uid,shm_perm.gid和shm_perm.mode,这三个成员的值来自buf参数指向的结构中的对应成员,IPC_STAT是从共享内存区取出shmid_ds结构并保存在参数buf结构。

一般的编程步骤如下:
1. 创建共享内存:
     通过函数shmget()创建共享内存
2. 映射共享内存:
     通过函数shmget()把创建的共享内存映射到进程
3. 使用共享内存:
4. 撤销共享内存映射
     函数shmdt()
5. 删除共享内存映射:
     函数shmctl()

代码举例shm_test.c: 父进程从终端读取数据放到共享内存,子进程从共享内存读取数据显示到终端

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <sys/types.h>
  5. #include <sys/ipc.h>
  6. #include <sys/shm.h>
  7. #define BUFFER_SIZE 1024
  8. int main() {
  9. pid_t pid;
  10. int shmid;
  11. char *shm_addr;
  12. char flag[]="Parent";
  13. char buff[BUFFER_SIZE];
  14. //    创建当前进程的私有共享内存
  15. if ((shmid=shmget(IPC_PRIVATE,BUFFER_SIZE,0666))<0) {
  16. perror("shmget");
  17. exit(1);
  18. } else
  19. printf("Create shared memory: %d.\n",shmid);
  20. //    ipcs 命令往标准输出写入一些关于活动进程间通信设施的信息
  21. //    -m 表示共享内存
  22. printf("Created shared memory status:\n");
  23. system("ipcs -m");
  24. if((pid=fork())<0) {
  25. perror("fork");
  26. exit(1);
  27. }else if (pid==0) {
  28. //    自动分配共享内存映射地址,为可读可写,映射地址返回给shm_addr
  29. if ((shm_addr=shmat(shmid,0,0))==(void*)-1) {
  30. perror("Child:shmat");
  31. exit(1);
  32. }else
  33. printf("Child: Attach shared-memory: %p.\n",shm_addr);
  34. printf("Child Attach shared memory status:\n");
  35. system("ipcs -m");
  36. //    比较shm_addr,flag的长度为strlen(flag)的字符
  37. //    当其内容相同时,返回0
  38. //    否则返回(str1[n]-str2[n])
  39. while (strncmp(shm_addr,flag,strlen(flag))) {
  40. printf("Child: Waiting for data...\n");
  41. sleep(10);
  42. }
  43. strcpy(buff,shm_addr+strlen(flag));
  44. printf("Child: Shared-memory: %s\n",buff);
  45. //    删除子进程的共享内存映射地址
  46. if (shmdt(shm_addr)<0) {
  47. perror("Child:shmdt");
  48. exit(1);
  49. }else
  50. printf("Child: Deattach shared-memory.\n");
  51. printf("Child Deattach shared memory status:\n");
  52. system("ipcs -m");
  53. }else{
  54. sleep(1);
  55. //    自动分配共享内存映射地址,为可读可写,映射地址返回给shm_addr
  56. if ((shm_addr=shmat(shmid,0,0))==(void*)-1) {
  57. perror("Parent:shmat");
  58. exit(1);
  59. }else
  60. printf("Parent: Attach shared-memory: %p.\n",shm_addr);
  61. printf("Parent Attach shared memory status:\n");
  62. system("ipcs -m");
  63. //    shm_addr为flag+stdin
  64. sleep(1);
  65. printf("\nInput string:\n");
  66. fgets(buff,BUFFER_SIZE-strlen(flag),stdin);
  67. strncpy(shm_addr,flag,strlen(flag));
  68. strncpy(shm_addr+strlen(flag),buff,strlen(buff));
  69. //    删除父进程的共享内存映射地址
  70. if (shmdt(shm_addr)<0) {
  71. perror("Parent:shmdt");
  72. exit(1);
  73. }else
  74. printf("Parent: Deattach shared-memory.\n");
  75. printf("Parent Deattach shared memory status:\n");
  76. system("ipcs -m");
  77. //    保证父进程在删除共享内存前,子进程能读到共享内存的内容
  78. waitpid(pid,NULL,0);
  79. //    删除共享内存
  80. if (shmctl(shmid,IPC_RMID,NULL)==-1) {
  81. perror("shmct:IPC_RMID");
  82. exit(1);
  83. }else
  84. printf("Delete shared-memory.\n");
  85. printf("Child Delete shared memory status:\n");
  86. system("ipcs -m");
  87. printf("Finished!\n");
  88. }
  89. exit(0);
  90. }

复制代码

运行结果:
$ ./a.out
Create shared memory: 65536.
Created shared memory status:

------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status
0x00000000 65536      dongxw     666        2048       0

Child: Attach shared-memory: 0x7fc3519fe000.
Child Attach shared memory status:

------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status
0x00000000 65536      dongxw     666        2048       1

Child: Waiting for data...
Parent: Attach shared-memory: 0x7fc3519fe000.
Parent Attach shared memory status:

------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status
0x00000000 65536      dongxw     666        2048       2

Input string:
Child: Waiting for data...
Child: Waiting for data...
this is data
Parent: Deattach shared-memory.
Parent Deattach shared memory status:

------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status
0x00000000 65536      dongxw     666        2048       1

Child: Shared-memory: this is data

Child: Deattach shared-memory.
Child Deattach shared memory status:

------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status
0x00000000 65536      dongxw     666        2048       0

Delete shared-memory.
Child Delete shared memory status:

------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status

Finished!

可以看到红色标注从终端输入的数据“this is data”, 父进程读取写入共享内存区,子进程从共享内存读取再显示到终端红色标注“Child:Shared-memory:this is data”

原文地址:https://www.cnblogs.com/wudymand/p/9226520.html

时间: 2024-10-10 21:19:49

linux进程间通信之System V共享内存详解及代码示例的相关文章

细说linux IPC(五):system V共享内存

system V共享内存和posix共享内存类似,system V共享内存是调用shmget函数和shamat函数.           shmget函数创建共享内存区,或者访问一个存在的内存区,类似系统调用共享内存的open和posix共享内存shm_open函数.shmget函数原型为: #include <sys/ipc.h> #include <sys/shm.h> int shmget(key_t key, size_t size, int shmflg); key: 函

Linux IPC实践(9) --System V共享内存

共享内存API #include <sys/ipc.h> #include <sys/shm.h> int shmget(key_t key, size_t size, int shmflg); void *shmat(int shmid, const void *shmaddr, int shmflg); int shmdt(const void *shmaddr); int shmctl(int shmid, int cmd, struct shmid_ds *buf); //

阐述linux IPC(五岁以下儿童):system V共享内存

[版权声明:尊重原创.转载请保留源:blog.csdn.net/shallnet 要么 .../gentleliu,文章学习交流,不用于商业用途] system V共享内存和posix共享内存类似,system V共享内存是调用shmget函数和shamat函数. shmget函数创建共享内存区,或者訪问一个存在的内存区,类似系统调用共享内存的open和posix共享内存shm_open函数. shmget函数原型为: #include <sys/ipc.h> #include <sys

Linux system v 共享内存

system v 共享内存 #include <sys/types.h> #include <sys/shm.h> int shmget(key_t key, size_t size, int shmflg); 建立:进程与共享内存的关联关系 key_t key:16进制的非0数字. 一般有两种方式设置它. 第一种:调用fotk函数 第二章:直接使用IPC_PRIVATE size:共享内存的大小 shmflg: IPC_CREAT IPC_EXCL 用户,组用户,其他用户对这片内

System V 共享内存

一 System V 共享内存的函数 1 shmget 函数 shmget(得到一个共享内存标识符或创建一个共享内存对象) 所需头文件 #include <sys/ipc.h> #include <sys/shm.h> 函数说明 得到一个共享内存标识符或创建一个共享内存对象并返回共享内存标识符 函数原型 int shmget(key_t key, size_t size, int shmflg) 函数传入值 key 0(IPC_PRIVATE):会建立新共享内存对象 大于0的32位

System V共享内存

shmread.c #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/mman.h> #include <sys/ipc.h> #include <sys/shm.h> #include <stdlib.h> #include <stdio.h> #inc

嵌入式 Linux进程间通信(八)——共享内存

嵌入式 Linux进程间通信(八)--共享内存 一.共享内存 共享内存允许两个或更多进程共享给定的内存区,数据不需要在不同进程间进行复制,是最快的进程间通信方式.使用共享内存唯一需要注意的是多个进程之间对给定存储区的同步访问,但共享内存本身没有提供同步机制,通常使用信号量来实现对共享内存访问的同步. 共享内存编程流程:创建共享内存.映射共享内存.使用共享内存.撤销映射操作.删除共享内存 1.创建共享内存 #include <sys/ipc.h> #include <sys/shm.h&g

Posix与System V共享内存函数区别

Posix标准shm_open:打开或创建一个共享内存区shm_unlink:删除一个共享内存区ftruncate:调整文件或共享内存区大小sem_open:创建信号量sem_wait:等待信号量sem_post:发送信号量sem_close:关闭信号量 System V标准ftok:生成keyshmget:建立共享内存shmdt:删除共享内存区semget:创建信号量semop:操作信号量semctl:控制信号量 简单解释一下ipcs命令和ipcrm命令.取得ipc信息:ipcs [-m|-q

system v 共享内存区

#include<sys/shm.h> int shmget(key_t key,size_t size,int oflag);    返回:成功则为共享内存区对象,出错为-1 key 的值可以是ftok的返回值,也可以是IPC_PRIVATE. ftok()               是非亲缘进程间 IPC_PRIVATE         是亲缘进程间的 size以字节为单位指定内存区的大小.当实际操作为创建一个新的共享内存区时,必须指定一个不为0的size值.如果实际操作为访问一个已存在