进程间通信--共享内存

来源:互联网 发布:动漫周边淘宝 编辑:程序博客网 时间:2024/06/06 09:26

进程间通信前面已经提到了两种system V版本的通信机制(消息队列和信号量)。接下来写一下另外一种system V的通信机制--共享内存


共享内存在所有的通信方式里是最快的,这离不开它的机制;先来看看为什么共享内存的速度这么快


共享内存原理:同一块物理内存被映射到两个进程各自的虚拟内存空间上,然后两个进程访问自己的虚拟内存相当于访问到了另一方的虚拟内存,因为它俩之间不需要建立一个独立的空间,所以访问速度是非常快的,可以说一个进程可以即时看到另一进程的数据更新。

创建共享内存用到的函数是shmget,shmget函数原型:

第一个参数key不用多数,就是他的唯一标识。第二个参数就是要申请内存的大小。第三个参数和前面两个通信机制的参数一样,IPC_CREAT和IPC_EXCL。


删除共享内存函数shmctl,函数原型为:


第一个参数为创建的共享内存ID,如果是删除就和以前的一样IPC_RMID,第三个参数为要删的缓冲区,设置为NULL。


既然共享内存是直接有物理内存映射的结果,那么另一个进程更新的数据会立马被另一个进程看到,所以它不存在同步与互斥机制,这时就要自己加一个互斥机制

       引入的互斥机制为关联内存和去关联内存,函数原型为:


其中shmat为关联,第一个参数为创建的共享内存ID,第二个参数为NULL, 第三个参数为格式,这里不需要创建,则设置为0。        shmdt为去关联,参数为要关联的地址。


为了验证共享内存的实时性,这里创建一个server和client,server往里写,client读。

#include "comm.h"static int commShm(int size, int flags){    key_t _k = ftok(PATHNAME, PROJ_ID);    if(_k < 0){        perror("ftok");        return -1;    }        int shmid = shmget(_k, size, flags);    if(shmid < 0){        perror("shmget");        return -2;    }    return shmid;}int creatShm(int size){    return commShm(size, IPC_CREAT|IPC_EXCL|0666);}int getShm(int size){    return commShm(size, IPC_CREAT);} int destroyShm(int shmid){    if(shmctl(shmid, IPC_RMID, NULL) < 0){        perror("shmctl");        return -1;    }       return 0; }  
#ifndef _COMM_H_#define _COMM_H_#include <stdio.h>#include <sys/ipc.h>#include <sys/shm.h>#define PATHNAME "."#define PROJ_ID 0x6666int creatShm(int size);int destroyShm(int shmid);int getShm(int size);#endif
#include "comm.h"int main(){    int shmid = creatShm(4097);    sleep(3);    char *addr = (char *)shmat(shmid, NULL, 0);          int i = 0;    while(1){        addr[i] = 'A' + i;        i++;        addr[i] = 0;        sleep(1);    }        shmdt(addr);    destroyShm(shmid);    return 0;} 

client.c

#include "comm.h"int main(){    int shmid = getShm(0);    sleep(3);    char *addr = (char *)shmat(shmid, NULL, 0);       while(1){        printf("%s\n",addr);            sleep(1);    }    shmdt(addr);    return 0;}

通过共享内存从server 里往 client里从A开始写,一次增加一个字符,然后从client端读到的现象为:



因为是通过system调用,所以它的生命周期是随内核。再来看两条指令;

查看系统中的共享内存: ipcs -m



删除共享内存 : ipcrm -m ID号



原创粉丝点击