进程通信之共享内存
2017-01-06 21:55
267 查看
1、共享内存
–共享内存是进程间通信中最简单的方式之一。共享内存在各种进程间通信方式中具有最高的效率。因为系统内核没有对访问共享内存进行同步,您必须提供自己的同步措施。解决这些问题的常用方法是通过使用信号量进行同步。
2、int shmget(key_t key, size_t size, int shmflg)
–shmget((key_t)1234, sizeof(struct shared_use_st), 0666|IPC_CREAT)
–shmget得到一个共享内存标识符或创建一个共享内存对象
–key:建立新的共享内存对象
–size:新建立的内存大小(以字节为单位)
–shmflg:标识符
例:
$gcc create_shm.c -o create_shm
$./create_shm
successfully created segment :98305
-------shared Memory segments--------
key shemid owner perms bytes nattch status
0x00000000 0 linux-c 600 393216 2 dest
0x00000000 98305 linux-c 666 4096 0
3、将一个存在的共享内存连接到本进程空间
void *shmat(int shmid, const void *shmaddr, int shmflg)
–shmat(shmid, 0, 0)
–返回共享的内存地址,否则返回-1
–shmid:共享内存标识符
–shmaddr:指定共享内存出现在进程内存地址的什么位置,直接指定为NULL让内核自己决定一个合适的地址位置
–shmflg SHM_RDONLY:为只读模式,其他为读写模式
addr 和 flag 组合 说明要引入的地址值,通常只有两种用法:
注:如函数成功返回值为实际引入的地址,如失败返回-1。shmat()函数成功执行会将shm_id段的shmid_ds结构的shm_nattch计数器的值加。
4、对共享内存段操作结束时从进程空间中脱离
#include<sys/shm.h>
int shmdt(void *addr);
参数addr是调用shemat()函数的返回值,如函数执行成功返回0,并将该共享内存的shmid_ds结构的shm_nattch计数器减1,如失败返回-1。
例:
$ gcc opr_shm.c -o opr_shm
segment attached at oxb7723000
key shemid owner perms bytes nattch status
0x00000000 0 linux-c 600 393216 2 dest
0x00000000 98305 linux-c 666 4096 1
key shemid owner perms bytes nattch status
0x00000000 0 linux-c 600 393216 2 dest
0x00000000 98305 linux-c 666 4096 0
5、int shmctl(int shmid, int cmd, struct shmid_ds *buf)
–shmctl(shmid, IPC_RMID, 0) == -1
–shmid:共享内存标识符
–cmd IPC_RMID:删除这片共享内存
–buf:共享内存管理结构体
cmd的值 意义
IPC_STAT 取shm_id 所指向内存共享段的shm_ds结构,对参数buf指向的结构赋值。
IPC_SET 使用buf指向的结构对,sh_mid段的相关结构赋值,只对以下几个域有作用。
shm_perm.uid shm_perm.gid shm_perm.mode
注意此命令只有具备以下条件的进程才可以请求:
(1)进程的用户ID等于shm_perm.cuid shm_perm.uid
(2)超级用户特权进程。
IPC_RMID 删除shm_id所指向的共享内存段,只有当shmid_ds结构的shm_nattch 域为0时
才会真正执行删除命令,否则不会删除该段。注意此命令的请求规则与IPC_SET命令相同
SHM_LOCK 锁定共享内存段在内存,此命令只能由超级用户请求。
SHM_UNLOCK 对共享内存段解锁,此命令只能由超级用户请求。
例:
shmdata.h
shmread.h
shmwrite.h
–共享内存是进程间通信中最简单的方式之一。共享内存在各种进程间通信方式中具有最高的效率。因为系统内核没有对访问共享内存进行同步,您必须提供自己的同步措施。解决这些问题的常用方法是通过使用信号量进行同步。
2、int shmget(key_t key, size_t size, int shmflg)
–shmget((key_t)1234, sizeof(struct shared_use_st), 0666|IPC_CREAT)
–shmget得到一个共享内存标识符或创建一个共享内存对象
–key:建立新的共享内存对象
–size:新建立的内存大小(以字节为单位)
–shmflg:标识符
例:
#include<sys/types.h> #include<sys/ipc.h> #include<sys/shm.h> #include<stdlib.h> #include<stdio.h> #define BUFSZ 4096 int main(void) { int shm_id; /*共享内存标识符*/ shm_id = shmget(IPC_PRIVTE, BUFSZ,0666); if(shm_id < 0) { /*创建共享内存*/ perror("shmgget"); exit(1); } printf("successfully created segment :%d\n",shm_id); system("ipcs -m"); /*调用ipcs命令查看IPC*/ eixt(0); }
$gcc create_shm.c -o create_shm
$./create_shm
successfully created segment :98305
-------shared Memory segments--------
key shemid owner perms bytes nattch status
0x00000000 0 linux-c 600 393216 2 dest
0x00000000 98305 linux-c 666 4096 0
3、将一个存在的共享内存连接到本进程空间
void *shmat(int shmid, const void *shmaddr, int shmflg)
–shmat(shmid, 0, 0)
–返回共享的内存地址,否则返回-1
–shmid:共享内存标识符
–shmaddr:指定共享内存出现在进程内存地址的什么位置,直接指定为NULL让内核自己决定一个合适的地址位置
–shmflg SHM_RDONLY:为只读模式,其他为读写模式
addr 和 flag 组合 说明要引入的地址值,通常只有两种用法:
注:如函数成功返回值为实际引入的地址,如失败返回-1。shmat()函数成功执行会将shm_id段的shmid_ds结构的shm_nattch计数器的值加。
4、对共享内存段操作结束时从进程空间中脱离
#include<sys/shm.h>
int shmdt(void *addr);
参数addr是调用shemat()函数的返回值,如函数执行成功返回0,并将该共享内存的shmid_ds结构的shm_nattch计数器减1,如失败返回-1。
例:
#include<sys/types.h> #include<sys/ipc.h> #include<sys/shm.h> #include<stdlib.h> #include<stdio.h> int main(int argc, char *argv[]) { int shm_id; char *shm_buf; if(argc != 2) { printf("USAGE: atshm <identifier>"); exit(1); } shm_id = atoi(argv[1]); if((shm_buf = shmat(shm_id,0 ,0)) < (char *)0) { perror("shmat"); exit(1); } printf("segment attached at %p\n", shm_buf); system("ipc -m"); sleep(3); if((shmdt(shm_buf)) < 0) { perror("shmdt"); exit(1); } printf("segment detached \n"); system("ipcs -m"); exit(0); }
$ gcc opr_shm.c -o opr_shm
segment attached at oxb7723000
key shemid owner perms bytes nattch status
0x00000000 0 linux-c 600 393216 2 dest
0x00000000 98305 linux-c 666 4096 1
key shemid owner perms bytes nattch status
0x00000000 0 linux-c 600 393216 2 dest
0x00000000 98305 linux-c 666 4096 0
5、int shmctl(int shmid, int cmd, struct shmid_ds *buf)
–shmctl(shmid, IPC_RMID, 0) == -1
–shmid:共享内存标识符
–cmd IPC_RMID:删除这片共享内存
–buf:共享内存管理结构体
cmd的值 意义
IPC_STAT 取shm_id 所指向内存共享段的shm_ds结构,对参数buf指向的结构赋值。
IPC_SET 使用buf指向的结构对,sh_mid段的相关结构赋值,只对以下几个域有作用。
shm_perm.uid shm_perm.gid shm_perm.mode
注意此命令只有具备以下条件的进程才可以请求:
(1)进程的用户ID等于shm_perm.cuid shm_perm.uid
(2)超级用户特权进程。
IPC_RMID 删除shm_id所指向的共享内存段,只有当shmid_ds结构的shm_nattch 域为0时
才会真正执行删除命令,否则不会删除该段。注意此命令的请求规则与IPC_SET命令相同
SHM_LOCK 锁定共享内存段在内存,此命令只能由超级用户请求。
SHM_UNLOCK 对共享内存段解锁,此命令只能由超级用户请求。
例:
shmdata.h
#ifndef _SHMDATA_H_HEADER #define _SHMDATA_H_HEADER #define TEXT_SZ 2048 struct shared_use_st { //作为一个标志,非0:表示可读,0表示可写 int written; //记录写入和读取的文本 char text[TEXT_SZ]; }; #endif
shmread.h
#include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <sys/shm.h> #include "shmdata.h" int main(void) { int running = 1;//程序是否继续运行的标志 void *shm = NULL;//分配的共享内存的原始首地址 struct shared_use_st *shared;//指向shm int shmid;//共享内存标识符 //创建共享内存 shmid = shmget((key_t)1234, sizeof(struct shared_use_st), 0666|IPC_CREAT); if(shmid == -1) { fprintf(stderr, "shmget failed\n"); exit(EXIT_FAILURE); } //将共享内存连接到当前进程的地址空间 shm = shmat(shmid, 0, 0); if(shm == (void*)-1) { fprintf(stderr, "shmat failed\n"); exit(EXIT_FAILURE); } printf("\nMemory attached at %p\n", shm); //设置共享内存 shared = (struct shared_use_st*)shm; shared->written = 0; while(running)//读取共享内存中的数据 { //没有进程向共享内存定数据有数据可读取 if(shared->written != 0) { printf("You wrote: %s", shared->text); sleep(rand() % 3); //读取完数据,设置written使共享内存段可写 shared->written = 0; //输入了end,退出循环(程序) if(strncmp(shared->text, "end", 3) == 0) running = 0; } else//有其他进程在写数据,不能读取数据 sleep(1); } //把共享内存从当前进程中分离 if(shmdt(shm) == -1) { fprintf(stderr, "shmdt failed\n"); exit(EXIT_FAILURE); } //删除共享内存 if(shmctl(shmid, IPC_RMID, 0) == -1) { fprintf(stderr, "shmctl(IPC_RMID) failed\n"); exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); }
shmwrite.h
#include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <sys/shm.h> #include "shmdata.h" int main(void) { int running = 1; void *shm = NULL; struct shared_use_st *shared = NULL; char buffer[BUFSIZ + 1];//用于保存输入的文本 int shmid; //创建共享内存 shmid = shmget((key_t)1234, sizeof(struct shared_use_st), 0666|IPC_CREAT); if(shmid == -1) { fprintf(stderr, "shmget failed\n"); exit(EXIT_FAILURE); } //将共享内存连接到当前进程的地址空间 shm = shmat(shmid, (void*)0, 0); if(shm == (void*)-1) { fprintf(stderr, "shmat failed\n"); exit(EXIT_FAILURE); } printf("Memory attached at %p\n", shm); //设置共享内存 shared = (struct shared_use_st*)shm; while(running)//向共享内存中写数据 { //数据还没有被读取,则等待数据被读取,不能向共享内存中写入文本 while(shared->written == 1) { sleep(1); printf("Waiting...\n"); } //向共享内存中写入数据 printf("Enter some text: "); fgets(buffer, BUFSIZ, stdin); strncpy(shared->text, buffer, TEXT_SZ); //写完数据,设置written使共享内存段可读 shared->written = 1; //输入了end,退出循环(程序) if(strncmp(buffer, "end", 3) == 0) running = 0; } //把共享内存从当前进程中分离 if(shmdt(shm) == -1) { fprintf(stderr, "shmdt failed\n"); exit(EXIT_FAILURE); } sleep(2); exit(EXIT_SUCCESS); }
相关文章推荐
- 共享内存应用于进程通信
- 应用程序开发-进程通信-共享内存
- 进程通信-共享内存-mmap()-code3
- C# .Net 多进程同步 通信 共享内存 内存映射文件 Memory Mapped 转
- 通过共享内存和信号量实现进程间的通信
- 进程之间使用共享内存通信....
- linux 进程间的通信(五) 共享内存-2
- 非亲缘进程间的共享内存与信号通信
- 进程通信-共享内存-mmap()
- 进程间通过共享内存通信
- UNIX环境高级编程学习之第十五章进程间通信 - 两个进程通过映射普通文件实现共享内存通信
- window中进程间如何通信vc++技术 (共享内存)
- linux 进程间的通信(五) 共享内存-1
- 非亲缘进程间的共享内存与信号通信
- 进程通信之共享内存
- 动态链接库(DLL) (含进程通信之共享内存)
- window中进程间如何通信vc++技术 (共享内存)
- window中进程间如何通信vc++技术 (共享内存)
- 共享内存 进程通信
- Linux进程通信-共享内存