共享内存
进程间通信的本质是让不同的进程访问一块公共的资源。
1、共享内存是进程间通信最快的方式(为什么)
2、共享内存不提供任何的同步与互斥关系。(由用户维护,可以用信号量)
以下图解释了问题1,原因是,由于共享内存的机制,两个进程不需要拷贝拷贝数据,这个特点可能在数据较少的情况下看不出来,但是数据较多时,优势较为明显。
下图是shmat之前之后的共享内存示意图:(shmget获得共享内存后需要挂接)
函数:
用于Linux进程通信共享内存。共享内存函数由shmget、shmat、shmdt、shmctl四个函数组成。
shmat(把共享内存区对象映射到调用进程的地址空间)
void *shmat(int shmid, const void *shmaddr, int shmflg)
参数:
shmid | 共享内存标识符 |
shmaddr | 指定共享内存出现在进程内存地址的什么位置,直接指定为NULL让内核自己决定一个合适的地址位置 |
shmflg | 如果设置为SHM_RDONLY是只读模式,其他为读写模式 |
返回值:成功返回附加好的共享内存地址
shmdt(断开共享内存连接)
int shmdt(const void *shmaddr)
参数:
shmaddr:连接的共享内存的起始地址
返回值:成功返回0
shmget(得到一个共享内存标识符或创建一个共享内存对象)
int shmget(key_t key, size_t size, int shmflg)
参数:
key | 大于0的32位整数:视参数shmflg来确定操作。通常要求此值来源于ftok返回的IPC键值 |
size | 大于0的整数:新建的共享内存大小,以字节为单位 |
flags | 有IPC_CREAT和IPC_EXCL(用法同前面写的一致) |
返回值:成功返回共享内存标示符
注:system V分配内存的方法以页为基本单位,一般以页的整数倍分配。
shmctl完成对共享内存的控制
int shmctl(int shmid, int cmd, struct shmid_ds *buf)
参数:
shmid | 共享内存标识符 | |
cmd | IPC_STAT:得到共享内存的状态,把共享内存的shmid_ds结构复制到buf中 | |
IPC_SET:改变共享内存的状态,把buf所指的shmid_ds结构中的uid、gid、mode复制到共享内存的shmid_ds结构内 | ||
IPC_RMID:删除这片共享内存 | ||
buf | 共享内存管理结构体。具体说明参见共享内存内核结构定义部分 |
共享内存实现通信的例子
comm.h
#pragma once #include<errno.h> #include<sys/ipc.h> #include<sys/shm.h> #include<string.h> #define _PATH_NAME_ "/temp" #define _PROJ_ID_ 0x6666 int create_shm(int size); int get_shm(); int destory_shm(int shm_id); void* shm_at(int shm_id); int shm_dt(void*shmaddr);
comm.c
#include"comm.h" static int comm_create_shm(int size,int flags) { key_t _key = ftok(_PATH_NAME_,_PROJ_ID_); if(_key<0) { perror("ftok"); return -1; } // int shm_id=shmget(_key,size,IPC_CREAT | IPC_EXCL); int shm_id=shmget(_key,size,flags); if(shm_id < 0) { perror("shmget"); return -2; } return shm_id; } int create_shm(int size) { int flags = IPC_CREAT | IPC_EXCL|0666; return comm_create_shm(size,flags); } int get_shm() { int flags = IPC_CREAT; return comm_create_shm(0,flags); } int destory_shm(int shm_id) { if(shmctl(shm_id,IPC_RMID,NULL)<0) { perror("shmctl"); return -1; } return 0; } void* shm_at(int shm_id) { return shmat(shm_id,NULL,0); } int shm_dt(void* shmaddr) { return shmdt(shmaddr); }
server.c
#include"comm.c" int main() { int shm_id = create_shm(4096); sleep(5); char* buf = (char*)shm_at(shm_id); sleep(1); sleep(1); while(1) { printf("%s\n",buf); sleep(1); if(strcmp(buf,"AAAAA") == 0) { break; } } shm_dt(buf); sleep(5); destory_sem(sem_id); return 0; }
client.c
#include"comm.c" int main() { int shm_id = get_shm(); char* buf = (char*)shm_at(shm_id); int index = 0; while(1) { buf[index++]='A'; buf[index]='\0'; sleep(1); if(index>5) { break; } } sleep(5); shm_dt(buf); sleep(5); return 0; }
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。