共享内存函数由shmget、shmat、shmdt、shmctl四个函数组成。下面的表格列出了这四个函数的函数原型及其具体说明。 1. shmget函数原型
在Linux环境中,对开始申请的共享内存空间进行了初始化,初始值为0x00。 如果用shmget创建了一个新的消息队列对象时,则shmid_ds结构成员变量的值设置如下: shm_lpid、shm_nattach、shm_atime、shm_dtime设置为0。 msg_ctime设置为当前时间。 shm_segsz设成创建共享内存的大小。 shmflg的读写权限放在shm_perm.mode中。 shm_perm结构的uid和cuid成员被设置成当前进程的有效用户ID,gid和cuid成员被设置成当前进程的有效组ID。 2. shmat函数原型
3. shmdt函数原型
4. shmctl函数原型
共享内存应用范例 5. 父子进程通信范例父子进程通信范例,shm.c源代码如下: #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! 6. 多进程读写范例多进程读写即一个进程写共享内存,一个或多个进程读共享内存。下面的例子实现的是一个进程写共享内存,一个进程读共享内存。 (1)下面程序实现了创建共享内存,并写入消息。 shmwrite.c源代码如下: #include <stdio.h> #include <sys/ipc.h> #include <sys/shm.h> #include <sys/types.h> #include <unistd.h> #include <string.h> typedef struct{ char name[8]; int age; } people; int main(int argc, char** argv) { int shm_id,i; key_t key; char temp[8]; people *p_map; char pathname[30] ;
strcpy(pathname,"/tmp") ; key = ftok(pathname,0x03); if(key==-1) { perror("ftok error"); return -1; } printf("key=%d\n",key) ; shm_id=shmget(key,4096,IPC_CREAT|IPC_EXCL|0600); if(shm_id==-1) { perror("shmget error"); return -1; } printf("shm_id=%d\n", shm_id) ; p_map=(people*)shmat(shm_id,NULL,0); memset(temp, 0x00, sizeof(temp)) ; strcpy(temp,"test") ; temp[4]='0'; for(i = 0;i<3;i++) { temp[4]+=1; strncpy((p_map+i)->name,temp,5); (p_map+i)->age=0+i; } shmdt(p_map) ; return 0 ; } (2)下面程序实现从共享内存读消息。 shmread.c源代码如下: #include <stdio.h> #include <string.h> #include <sys/ipc.h> #include <sys/shm.h> #include <sys/types.h> #include <unistd.h> typedef struct{ char name[8]; int age; } people; int main(int argc, char** argv) { int shm_id,i; key_t key; people *p_map; char pathname[30] ;
strcpy(pathname,"/tmp") ; key = ftok(pathname,0x03); if(key == -1) { perror("ftok error"); return -1; } printf("key=%d\n", key) ; shm_id = shmget(key,0, 0); if(shm_id == -1) { perror("shmget error"); return -1; } printf("shm_id=%d\n", shm_id) ; p_map = (people*)shmat(shm_id,NULL,0); for(i = 0;i<3;i++) { printf( "name:%s\n",(*(p_map+i)).name ); printf( "age %d\n",(*(p_map+i)).age ); } if(shmdt(p_map) == -1) { perror("detach error"); return -1; } return 0 ; } (3)编译与执行 ① 编译gcc shmwrite.c -o shmwrite。 ② 执行./shmwrite,执行结果如下: key=50453281 shm_id=688137 ③ 编译gcc shmread.c -o shmread。 ④ 执行./shmread,执行结果如下: key=50453281 shm_id=688137 name:test1 age 0 name:test2 age 1 name:test3 age 2 ⑤ 再执行./shmwrite,执行结果如下: key=50453281 shmget error: File exists |
|