您的位置:首页 > 运维架构 > Linux

linux进程通讯-共享内存1

2011-11-26 14:26 405 查看
一)概念:

  1)Linux和所有的UNIX操作系统都允许通过共享内存在应用程序之间共享存储空间.

  2)有两类基本的API函数用于在进程间共享内存:System v和POSIX.

  3)这两类函数上使用相同的原则,核心思想就是任何要被共享的内存都必须经过显示的分配.

  4)因为所有进程共享同一块内存,共享内存在各种进程间通信方式中具有最高的效率.

  5)内核没有对访问共享内存进行同步,所以必须提供自己的同步措施,比如数据在写入之前,不允许其它进程对其进行读写.我们这里用wait来解决这个问题.

  二)POSIX共享内存API

  1)函数shm_open和shm_unlink非常类似于为普通文件所提供的open和unlink系统调用.

  2)如果要编写一个可移植的程序,那么shm_open和shm_unlink是最好的选择.

  3)shm_open:创建一个新的共享区域或者附加在已有的共享区域上.区域被其名字标识,函数返回各文件的描述符.

  4)shm_unlink:类似于unlink系统调用对文件进行操作,直到所有的进程不再引用该内存区后才对其进行释放.

  5)mmap:用于将一个文件映射到某一内存区中,其中也使用了shm_open函数返回的文件描述符.

  6)munmap:用于释放mmap所映射的内存区域.

  7)msync:同步存取一个映射区域并将高速缓存的数据回写到物理内存中,以便其他进程可以监听这些改变.

  源程序1

  #include <stdio.h>

  #include <string.h>

  #include <stdlib.h>

  #include <unistd.h>

  #include <sys/file.h>

  #include <sys/mman.h>

  #include <sys/wait.h>

  void error_out(const char *msg)

  {

  perror(msg);

  exit(EXIT_FAILURE);

  }

  int main (int argc, char *argv[])

  {

  int r;

  const char *memname = "/mymem";

  const size_t region_size = sysconf(_SC_PAGE_SIZE);

  int fd = shm_open(memname, O_CREAT|O_TRUNC|O_RDWR, 0666);

  if (fd == -1)

  error_out("shm_open");

  r = ftruncate(fd, region_size);

  if (r != 0)

  error_out("ftruncate");

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

  if (ptr == MAP_FAILED)

  error_out("MMAP");

  close(fd);

  pid_t pid = fork();

  if (pid == 0){

  u_long *d = (u_long *)ptr;

  *d = 0xdeadbeef;

  exit(0);

  }

  else{

  int status;

  waitpid(pid, &status, 0);

  printf("child wrote %#lx\n", *(u_long *)ptr);

  }

  sleep(50);

  r = munmap(ptr, region_size);

  if (r != 0)

  error_out("munmap");

  r = shm_unlink(memname);

  if (r != 0)

  error_out("shm_unlink");

  return 0;

  }

  编译:

  gcc -o postix-shm postix-shm.c -lrt

  ./postix-shm

  child wrote 0xdeadbeef

  等50秒后,程序退出.

  程序分析:

  1)程序执行shm_open函数创建了共享内存区域,此时会在/dev/shm/创建mymem文件.

  2)通过ftruncate函数改变shm_open创建共享内存的大小为页大小(sysconf(_SC_PAGE_SIZE)),如果不执行ftruncate函数的话,会报Bus error的错误.

  3)通过mmap函数将创建的mymem文件映射到内存.

  4)通过fork派生出子进程,而共享区域映射通过fork调用而被继承.

  5)程序通过wait系统调用来保持父进程与子进程的同步.

  6)在非父子进程也可以通过共享内存区域的方式进行通讯.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: