1、IPC资源简介

  除了管道、文件、以及信号以外,还有IPC这样一种进程间的通信手段。IPC的含义即就是进程间通信资源,它包含三种资源类型。

  (1)、共享内存;

  (2)、信号量;

  (3)、消息队列;

  使用ipcs可以查看当前系统中IPC资源的情况。

2、共享内存简介

  共享内存简而言之就是一句话:各个进程都能够共同访问的共享的内存区域。

  进程的特征:高度的独立性和封闭性,它能够直接访问的内存只能是自身所包含的。

  共享内存为了达到多个进程访问的效果,必然是独立于所有进程之外的内存区域。共享内存最终是受到操作系统内核管理。

  进程对于共享内存的操作与管理主要是:

  (1)、申请创建一个共享内存区域(操作系统内核是不可能主动为进程创建共享内存的!),操作系统内核得到申请然后创建。

  (2)、申请使用一个已存在的共享内存区域。

  (3)、申请释放共享内存区域(操作系统内核也是不可能主动释放共享内存区域的!),操作系统内核得到申请然后释放。

3、对于共享内存的编程

(1)、需要使用API : shmget()方法。

  int shmget(key_t key, size_t size, int shmflg);

  key_t其实就是long,key就是关键字,size大小,shmflg表示这块内存区域的标志。

  其返回值为共享内存ID(也就是一个编号)shmid,即就是某一个共享内存区域的唯一标识,该标识又是操作系统内核动态分配的。

代码实现创建一块共享内存

#include
#include
#include
#include
int main(void){    key_t key;    key = 0xabc00000;    int ret = shmget(key, 256, IPC_CREAT | IPC_EXCL | 0755);    if(ret == -1){        perror("");        return -1;     }   }

运行结果

ipcrm -m shmid:通过命令的方式删除共享内存。

(2)、说明key_t

  i>、key_t是一个long类型,是IPC资源外部约定的key(关键)值,通过key值映射对应的唯一存在的某一个IPC资源。

  ii>、通过key_t的值就能够判断某一个对应的共享内存区域在哪,是否已经创建等等。

  iii>、一个key值只能映射一个共享内存区域,但同时还可以映射一个信号量,而且还能同时映射一个消息队列资源,于是就可以使用一个key值管理三种不同的资源。

(3)、shmget()函数第三个参数的使用细节:

取值
说明
IPC_CREAT
创建一个新的共享内存
IPC_EXCL
判断key对应的共享内存是否已经存在

(4)、key_t值的产生,有两种方式:

  i>、把key值写死;

  ii>、根据文件的inode编号生成。需要调用的API:ftok()方法,该方法是获取指定文件的inode编号在根据第二个参数计算得到最终的一个整型量。

共享内存的获取:使用shmget()方法即可。IPC_EXCL

4、共享内存的使用

  共享内存的使用分为2个小的步骤:i>、建立进程与共享内存的映射关系;ii>、读/写(直接使用指针即可);iii>、如果对于共享内存的使用结束,此时就要断开与共享内存的映射。

  对于第一步来说,需要使用的API:shmat()方法。

  对于第三步来说,需要使用的API:shmdt()方法。

  被映射正在使用共享内存是否此时可以执行删除操作呢?

    :是,虽然可以执行删除操作,却不能将其直接删除掉。而是做了2个操作,i>、将其状态置为dest,ii>、将其key值置为0x00000000,IPC_PRIVATE值。

  当共享内存处于dest(待回收状态),则将其资源设为"私有"(只能将该共享资源分享给其子进程,其它进程无法创建于该资源的使用)。

5、共享内存的控制

 共享内存的控制信息可以通过shmctl()方法获取,会保存在struct_shmid_ds结构体中。

  共享内存的控制主要是shmid_ds,即就是共享内存的控制信息。

  API:int shmctl(int shmid, int cmd, struct shmid_ds *buf);

参数:

shmid:就是要被控制的共享内存的编号。

cmd:看执行什么操作(1、获取共享内存信息;2、设置共享内存信息;3、删除共享内存)。

可用命令 说明
IPC_STAT 从内核中拷贝获取共享内存信息,将其保存到第三个参数指针所指向的空间
IPC_SET 将第三个参数所指向的空间的值设置到内核的共享内存管理数据中
IPC_RMID 删除共享内存

6、编程实现

写入共享内存的一方:

#include
#include
#include
#include
int createShm(void){    key_t key = ftok("./tmp", 7);    int shmid = shmget(key, 256, IPC_CREAT | IPC_EXCL | 0755);    return shmid;}int main(void){    int shmid = createShm();    if(shmid == -1){        perror("");        return -1;    }    char *shmptr = (char *)shmat(shmid, NULL, 0);    if(shmptr == NULL){        perror("");        return -1;    }    sprintf(shmptr, "Hello I am writer, write to shm");    return 0;}

从共享内存读出的一方:

#include
#include
#include
#include
#include
int getShm(void){    key_t key = ftok("./tmp", 7);     return shmget(key, 256, IPC_EXCL | 0755);}int main(void){    int shmid = getShm();    if(shmid == -1){        perror("");        return -1;     }       char *shmptr = (char *)shmat(shmid, NULL, 0);     if(shmptr == NULL){        perror("");        return -1;     }       char buf[80];    memset(buf, 0, sizeof(buf));    strncpy(buf, shmptr, 80);    printf("buf content : %s\n", buf);        return 0;}

运行结果

共享内存的应用场景

  a) 应用场景:将共享内存视作公告板;

  b) 方式与规则:i>、通常只有少量的进程对其进行写操作,大部分的进程只能进行读操作;

  ii>、独占的写方式,写的时候既不能其它进程写也不能其它进程读。