高级编程之进程间通信(二)

进 程 间 通 信

 

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


作业:
 设计一个父子进程的双进程程序,完成父进程获取用户输入信息
 并写入消息队列/共享内存 ,子进程完成信息的输出和文件的写入
 最后保留文件。

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值