linux下共享内存

C programming in the UNIX environment的编程手册,一般都会为进程间用共享内存的方法通信提供两组方法:

1. SYSTEM V定义的

int shmget(key_t key, int 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); //完成对共享内存的控制可以修改共享内存信息,也可以删除这片贡献内存。

例子代码如下:

#include <stdio.h> #include <unistd.h> #include <string.h> #include <sys/ipc.h> #include <sys/shm.h> #include <error.h> #define SIZE 1024 int main()  {   int shmid ;     char *shmaddr ;   struct shmid_ds buf ;     int flag = 0 ;   int pid ;     shmid = shmget(IPC_PRIVATE, SIZE, IPC_CREAT|0600 ) ;   if ( shmid < 0 )     {   perror("get shm ipc_id error") ;     return -1 ;     }     pid = fork() ;   if ( pid == 0 )     {   shmaddr = (char *)shmat( shmid, NULL, 0 ) ;     if ( (int)shmaddr == -1 )   {     perror("shmat addr error") ;   return -1 ;   }   strcpy( shmaddr, "Hi, I am child process!\n") ;     shmdt( shmaddr ) ;   return 0;     } else if ( pid > 0) {   sleep(3 ) ;     flag = shmctl( shmid, IPC_STAT, &buf) ;   if ( flag == -1 )     {   perror("shmctl shm error") ;     return -1 ;     }     printf("shm_segsz =%d bytes\n", buf.shm_segsz ) ;   printf("parent pid=%d, shm_cpid = %d \n", getpid(), buf.shm_cpid ) ;     printf("chlid pid=%d, shm_lpid = %d \n",pid , buf.shm_lpid ) ;   shmaddr = (char *) shmat(shmid, NULL, 0 ) ;     if ( (int)shmaddr == -1 )   {     perror("shmat addr error") ;   return -1 ;   }   printf("%s", shmaddr) ;     shmdt( shmaddr ) ;   shmctl(shmid, IPC_RMID, NULL) ;     }else{   perror("fork error") ;     shmctl(shmid, IPC_RMID, NULL) ;   }   return 0 ; }

编译 gcc shm.c –o shm。

  执行 ./shm,执行结果如下:

  shm_segsz =1024 bytes

  shm_cpid = 9503

  shm_lpid = 9504

Hi, I am child process!

2. POSIX定义的:

int shm_open(const char *name, int oflag, mode_t mode); //打开

参数:name 共享内存区的名字(不能为空), cflag 标志位 mode 权限位 返回值:成功返回0,出错返回-1

oflag参数必须含有O_RDONLY和O_RDWR标志,还可以指定如下标志:O_CREAT,O_EXCL或O_TRUNC.

mode参数指定权限位,它指定O_CREAT标志的前提下使用。 shm_open的返回值是一个整数描述字,它随后用作mmap的第五个参数。int shm_unlink(const char *name); //删除一个共享内存区,返回值,0成功,-1失败。

int ftruncate(int fd, off_t length); //分配大小

void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset); //将一个文件或者其它对象映射进内存

返回值:如果mmap成功则返回映射首地址,如果出错则返回常数MAP_FAILED。 参数:addr 指向映射存储区的起始地址;len 映射的字节prot 对映射存储区的保护要求flag 标志位filedes 要被映射文件的描述符off 要映射字节在文件中的起始偏移量参数解释如下:整体相当于磁盘文件的对应长度搬移到内存中。如果addr参数为NULL,内核会自己在进程地址空间中选择合适的地址建立映射。如果addr不是NULL,则给内核一个提示,应该从什么地址开始映射,内核会选择addr之上的某个合适的地址开始映射。建立映射后,真正的映射首地址通过返回值可以得到。off参数是从文件的什么位置开始映射,必须是页大小的整数倍(在32位体系统结构上通常是4K)。prot参数有四种取值:PROT_EXEC表示映射的这一段可执行,例如映射共享库PROT_READ表示映射的这一段可读PROT_WRITE表示映射的这一段可写PROT_NONE表示映射的这一段不可访问flag参数有很多种取值,这里只讲两种,MAP_SHARED多个进程对同一个文件的映射是共享的,一个进程对映射的内存做了修改,另一个进程也会看到这种变化。MAP_PRIVATE多个进程对同一个文件的映射不是共享的,一个进程对映射的内存做了修改,另一个进程并不会看到这种变化,也不会真的写到文件中去。

int fstat(int fd, struct stat *buf) //当打开一个已经从在的共享内存时,我们调用fstat 来获取有关该对象的信息

int munmap(void *addr,size_t len) // 要删除一个已经建立的映射关系

int msync (void *addr,size_t len,int flags) //实现同步或者异步

由于POSIX标准比较通用,一般建议使用该标准定义的方法集。但在编译的时候可能会出现“undefined reference to `shm_open’”的错误,加上–lrt就可以编过,例如:

/* This is just to test if the function is found in the libs. */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <sys/mman.h> #include <sys/stat.h> int main (void) {      int i;      i = shm_open ("/tmp/shared", O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);      printf ("shm_open rc = %d\n", i);      shm_unlink ("/tmp/shared");      return (0); } 

用命令 gcc -lrt -o test test.c 就可以编过。

对于旅行,从来都记忆模糊。记不得都去了哪些地方,

linux下共享内存

相关文章:

你感兴趣的文章:

标签云: