4.共享内存shm

匿名 (未验证) 提交于 2019-12-02 22:56:40
版权声明:guojawee https://blog.csdn.net/weixin_36750623/article/details/83384612

1.最快的IPC通信方式

  共享内存区是最快的IPC形式。一旦这样的内存映射到共享它的进程的地址空间,这 些进程间数据传递不再涉及到内核,换句话说是进程不再通过执行进入内核的系统调 用来传递彼此的数据。 

图:用管道或者消息队列传递数据

图:用共享内存传递数据

2.相关API
[1]shmget

int shmget(key_t key, size_t size, int shmflg); //创建或打开 

[2]shmat:将共享内存段连接到进程地址空间

[说明]shmget创建/打开共享内存后,必须使用shmat将该共享内存连接到 进程的地址空间,以便进程使用。不适用shmat,进程无法使用该共享内存。 (每个进程shmat以后得到的地址不一样--属于自己的共享内存地址)  p=shmat(shm_id,NULL,0);//让本进程链接到共享内存会得到一个共享内存的首地址p,可 以直接通过指针p去操控共享内存。 -----------------------------------   void *shmat(int shmid, const void *shmaddr, int shmflg); 参数: 	shmaddr:指定连接的地址 	shmflg:两个可能取值SHM_RND和SHM_RDONLY 返回值:失败返回-1;成功返回一个指针p(指向共享内存的第一个字节),使用p操         控共享内存。 
shmaddr和shmflg的组合关系 共享内存最终地址
shmaddr为NULL,不管shmflg 核心自动选择一个地址
shmaddr不为NULL且shmflg无SHM_RND标记 以shmaddr为连接地址
shmaddr不为NULL且shmflg设置了SHM_RND标记 连接的地址会自动向下调整为SHMLBA的整数倍。公式:shmaddr - (shmaddr % SHMLBA)
shmflg=SHM_RDONLY 表示连接操作用来只读共享内存

[3]shmdt:将共享内存段与当前进程脱离

int shmdt(const void *shmaddr); 参数shmaddr:由shmat所返回的指针 

注意:将共享内存段与当前进程脱离不等于删除共享内存段
[3]shmctl:控制共享内存

int shmctl(int shmid, int cmd, struct shmid_ds *buf); IPC_STAT:获取shmid_ds结构中的值 IPC_SET:设置shmid_ds结构中的值 IPC_RMID:删除共享内存 

3.共享内存的删除[难点]

1.如果共享内存被别的程序占用,连接数/引用计数不为0,则删除共享内存不会立马被 删除====>删除后,会出现一个现象---共享内存key值变成了0,引用计数减1---且此时 的共享内存已经不能被其他[新shmat]的进程读取了(重启一个进程重新shmat的时候 由于key已经变为0,所以新开的进程是不能再继续读取共享内存的数据的);只能被 在删除之前就[已经shmat]的进程读取。 2.只有当连接共享内存的所有进程都死掉,Linux内核才会删除共享内存 --------------------------------- 总结:是否能直接删除共享内存?   关键是看在删除以后有无进程链接到该块内存<==>等同于shmctl+shmdt删除之前有 多少进程已经执行了shmat。 

示例代码

子进程向shm中写数据 父进程从shm中读取子进程向shm写入的数据 
typedef struct student{   int age;   char name[10]; }student;  int main() {   key_t key=ftok("/home/gjw/tmp",'a');   int shm_id=shmget(key,sizeof(int)*100,0664|IPC_CREAT);    pid_t pid=fork();    if(pid>0)   {    }   else if(pid==0)   {     void* ptr=shmat(shm_id,NULL,0);     struct student* stu=(struct student*)ptr;     stu->age=24;     strcpy(stu->name,"guojiawei");     shmdt(ptr);     exit(0);   }      sleep(1);    wait(NULL);    void* ptr=shmat(shm_id,NULL,0);   printf("age=%d, name=%s\n",((student*)ptr)->age,((student*)ptr)->name);    shmdt(ptr);    return 0; } 
文章来源: 4.共享内存shm
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!