前言:进程间的通信方式包括
IPC:
1、管道
pipe 无名管道
fifo 有名管道
2、信号 signal
3、消息队列 System V消息队列 / POSIX消息队列
4、共享内存 System V共享内存 / POSIX共享内存 <-----------
5、信号量 System V信号量 / POSIX信号量
6、socket套接字
1、共享内存
共享内存是进程间通信的一种方式,多个进程共享一段内存空间 “共享内存”
由于多个进程共享同一个内存,你往这个内存中写入数据,实际上就是往我的内存中写入数据
随内核的持续性
实现方式:
在内核中开辟了一块空间,其他进程通过 “内存映射” 的方式
获取到这个共享内存的首地址
进程p1可以映射这段内存,其他进程p2也可以映射这段内存
p1往这段内存中写入数据,实际上就是往p2中写入数据
2、System V 共享内存的相关接口函数
System V IPC (msg/shm/sem) 操作流程:
(1)获取键值key
(2)创建或打开一个IPC对象,获取IPC对象的id
(3)操作:发送/接收
(4)其他控制操作: 删除/获取、设置属性/...
1)获取键值key - ftok函数
2)创建或者打开一个System V共享内存 shmget
NAME
shmget - allocates a System V shared memory segment
SYNOPSIS
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, size_t size, int shmflg);
功能:获取一块共享内存
参数:
key: 共享内存的键值
size: 共享内存的大小 ,单位 字节
当实际操作是 创建一个新的共享内存时,必须指定一个不为0的size值
当实际操作是 打开一个共享内存时,那么size==0
shmflg: 标志
(1)创建标志
IPC_CREAT | 权限
例子:
IPC_CREAT | 0666
注意:
如果创建失败的原因 是因为已经存在了
且 创建的标志为 IPC_CREAT | IPC_EXCL 一起使用
此时 errno == EEXIST
(2)打开标志
0
返回值:
成功,返回共享内存的id
失败,返回-1,并设置errno
3)共享内存的映射和解映射
NAME
shmat, shmdt - System V shared memory operations
SYNOPSIS
#include <sys/types.h>
#include <sys/shm.h>
void *shmat(int shmid, const void *shmaddr, int shmflg);
功能:用来映射一个System V共享内存到进程的地址空间
参数:
shmid: 共享内存的id
shmaddr:指定映射到进程地址空间的哪个位置上
一般为 NULL 让它自行分配
shmflg:映射标志
SHM_RDONLY 只读
0 可读可写
返回值:
成功,返回映射区域的首地址
失败,返回(void *) -1,同时errno被设置
int shmdt(const void *shmaddr);
功能:解除映射
参数:
shmaddr: 映射区域的首地址
返回值:
成功,返回0
失败,返回-1,并设置errno
创建一个共享内存,实现父子进程的通信 子进程 --》 写入数据 父进程 --》 读取数据,并打印 #define PATHNAME "/home/china/"int main() {//1.获取键值key key_t key = ftok( PATHNAME, 5 );if( key == -1 ){perror("ftok error ");return -1;}printf("key = 0x%x\n", key );//2.创建或打开一个System V共享内存 int shm_id = shmget( key, 4096, IPC_CREAT | IPC_EXCL | 0666 );if( shm_id == -1 ){if( errno == EEXIST ) //已经存在 就直接打开{shm_id = shmget( key, 0, 0 );}else {perror("shmget error ");return -1;}}printf("shm_id = %d\n", shm_id );//3.映射 char * p = shmat( shm_id, NULL, 0 );if( p == NULL ){perror("shmat error ");return -1;}//4.创建一个子进程 pid_t pid = fork();if( pid > 0 ) //父进程 {//等待子进程退出 wait( NULL );//读取数据,打印printf("father : %s\n", p );//5.解除映射 shmdt( p );}else if( pid == 0 ) //子进程 {//写入数据printf("child : ");fgets( p, 128, stdin );}else {perror("fork error ");shmdt( p );return -1;}}
4)共享内存的控制操作shmctl
NAME
shmctl - System V shared memory control
SYNOPSIS
#include <sys/ipc.h>
#include <sys/shm.h>
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
功能:对共享内存的其他控制操作
参数:
shmid: 共享内存id
cmd: 命令号
IPC_RMID 删除
IPC_STAT 获取属性
IPC_SET 设置属性
...
buf: 结构体指针 , 具体根据cmd的不同,有不同含义
如果 cmd == IPC_RMID ,那么就填 NULL
返回值:
成功,返回0
失败,返回-1,同时errno被设置
struct shmid_ds {struct ipc_perm shm_perm; /* Ownership and permissions */size_t shm_segsz; /* Size of segment (bytes) */time_t shm_atime; /* Last attach time */time_t shm_dtime; /* Last detach time */time_t shm_ctime; /* Last change time */pid_t shm_cpid; /* PID of creator */pid_t shm_lpid; /* PID of last shmat(2)/shmdt(2) */shmatt_t shm_nattch; /* No. of current attaches */...};