Linux下基于POSIX标准的共享内存操作示例

对于进程间通信,之前一直是用管道进行实现。比如父子进程间使用pipe,无血缘关系的进程可以使用fifo。从来没有想过使用共享内存,为什么呢?大家还记得这本书吧《Unix环境高级编程》,上面讲解了关于共享内存的操作,说实话,太麻烦了,真的不好用(有好多繁杂的接口,比如shmget, shmat,shmdt,chmctl等)。现在好了,基于POSIX标准的共享内存操作变得及其简单,总共就几个接口可供调用,已经变得像操作普通文件一样简单!

       新的标准的接口如下:

       POSIX 为创建、映射、同步和取消共享内存段提供五个入口点:

  • shm_open():创建共享内存段或连接到现有的已命名内存段。这个系统调用返回一个文件描述符。

  • shm_unlink():根据(shm_open() 返回的)文件描述符,删除共享内存段。实际上,这个内存段直到访问它的所有进程都退出时才会删除,这与在 UNIX 中删除文件很相似。但是,调用 shm_unlink() (通常由原来创建共享内存段的进程调用)之后,其他进程就无法访问这个内存段了。

  • mmap():把共享内存段映射到进程的内存。这个系统调用需要 shm_open() 返回的文件描述符,它返回指向内存的指针。(在某些情况下,还可以把一般文件或另一个设备的文件描述符映射到内存。对这些操作的讨论超出了本文的范围;具体方法请查阅操作系统的 mmap() 文档。)

  • munmap():作用与 mmap() 相反。

  • msync():用来让共享内存段与文件系统同步 ― 当把文件映射到内存时,这种技术有用。

使用共享内存的过程是,用 shm_open() 创建内存段,用 write()ftruncate() 设置它的大小,用 mmap() 把它映射到进程内存,执行其他参与者需要的操作。当使用完时,原来的进程调用 munmap()shm_unlink(),然后退出。

     怎么样?简单吧,就像文件操作一样,打开,映射得到一个指针,对指针操作,然后撤销映射,关闭!

     下面给出两段示例代码,以示用来进行无血缘关系的进程间通信


[cpp] view plain copy print ?
  1.   #include <sys/file.h>

  2. 6 #include <sys/mman.h>  

  3. 7 #include <fcntl.h>  

  4. 8 #include <sys/stat.h>  

  5. 9 #include <sys/wait.h>  

  6. 10 #include "util.h"

  7. 11  

  8. 12 void error_and_die(constchar *msg) {  

  9. 13     perror(msg);  

  10. 14     exit(EXIT_FAILURE);  

  11. 15 }  

  12. 16  

  13. 17 int main()  

  14. 18 {  

  15. 19     int ret;  

  16. 20     constsize_t region_size = sysconf(_SC_PAGE_SIZE);  

  17. 21     constchar *string = "This is a test for share memory!/n";  

  18. 22     int fd = shm_open(SHARE_MEMORY, O_CREAT | O_TRUNC | O_RDWR, 0666);  

  19. 23     if (-1 == fd)  

  20. 24     {  

  21. 25         error_and_die("shm_open");  

  22. 26     }  

  23. 27  

  24. 28     ret = ftruncate(fd, region_size);  

  25. 29     if (ret)  

  26. 30     {  

  27. 31         error_and_die("ftruncate");  

  28. 32     }  

  29. 33  

  30. 34     void *ptr = mmap(0, region_size, PROT_READ | PROT_WRITE , MAP_SHARED, fd, 0);  

  31. 35     if (ptr == MAP_FAILED)  

  32. 36     {  

  33. 37         error_and_die("mmap");  

  34. 38     }  

  35. 39  

  36. 40     close(fd);  

  37. 41     //*(int *)ptr = 0x55aa;

  38. 42     memcpy(ptr, string, (strlen(string) + 1));  

  39. 43  

  40. 44     sleep(10);  

  41. 45  

  42. 46     ret = munmap(ptr, region_size);  

  43. 47     if (ret)  

  44. 48         error_and_die("munmap");  

  45. 49  

  46. 50     ret = shm_unlink(SHARE_MEMORY);  

  47. 51     if (ret)  

  48. 52         error_and_die("shm_unlink");  

  49. 53     return 0;  

  50. 54  

  51. 55  

  52. 56 }  

#include <sys/file.h> 6 #include <sys/mman.h> 7 #include <fcntl.h> 8 #include <sys/stat.h> 9 #include <sys/wait.h> 10 #include "util.h" 11 12 void error_and_die(const char *msg) { 13 perror(msg); 14 exit(EXIT_FAILURE); 15 } 16 17 int main() 18 { 19 int ret; 20 const size_t region_size = sysconf(_SC_PAGE_SIZE); 21 const char *string = "This is a test for share memory!/n"; 22 int fd = shm_open(SHARE_MEMORY, O_CREAT | O_TRUNC | O_RDWR, 0666); 23 if (-1 == fd) 24 { 25 error_and_die("shm_open"); 26 } 27 28 ret = ftruncate(fd, region_size); 29 if (ret) 30 { 31 error_and_die("ftruncate"); 32 } 33 34 void *ptr = mmap(0, region_size, PROT_READ | PROT_WRITE , MAP_SHARED, fd, 0); 35 if (ptr == MAP_FAILED) 36 { 37 error_and_die("mmap"); 38 } 39 40 close(fd); 41 //*(int *)ptr = 0x55aa; 42 memcpy(ptr, string, (strlen(string) + 1)); 43 44 sleep(10); 45 46 ret = munmap(ptr, region_size); 47 if (ret) 48 error_and_die("munmap"); 49 50 ret = shm_unlink(SHARE_MEMORY); 51 if (ret) 52 error_and_die("shm_unlink"); 53 return 0; 54 55 56 }



[cpp] view plain copy print ?
  1. 1 #include <stdio.h>  

  2.  2 #include <string.h>  

  3.  3 #include <stdlib.h>  

  4.  4 #include <unistd.h>  

  5.  5 #include <sys/file.h>  

  6.  6 #include <sys/mman.h>  

  7.  7 #include <fcntl.h>  

  8.  8 #include <sys/stat.h>  

  9.  9 #include <sys/wait.h>  

  10. 10 #include "util.h"

  11. 11  

  12. 12 void error_and_die(constchar *msg) {  

  13. 13     perror(msg);  

  14. 14     exit(EXIT_FAILURE);  

  15. 15 }  

  16. 16  

  17. 17 int main()  

  18. 18 {  

  19. 19     int ret;  

  20. 20     constsize_t region_size = sysconf(_SC_PAGE_SIZE);  

  21. 21     int fd = shm_open(SHARE_MEMORY, O_CREAT | O_RDWR, 0666);  

  22. 22     if (-1 == fd)  

  23. 23     {  

  24. 24         error_and_die("shm_open");  

  25. 25     }  

  26. 26  

  27. 27     ret = ftruncate(fd, region_size);  

  28. 28     if (ret)  

  29. 29     {  

  30. 30         error_and_die("ftruncate");  

  31. 31     }  

  32. 32  

  33. 33     void *ptr = mmap(0, region_size, PROT_READ | PROT_WRITE , MAP_SHARED, fd, 0);  

  34. 34     if (ptr == MAP_FAILED)  

  35. 35     {  

  36. 36         error_and_die("mmap");  

  37. 37     }  

  38. 38  

  39. 39     close(fd);  

  40. 40  

  41. 41  

  42. 42     printf("%s", (char *)ptr);  

  43. 43     ret = munmap(ptr, region_size);  

  44. 44     if (ret)  

  45. 45         error_and_die("munmap");  

  46. 46  

  47. 47     ret = shm_unlink(SHARE_MEMORY);  

  48. 48     if (ret)  

  49. 49         error_and_die("shm_unlink");  

  50. 50  

  51. 51     return 0;  

  52. 52 }  

1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 #include <unistd.h> 5 #include <sys/file.h> 6 #include <sys/mman.h> 7 #include <fcntl.h> 8 #include <sys/stat.h> 9 #include <sys/wait.h> 10 #include "util.h" 11 12 void error_and_die(const char *msg) { 13 perror(msg); 14 exit(EXIT_FAILURE); 15 } 16 17 int main() 18 { 19 int ret; 20 const size_t region_size = sysconf(_SC_PAGE_SIZE); 21 int fd = shm_open(SHARE_MEMORY, O_CREAT | O_RDWR, 0666); 22 if (-1 == fd) 23 { 24 error_and_die("shm_open"); 25 } 26 27 ret = ftruncate(fd, region_size); 28 if (ret) 29 { 30 error_and_die("ftruncate"); 31 } 32 33 void *ptr = mmap(0, region_size, PROT_READ | PROT_WRITE , MAP_SHARED, fd, 0); 34 if (ptr == MAP_FAILED) 35 { 36 error_and_die("mmap"); 37 } 38 39 close(fd); 40 41 42 printf("%s", (char *)ptr); 43 ret = munmap(ptr, region_size); 44 if (ret) 45 error_and_die("munmap"); 46 47 ret = shm_unlink(SHARE_MEMORY); 48 if (ret) 49 error_and_die("shm_unlink"); 50 51 return 0; 52 }



代码很简单,唯一注意的地方是,第二个文件中shm_open的时候O_TUNC参数要去掉,否则内存又被截断为0,读不到东西的。


你可能感兴趣的:(application)