目录
1、IPC简介
1.1、共享内存
1.1.1 创建/访问共享内存
1.1.2 映射
1.1.3 解除映射
1.1.4 删除/修改共享内存
1.2 信号量集
1.2.1 创建信号量集合
1.2.2 信号量的初始化
1.2.3 信号量的还原和消耗
1.3 消息队列
1.3.1 概念
1.3.3 添加消息队列
1.3.4 读取消息
1、IPC简介
IPC全称:Inter-Process Communication
功能:进程间通信多运用于多进程之间其中包括:共享内存,信号量集,消息队列;
查看系统的IPC的指令:
ipcs
分开查看:
共享内存 Shared memory ipcs -m 函数 shm 开头的
信号量集 Semaphore set ipcs -s 函数 sem 开头的
消息队列 Message Queue pcs -q 函数 msg 开头的
删除:
删除共享内存 ipcrm -m 共享内存的 id
删除信号量集 ipcrm -s 信号量集的 id
删除消息队列 ipcrm -q 消息队列的 id
获得键值:
存在的意义:保证多个进程访问的共享内存是同一个;或者多个进程访问的信号集是同一个,再或者多个进程访问的消息队列是同一个;
头文件:
# include <sys/types.h>
# include <sys/ipc.h>
函数原型:
key_t ftok(const char *pathname, int proj_id);
参数:
pathname:任何的存在的路劲/文件夹名;"/home/xxx"
proj_id:任意一个0-255之间的数值;
返回值:当成功执行的时候,一个key_t值将会被返回,否则 -1被返回
1.1、共享内存
1.1.1 创建/访问共享内存
作用:用来获得共享内存区域的ID,如果不存在指定的共享区域就创建相应的区域
头文件:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
函数原型:
int shmget(key_t key, size_t size, int shmflg);
参数:
key:键值,用ftok()获得;//任意进程均可使用
size:共享内存的大小
shmflg:IPC_CREAT|0600
IPC_CREAT:如果内有就创建,有就直接获取
返回值:成功返回内存段标识符,失败:-1
1.1.2 映射
作用:把共享内存区域映射到调用进程的地址空间中去
头文件:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
函数原型:
void *shmat(int shmid, const void *shmaddr, int shmflg);
参数:
shmid:要映射的共享内存区域标识符
shmaddr:将共享内存映射到指定位置,一般填NULL
shmflg:默认 0,共享内存可读写
返回值:
成功:被映射的段地址,失败:返回NULL
1.1.3 解除映射
作用:解除调用用来解除进程对共享区域的映射
头文件:
#include <sys/types.h>#include <sys/shm.h>
函数原型:
int shmdt(const void *shmaddr);
参数:被映射的共享内存段地址
返回值:成功返回0;失败返回-1
1.1.4 删除/修改共享内存
头文件:
#include <sys/ipc.h>
#include <sys/shm.h>
函数原型:
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
参数:
shmid:shmget的返回值
cmd:选择的操作
IPC_STAT:获取共享内存属性
IPC_SET:修改共享内存
IPC_RMID:删除共享内存,此时第三个参数为NULL
返回值:
成功0,失败-1
补充:
memcpy-- 内存复制
函数原型:
void *memcpy(void *destin, void *source, unsigned n);
参数:
destin: 指向用于存储复制内容的目标数组, 类型强制转换为 void* 指针。
source-- 指向要复制的数据源, 类型强制转换为 void* 指针。 n-- 要被复制的字节数。
返回值: 该函数返回一个指向目标存储区 destin 的指针。
1.2 信号量集
1.2.1 创建信号量集合
作用:创建一个信号量集或访问一个已存在的信号量集
头文件:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
函数原型:
int semget(key_t key, int nsems, int semflg);
参数:
key:键值
nsems:信号量集合中创建几组信号量,通常取值为1;
semflg:IPC_CREAT 表示若信号量已存在, 返回该信号量标识符; 不存在, 创建; IPC_CREAT|0600
返回值: 如果成功, 则返回信号量集的 IPC 标识符。 如果失败, 则返回-1
1.2.2 信号量的初始化
头文件:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
函数原型:
int semctl(int semid, int semnum, int cmd, ...);
参数:
semid:是由semget返回的信号量标识符
sumnum:你要操作的信号量集合中信号量的下标,第一组的下标是0;
cmd:
删除:IPC_RMID( 立即删除信号集, 唤醒所有被阻塞的进程)
设置: SETVAL( 根据 semnum 指定的编号设定相应信号的值, 此时需要填充第四个参数(用联合体中 val 成员的值设置信号量集合中单个信号量的值))
获取: GETVAL( 根据 semnum 指定的编号返回相应信号的值, 此时该函数返回值就是你要获得的信号量的值, 不再是 0 或-1)
如果有第四个参数类型
union semun {
short val; /*SETVAL 用的值*/
struct semid_ds* buf; /*IPC_STAT、 IPC_SET 用的 semid_ds 结构(则是一个内核结构体)*/
nsigned short* array; /*SETALL、 GETALL 用的数组值*/
struct seminfo *buf; /*为控制 IPC_INFO 提供的缓存(表示信号量系统资源配置信息)*/
} arg;
返回值
成功: 返回相应的值, 失败: 返回-1
举例:
key = ftok();
semid = semget(key,1,IPC_CREAT|0600);
union semun text;
text.val = 1;//二值信号量
semctl(semid,0,SETVAL,text);
1.2.3 信号量的还原和消耗
用于改变信号量对像中各个信号量的状态
函数原型:
int semop(int semid, struct sembuf *sops, unsigned nsops);
参数: semid: semget 返回值
sops: 对信号量的操作
struct sembuf{
unsigned short sem_num; //信号量的下标 0
short sem_op; //操作类型 +1 -1
sem_op > 0 信号加上 sem_op 的值, 表示进程释放控制的资源;
sem_op < 0 信号减去 sem_op 的值。
short sem_flg; //操作标志 0 设置信号量的默认操作
}
nsops: 进行操作信号量的个数, 即 sops 结构变量的个数, 需大于或等于 1。 最常见设置此值
等于 1, 只完成对一个信号量的操作
返回值: 成功时, 返回 0; 失败时, 返回-1
1.3 消息队列
1.3.1 概念
消息队列就是一个消息的链表,可以把消息看作一个记录,具有特定的格式以及特定的优先级。对消息队列有写权限的进程可以向其中按照一定的规则添加新信息,对消息队列有读权限的进程则可以从消息队列中读走消息。和队列的特点一样,遵从先进先出的原则。
1.3.2 创建新的消息队列获取已存在的消息队列
头文件:
#include <sys / types.h>
#include <sys / ipc.h>
#include <sys / msg.h>
函数原型:
int msgget(key_t key, int msgflg);
参数:key由ftok生成。
msgflg:IPC_CREAT|0600
IPC_CREAT 值, 若没有该队列, 则创建一个并返回新标识符; 若已存在, 则返回原标识
符。
返回值:
成功执行:返回消息队列标识符。失败返回-1.
1.3.3 添加消息队列
作用:把消息添加到已打开的消息队列末尾(尾差法)。
函数原型:
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
参数:
msgid:值明消息队列的ID,通常是msgget 函数成功的返回值
msgp:发送数据缓冲区首地址,指向消息结构的指针。
该消息结构 msgbuf 为:
struct msgbuf{
long mtype;//消息类型
char mtext[1];//消息正文:可以是数值/数组/结构体
}
消息必须是一个结构体, 并且结构体的第一个成员必须是消息类型(long);
msgsz: 数据大小, 注意, 改大小仅仅是数据大小, 需要用结构体整体大小减去消息类型
的大小, 每个消息体最大不要超过 4K;
sizeof(struct msgbuf) - sizeof(long);
msgflg: 一般赋 0, 阻塞方式
IPC_NOWAIT : 非阻塞
返回值: 成功则返回 0, 出错则返回-1
1.3.4 读取消息
作用:把消息从消息队列中取走,与FIFO不同的是,这里可以指定取走某种类型的消息(在该类型的消息中,依旧是FIFO)
函数原型:
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
参数:
msqid : 消息队列的队列 ID
msgp: 消息缓冲区 -- 提供空间 -- 结构体类型
msgsz: 消息的字节数 -- sizeof(结构体)-sizeof(long);
msgtyp: 消息类型
=0 忽略类型
>0 只接收指定类型的数据
<0 只接受小于等于其绝对值的数据
msgflg: 0: msgsnd 调用阻塞直到条件满足为止
IPC_NOWAIT 不阻塞
返回值: 接收成功返回 0, 失败返回-1
1.3.5 控制消息队列
函数原型:
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
参数:
msqid: 消息队列的队列 ID
cmd:
IPC_STAT: 读取消息队列的属性 msqid_ds, 并将其存储在 buf 指定的地址中
IPC_SET: 设置消息队列的属性 msqid_ds 中的 ipc_perm 元素的值。 这个值取自 buf 参数。
IPC_RMID: 从系统内核中移走消息队列, 此时最后一个写 NULL
Buf: 消息队列缓冲区
返回值:接收成功返回0,失败返回-1.