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,struct,null,存储,reference)