码迷,mamicode.com
首页 > 系统相关 > 详细

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

时间:2018-06-25 22:50:30      阅读:245      评论:0      收藏:0      [点我收藏+]

标签:input   共享   rms   头文件   撤销   相关   dea   type   erro   

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

共享内存有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.     
  90.     exit(0);
  91. }
复制代码

运行结果:
$ ./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”

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

标签:input   共享   rms   头文件   撤销   相关   dea   type   erro   

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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!