擁有夢想是一種智力,實現夢想是一種能力
概述
若是一個多線程的進程,由于各個線程共享一個地址空間,可以直接通過變量的形式進行通信。而進程linux查看信號量命令,由于各個進程獨占一個地址空間,我們需要一種通信機制來完成進程間的數據交互。本章介紹的是消息隊列,進程間的通信機制有以下幾種:
無名管道(pipe)
有名管道 (fifo)
信號()
V IPC
共享內存(share )
消息隊列( queue)
信號燈集( set)
套接字()
之間有區分與各自的運用場景,其中套接字通常使用在網絡服務,其他只能在本地場景下使用。筆者以后會逐一學習,本章介紹 V IPC中的消息隊列。
V IPC
VIPC引入了三種高級進程間的通信機制。一個IPC對象包含消息隊列、共享內寸和信號量。
V IPC對象
每個IPC對象有唯一的ID
IPC對象創建后一直存在,直到被顯式地刪除
每個IPC對象有一個關聯的KEY(其中進程的私有對象KTY值為0)
命令查看IPC對象
IPC對象是全局對象,可用ipcs,ipcrm等命令查看或刪除
ipcs-q:只顯示消息隊列
ipcs-s:只顯示信號量
ipcs-m:只顯示共享內存
ipcs–help:其他的參數
函數操作
創建一個IPC對象
進程創建IPC對象之前,先ftok生成一個key值。
#
#
key_t ftok(const char *path, int );
消息隊列
消息隊列是 V IPC對象的一種linux查看信號量命令,由消息隊列ID來唯一標識。消息隊列就是一個消息的列表。用戶可以在消息隊列中添加消息、讀取消息等
特點是消息隊列可以按照類型來發送/接收消息。
消息隊列結構
消息格式
通信雙方首先定義好統一的消息格式,用戶根據應用需求定義結構體類型
其中,首成員類型為long,代表消息類型(正整數),其他成員都屬于消息正文
typedef struct {
long mtype;
char mtext[64];
} MSG;
消息隊列使用步驟 打開/創建消息隊列 向消息隊列發送消息 從消息隊列接收消息 控制消息隊列
消息隊列創建/打開 –
#
#
int (key_t key, int );
消息發送 –
#
#
int (int msgid, const void *msgp, size,
int );
消息接收 –
#
#
int (int msgid, void *msgp, size, long ,
int );
控制消息隊列 –
#
#
int (int msgid, int cmd, *buf);
示例
兩個進程通過消息隊列輪流將鍵盤輸入的字符串發送給對方,接收并打印對方發送的消息
A.c
#include
#include
#include
#include
#include
typedef struct {
long mtype;
char mtext[64];
} MSG;
#define LEN (sizeof(MSG) – sizeof(long))
#define TypeA 100
#define TypeB 200
int main()
{
int msgid;
key_t key;

MSG buf;
if ((key = ftok(“.”, ‘q’)) == -1)
{
perror(“ftok”);
exit(-1);
}
if ((msgid = msgget(key, IPC_CREAT|0666)) < 0)
{
perror(“msgget”);
exit(-1);
}
while ( 1 )
{
buf.mtype = TypeB;
printf("input > ");
fgets(buf.mtext, 64, stdin);
msgsnd(msgid, &buf, LEN, 0);
if (strcmp(buf.mtext, "quit\n") == 0) exit(0);
msgrcv(msgid, &buf, LEN, TypeA, 0);
if (strcmp(buf.mtext, "quit\n") == 0) break;
printf("recv message : %s", buf.mtext);
}
msgctl(msgid, IPC_RMID, NULL);
return 0;

}
B.c
#include
#include
#include
#include
#include
typedef struct {
long mtype;
char mtext[64];
} MSG;
#define LEN (sizeof(MSG) – sizeof(long))
#define TypeA 100
#define TypeB 200
int main()
{
int msgid;
key_t key;
MSG buf;
if ((key = ftok(“.”, ‘q’)) == -1)
{

perror(“ftok”);
exit(-1);
}
if ((msgid = msgget(key, IPC_CREAT|0666)) < 0)
{
perror(“msgget”);
exit(-1);
}
while ( 1 )
{
msgrcv(msgid, &buf, LEN, TypeB, 0);
if (strcmp(buf.mtext, "quit\n") == 0) break;
printf("recv message : %s", buf.mtext);
buf.mtype = TypeA;
printf("input > ");
fgets(buf.mtext, 64, stdin);
msgsnd(msgid, &buf, LEN, 0);
if (strcmp(buf.mtext, "quit\n") == 0) exit(0);
}
msgctl(msgid, IPC_RMID, NULL);
return 0;
}
這樣,當A是發送端,B進程在等待接收。B接收到數據,成為發送端,A進程等待接收。直到一方發送'quit',發送端進程結束,接收端刪除消息隊列,結束。
注意的是,進程發送對方的類型,接收時指定自己的類型。