进 程 间 通 信
2: system V 的IPC通信:
IPC 对象 ===》进程间通信 ===》IPC对象: 消息队列 共享内存 信号量集
基本通信框架:
key ==>IPC对象 ===》读写 ===》关闭 ===》卸载
key值的获取:
1、通过ftok函数获取
2、使用IPC_PRIVATE私有键值
3、使用自定义的键值
头文件: sys/ipc.h
sys/types.h
原型:key_t ftok(const char *pathname, int proj_id);
功能:根据指定的pathname的文件路径+名称,用参数二的id运算后得到
的一个唯一键值。
参数:pathname 文件路径+名称,该文件不能被删除重建,可能得到不同
的键值。
proj_id 整形数字,一般用于计算键值,取128以内的数字居多。
类似一种简单加密算法。
返回值:成功 返回一个唯一键值
失败 -1;
IPC_PRIVATE ===>0X00000000 ====>只能用于有亲缘关系的进程使用。
自定义键值 ===》0x01068888 ===>企业中大量使用的自定义键值。
IPC对象 ==》消息队列
1、操作流程: key ===》创建并打开消息队列===》读写队列 ==》删除队列
msgget() msgrcv/msgsnd msgctl
#include <sys/msg.h>
原型:int msgget(key_t key, int msgflg);
功能:根据指定的key值,向内核提出消息队列的使用申请,
同时用msgflg方式创建一个消息队列的访问权限。
参数: key 之前已经获取/定制的唯一键值
msgflg 消息队列的创建权限,用0664等八进制表示
注意:如果之前没有该消息队列则内核自动创建该队列IPC_CREAT
如果之前经创建号队列,则会返回异常,IPC_EXCL检测
返回值:成功 返回一个有效的消息队列id,一般用msgid表示
失败 -1;
IPC对象是否存在可以手工维护:
ipcs -a ==>查看所有的IPC对象信息。
ipcs -q ==>只查看消息队列信息
ipcs -m ==>只查看共享内存信息
ipcs -s ==>只查看信号量信息
ipcs -lq ==>查看当前消息队列对象的上限设置。
ipcrm -q msgid 手工删除指定的消息队列对象。
读写消息队列:
1、写 msgsnd
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
功能:向经申请好的消息对象msqid中写入来自msgp中大小为msgsz的数据。
参数:msqid 要操作的消息队列id
msgp 要写的数据来源。一般用如下结构表示
struct msgbuf
{
long mtype; 消息的类型,大于0 的数字。
char mtext[128]; 消息的内容
};
msgsz 消息的正文长度,一般等于mtext的长度。
msgflg 消息的发送方式,0 表示阻塞发送。IPC_NOWAIT 非阻塞方式。
返回值:成功 0
失败 -1;
2、读 msgrcv
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,
int msgflg);
功能:从指定的msqid消息队列中,获取长度为msgsz字节,类型为msgtyp
的数据写入到本地的msgp内存空间。
参数:msgid 消息队列id
msgp 要存储消息的内存,一般是动态内存的数组或者malloc
msgsz 要存储的数据正文长度。
msgtyp 要获取的数据类型,大于0 的数字。
msgflg 接受方式,0 阻塞接受,IPC_NOWAIT 非阻塞接受
返回值:成功 收到的有效数据长度,等于实际的发送数据。
失败 -1;
练习:
设计两个程序,一个用来获取用户输入信息,并按照不同
类型存储到消息队列中。另一个从消息队列中指定读取
一种类型的数据。
3、消息队列对象的卸载:msgctl
原型:int msgctl(int msqid, int cmd, struct msqid_ds *buf);
功能:该函数用于控制修改消息队列的属性,可以删除对象。
参数: msqid 消息队列id
cmd 要执行的命令:
IPC_RMID 表示删除对象
buff 对象的属性,一般不做调整,用NULL表示。
返回值:成功 0
失败 -1;
1、sizeof(buff)-sizeof(long) 含义的理解
2、结构体中新增加一个int类型,放到long 与 char之间使用正常
在char之后内容是任意数字。
3、msgrcv 参数2 写为 buff.mtext &buff.mtext 不能获取数据
4、key 值的作用?
5、msgctl 函数中的参数3的属性?
6、信号 中alarm(?) 与 void fun(int sig) 之间的关系
IPC 通信之 共享内存 ===》效率最高的通信方式
操作流程:
key ==>申请共享内存 ==》映射共享内存==》读写共享内存
==》撤销映射内存 ===》删除共享内存
shmget shmat read/write... shmdt shmctl
#include <sys/shm.h>
原型:int shmget(key_t key, size_t size, int shmflg);
功能:该函数可以向内核提出共享内存使用申请。
参数:key 申请之前要定义的唯一键值。
size 要申请的共享内存大小,单位字节
shmflg 要申请的共享内存访问权限。如果第一次
申请用IPC_CREAT创建
如果是第二次申请用 IPC_EXCL 检测
返回值: 成功 共享内存id, shmid
失败 -1
原型:void *shmat(int shmid, const void *shmaddr, int shmflg);
参数:shmid 共享内存id
shmaddr 要将共享内存id对应的内核中的地址映射到本地的地址值。
当不能确认准确的本地地址值时候用NULL表示有OS 自动匹配。
shmflg 映射之后的内存访问权限
返回值:成功 表示映射成功的本地地址。
失败 NULL
1、如何通过共享内存传递数字
2、共享内存共享的数据是以那种数据结构形式存储
读完之后是否还存在?
原型:int shmdt(const void *shmaddr);
功能:断开当前内核与应用程序之间的内存映射。
参数: shmaddr 要断开的地址,一般等于shmat的返回值。
返回值:成功 0
失败 -1;
原型:int shmctl(int shmid, int cmd, struct shmid_ds *buf);
功能:该函数用于调整共享内存的属性信息,可以用来删除对象。
参数:shmid 要删除的共享内存id
cmd ==》IPC_RMID 表示删除对象
buff ===》NULL 表示不对共享内存属性调整。
返回值:成功 0
失败 -1
作业:
设计一个父子进程的双进程程序,完成父进程获取用户输入信息
并写入消息队列/共享内存 ,子进程完成信息的输出和文件的写入
最后保留文件。