进程间通信(IPC)

UNIX系统IPC就是进程间通讯方式的统称,所有进程间通讯的方式有三种类型,即半双工管道,System V IPC /POSIX IPC和网络进程间通讯。

   本实验涉及到System V IPC /POSIX IPC类型,System V IPC /POSIX IPC又包括三种进程通信方式,即消息队列、信号量以及共享存储器,实验中我采用了消息队列的方式。

消息队列是一个消息的链表,该表由内核进行维护及存储,通过一个消息的类型来索引指定的数据。消息队列在两个进程间通讯如下图所示:

进程间通信(IPC)

以下为一读取消息队列实例:

发送方代码:

进程间通信(IPC)

接收方代码:

进程间通信(IPC)

读写消息队列的运行结果如下所示:


进程间通信(IPC)

用消息队列实现的简单聊天程序

代码分析:

每一个SystemV 对象(消息队列,共享内存和信号量)创建时,需要的第一个参数是整数的Key值,
头文件<sys/types.h>把key_t定义为一个整数
 •  System V创建对象时假设进行IPC通讯双方都取了相同的key值.这样将双方关联起来
 •  生成key的方法有三种
–双方直接设置为一个相同的整数为key值
–用IPC_PRIVA让系统自动产生一个key值,
–用ftok函数将一个路径转换为key值
ftok()。它有两个参数,一个是字符串,一个是字符。字符串一般用当前进程的程序名,字符一般用来标记这个标识符所标识的共享内存是这个进程所开辟的第几个共享内存。ftok()会返回一个key_t型的值,也就是计算出来的标识符的值。

Send端代码如下所示:

进程间通信(IPC)

进程间通信(IPC)

Receive代码:

进程间通信(IPC)

进程间通信(IPC)

整个消息队列通信的实现基本由三个部分构成:

首先是创建消息队列:在程序中使用msgget函数来创建和打开一个队列,每个进程通讯对象都对应一个key参数,我在代码中实现个队列如下:

进程间通信(IPC)

IPC_CREAT | IPC_EXCL | 0666实现一个权限为0666的消息队列,其中组用户、当前用户以及其他用户拥有读写的权限。在程序最后可以使用system(“ipcs -q”)来查看系统中进程通信的状态。

Msgctl函数可以在队列上做多种操作,其中很有用的操作是删除指定的队列,虽然在代码中没有体现这一操作,但在后面的代码优化中还是有帮助的,具体实现如下:

进程间通信(IPC)

其中IPC_RMID参数就是执行删除队列操作的。

下面我开始进行读写消息队列的编写,先来看看写操作:为了实现可以多次写入数据,我把写操作放在一个while循环中:

进程间通信(IPC)

先通过fget函数将写入的数据存入buff中,在通过msgsend函数实现将数据传到队列中去,&pmsg指向一个msgbuf的结构,qid则指定了操作的队列。

读取消息可以使用msgrcv,从队列中读取消息,代码如下:

进程间通信(IPC)

参数&pmsg指向接收数据的缓冲区,这个buff在qid指定的队列中,其中实现AB两个进程互相通信的关键一个参数时“1”的设置,1代表了消息类型,在send端定义的发送消息类型为1,而在receive端定义的消息类型为2,这样当send端要接收数据时则通过msgrcv函数的type参数就可以接收到receive端发送的数据而不是接收到自己发送的数据。

进程间通信(IPC)

代码只通过队列的方式实现了简单的聊天通讯功能,send和receive端可以进行一对一的半双工的通讯,由于我只是用了一个队列,所以每次必须先运行send后运行receive,退出时先通过receive发出quit命令给send端,然后send端接收到quit后再执行一次quit命令即可AB进程全部退出,由于最近时间较紧,本实验先做到这里,后面还会进行改进实现功能更加完善的聊天程序。






上一篇:使用systemtap调试linux内核


下一篇:编程习惯-函数无参数用void填充