我们无论使用命名管道还是匿名管道,都是在文件层面上实现的通信,实际上还有基于系统层面的system v标准的进程间通信方式。
因为操作系统不相信用户,所以用户使用的时候只能通过调用的方式
进程间通信的本质:先让不同的进程看到同一份资源。
system v提供的主流方式有三个:
1.共享内存 2.消息队列(有些落伍)3.信号量
前两个以传送数据为目的,第三个以实现进程间同步后者互斥为目的。
共享内存
共享内存其实和我们之前在文件层面上进行通信的原理差不多,只不过是在操作系统层面上操作
通过系统调用,创造出一片新的内存空间,然后让两个进程都挂接到这个新的内存空间上,也就是把我们新开辟的内存空间,通过页表的映射在两个进程上,两个进程就可以拿到同一份地址空间
此时我们就让不同的进程看到了同一份资源,这种通信方案称之为共享内存
怎么创建一个共享内存:
使用shmget创建
key是自己自定义的
size通常是4kb的整数倍
shmflg有两种类型:
如果单独使用IPC_CREATE或者shmflg为0:如果不存在共享内存,则创建一个共享内存,如果创建的共享内存已经存在,直接返回当前已经存在的共享内存。(基本不会空手而归)
IPC_CREATE | IPC_EXCL:如果不存在共享内存,则创建;如果已经有了共享内存,则返回出错。意义在于如果我调用成功,得到的一定是一个最新的,没有被别人使用过的共享内存!
但是IPC_EXCL单独使用是没有意义的
使用ftok来共享
两个参数:自己设定的内存的路径,自己设定的id
增加两个概念:
key:是共享内存对于系统外部的标识符,通常是整数或字符串,也就是我们使用shemget创建共享内存时候的那个key
什么是ID:内核分配给文件的特有标识符,通常是整数
什么叫key的算法:生成id的算法
所以只要我们在生成共享内存的时候,只要我们内部的数据是一样的,并且生成id的key算法是一样的,那么这两个进程就可以共享同一块共享内存
key_t是一个特殊的类型,用于表示系统中的共享内存、消息队列和信号量等 IPC(进程间通信)机制中的键值,就像ssize_t一样
来写一个:
comm.h:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define MY_FIFO "./fifo"
#include<sys/shm.h>
#define PATH_NAME "./"
#define PROJ_ID 0X6666
#define SIZE 4097
shared.c:
#include"comm.h"
int main(){
key_t key=ftok(PATH_NAME,PROJ_ID);
if(key<0){
perror("key");
return 1;
}
int shmid=shmget(key,SIZE,IPC_CREAT|IPC_EXCL);
if(shmid<0){
per