使用 UNIX System V IPC 机制共享应用程序数据( 二 )


清单 2 显示了消息队列的消息提交部分 。
清单 2. 向消息队列提交消息的程序
#include
#include
#include
#include
#include
int main (void) {
key_t ipckey;
int mq_id;
struct { long type; char text[100]; } mymsg;
/* Generate the ipc key */
ipckey = ftok("/tmp/foo", 42);
printf("My key is %dn", ipckey);
/* Set up the message queue */
mq_id = msgget(ipckey, IPC_CREAT | 0666);
printf("Message identifIEr is %dn", mq_id);
/* Send a message */
memset(mymsg.text, 0, 100); /* Clear out the space */
strcpy(mymsg.text, "Hello, world!");
mymsg.type = 1;
msgsnd(mq_id, &mymsg, sizeof(mymsg), 0);
}
清单 2 中的代码包括了必要的头文件,然后定义了将在 main 函数中使用的变量 。第一要务是使用 /tmp/foo 作为命令文件和使用数字 42 作为 ID 来确定 IPC 密钥 。出于演示的目的,这里使用 printf(3c) 将密钥显示在屏幕上 。接下来,该代码使用 msgget 创建消息队列 。msgget 的第一个参数是 IPC 密钥,第二个参数是一组标志 。在该示例中,标志包括八进制权限(该权限允许具有 IPC 密钥的任何人完全使用该 IPC)和 IPC_CREAT 标志(此标志导致 msgget 创建队列) 。同样,结果被打印到屏幕上 。
将消息发送到队列是非常简单的 。在对消息中的内存空间清零之后,将一个熟悉的字符串复制到缓冲区的文本部分 。将消息类型设置为 1,然后调用 msgsnd 。msgsnd 预期接受的参数为队列 ID、一个指向数据的指针和数据的大小,以及一个指示是否阻塞该调用的标志 。如果该标志为 IPC_NOWAIT,则即使队列已满,该调用也会返回 。如果该标志为 0,则调用将阻塞,直至队列上的空间被释放、队列被删除或应用程序收到某个信号 。
该过程的客户端行为与此类似 。清单 3 显示了检索服务器发送的消息的代码 。
清单 3. 用于从队列检索消息的代码
#include
#include
#include
#include
#include
int main (void) {
key_t ipckey;
int mq_id;
struct { long type; char text[100]; } mymsg;
int received;
/* Generate the ipc key */
ipckey = ftok("/tmp/foo", 42);
printf("My key is %dn", ipckey);
/* Set up the message queue */
mq_id = msgget(ipckey, 0);
printf("Message identifIEr is %dn", mq_id);
received = msgrcv(mq_id, &mymsg, sizeof(mymsg), 0, 0);
printf("%s (%d)n", mymsg.text, received);
}
获得 IPC 密钥和消息队列标识符的过程与服务器的代码类似 。对 msgget 的调用不指定任何标志,因为服务器已经创建了队列 。如果应用程序的设计允许客户端在服务器之前启动,则客户端和服务器都必须指定权限和 IPC_CREAT 标志,以便其中首先启动的应用程序创建队列 。
然后 mq_clIEnt.c 调用 msgrcv 以从队列提取消息 。前三个参数指定消息队列标识符、指向将包含消息的内存空间的指针和缓冲区的大小 。第四个参数是类型参数,它允许您选择所要获得的消息:
如果类型为 0,则返回队列中的第一个消息 。
如果类型为正整数,则返回队列中的第一个该类型的消息 。
如果类型为负整数,则返回队列中具有最小值的第一个消息,且该最小值小于或等于指定类型的绝对值 。例如,如果要将 2 然后再将 1 添加到队列,则使用类型 -2 调用 msgrcv 将返回 1,因为它最小,尽管它是队列中的第二个消息 。
传递给 msgrcv 的第五个参数同样是阻塞标志 。清单 4 显示了实际操作中的客户端和服务器 。
清单 4. 客户端和服务器代码的输出
sunbox$ ./mq_server
My key is 704654099
Message identifier is 2

推荐阅读