3、For Example
下面寫(xiě)了一個(gè)簡(jiǎn)單的使用消息隊(duì)列進(jìn)行IPC的例子,服務(wù)端程序一直在等待特定類型的消息,當(dāng)收到該類型的消息以后,發(fā)送另一種特定類型的消息作為反饋,客戶端讀取該反饋并打印出來(lái)。
msg_server.c
// 用于創(chuàng)建一個(gè)唯一的key
// 消息結(jié)構(gòu)
struct msg_form {
long mtype;
char mtext[256];
};
int main()
{
int msqid;
key_t key;
struct msg_form msg;
// 獲取key值
if((key = ftok(MSG_FILE,'z')) < 0)
{
perror("ftok error");
exit(1);
}
// 打印key值
printf("Message Queue - Server key is: %d.\\n", key);
// 創(chuàng)建消息隊(duì)列
if ((msqid = msgget(key, IPC_CREAT|0777)) == -1)
{
perror("msgget error");
exit(1);
}
// 打印消息隊(duì)列ID及進(jìn)程ID
printf("My msqid is: %d.\\n", msqid);
printf("My pid is: %d.\\n", getpid());
// 循環(huán)讀取消息
for(;;)
{
msgrcv(msqid, &msg, 256, 888, 0);// 返回類型為888的第一個(gè)消息
printf("Server: receive msg.mtext is: %s.\\n", msg.mtext);
printf("Server: receive msg.mtype is: %d.\\n", msg.mtype);
msg.mtype = 999; // 客戶端接收的消息類型
sprintf(msg.mtext, "hello, I'm server %d", getpid());
msgsnd(msqid, &msg, sizeof(msg.mtext), 0);
}
return 0;
}
msg_client.c
// 用于創(chuàng)建一個(gè)唯一的key
// 消息結(jié)構(gòu)
struct msg_form {
long mtype;
char mtext[256];
};
int main()
{
int msqid;
key_t key;
struct msg_form msg;
// 獲取key值
if ((key = ftok(MSG_FILE, 'z')) < 0)
{
perror("ftok error");
exit(1);
}
// 打印key值
printf("Message Queue - Client key is: %d.\\n", key);
// 打開(kāi)消息隊(duì)列
if ((msqid = msgget(key, IPC_CREAT|0777)) == -1)
{
perror("msgget error");
exit(1);
}
// 打印消息隊(duì)列ID及進(jìn)程ID
printf("My msqid is: %d.\\n", msqid);
printf("My pid is: %d.\\n", getpid());
// 添加消息,類型為888
msg.mtype = 888;
sprintf(msg.mtext, "hello, I'm client %d", getpid());
msgsnd(msqid, &msg, sizeof(msg.mtext), 0);
// 讀取類型為777的消息
msgrcv(msqid, &msg, 256, 999, 0);
printf("Client: receive msg.mtext is: %s.\\n", msg.mtext);
printf("Client: receive msg.mtype is: %d.\\n", msg.mtype);
return 0;
}
四、信號(hào)量
信號(hào)量(semaphore)與已經(jīng)介紹過(guò)的 IPC 結(jié)構(gòu)不同,它是一個(gè)計(jì)數(shù)器。信號(hào)量用于實(shí)現(xiàn)進(jìn)程間的互斥與同步,而不是用于存儲(chǔ)進(jìn)程間通信數(shù)據(jù)。
1、特點(diǎn)
- 信號(hào)量用于進(jìn)程間同步,若要在進(jìn)程間傳遞數(shù)據(jù)需要結(jié)合共享內(nèi)存。
- 信號(hào)量基于操作系統(tǒng)的 PV 操作,程序?qū)π盘?hào)量的操作都是原子操作。
- 每次對(duì)信號(hào)量的 PV 操作不僅限于對(duì)信號(hào)量值加 1 或減 1,而且可以加減任意正整數(shù)。
- 支持信號(hào)量組。
2、原型
最簡(jiǎn)單的信號(hào)量是只能取 0 和 1 的變量,這也是信號(hào)量最常見(jiàn)的一種形式,叫做二值信號(hào)量(Binary Semaphore)。而可以取多個(gè)正整數(shù)的信號(hào)量被稱為通用信號(hào)量。
Linux 下的信號(hào)量函數(shù)都是在通用的信號(hào)量數(shù)組上進(jìn)行操作,而不是在一個(gè)單一的二值信號(hào)量上進(jìn)行操作。
// 創(chuàng)建或獲取一個(gè)信號(hào)量組:若成功返回信號(hào)量集ID,失敗返回-1
intsemget(key_t key, int num_sems, int sem_flags);
// 對(duì)信號(hào)量組進(jìn)行操作,改變信號(hào)量的值:成功返回0,失敗返回-1
intsemop(int semid, struct sembuf semoparray[], size_t numops);
// 控制信號(hào)量的相關(guān)信息
intsemctl(int semid, int sem_num, int cmd, ...);
當(dāng)semget創(chuàng)建新的信號(hào)量集合時(shí),必須指定集合中信號(hào)量的個(gè)數(shù)(即num_sems),通常為1;如果是引用一個(gè)現(xiàn)有的集合,則將num_sems指定為 0 。
在semop函數(shù)中,sembuf結(jié)構(gòu)的定義如下:
struct sembuf
{
short sem_num; // 信號(hào)量組中對(duì)應(yīng)的序號(hào),0~sem_nums-1
short sem_op; // 信號(hào)量值在一次操作中的改變量
short sem_flg; // IPC_NOWAIT, SEM_UNDO
}
其中 sem_op 是一次操作中的信號(hào)量的改變量:
- 若sem_op > 0,表示進(jìn)程釋放相應(yīng)的資源數(shù),將 sem_op 的值加到信號(hào)量的值上。如果有進(jìn)程正在休眠等待此信號(hào)量,則換行它們。
- 若sem_op < 0,請(qǐng)求 sem_op 的絕對(duì)值的資源。
- sem_flg 指定IPC_NOWAIT,則semop函數(shù)出錯(cuò)返回
EAGAIN
。 - sem_flg 沒(méi)有指定IPC_NOWAIT,則將該信號(hào)量的semncnt值加1,然后進(jìn)程掛起直到下述情況發(fā)生:
- 當(dāng)相應(yīng)的資源數(shù)可以滿足請(qǐng)求,此信號(hào)量的semncnt值減1,該信號(hào)量的值減去sem_op的絕對(duì)值。成功返回;
- 此信號(hào)量被刪除,函數(shù)smeop出錯(cuò)返回EIDRM;
- 進(jìn)程捕捉到信號(hào),并從信號(hào)處理函數(shù)返回,此情況下將此信號(hào)量的semncnt值減1,函數(shù)semop出錯(cuò)返回EINTR
- 如果相應(yīng)的資源數(shù)可以滿足請(qǐng)求,則將該信號(hào)量的值減去sem_op的絕對(duì)值,函數(shù)成功返回。
- 當(dāng)相應(yīng)的資源數(shù)不能滿足請(qǐng)求時(shí),這個(gè)操作與sem_flg有關(guān)。
- sem_flg 指定IPC_NOWAIT,則semop函數(shù)出錯(cuò)返回
- 若sem_op == 0,進(jìn)程阻塞直到信號(hào)量的相應(yīng)值為0:
- sem_flg指定IPC_NOWAIT,則出錯(cuò)返回EAGAIN。
- sem_flg沒(méi)有指定IPC_NOWAIT,則將該信號(hào)量的semncnt值加1,然后進(jìn)程掛起直到下述情況發(fā)生:
- 信號(hào)量值為0,將信號(hào)量的semzcnt的值減1,函數(shù)semop成功返回;
- 此信號(hào)量被刪除,函數(shù)smeop出錯(cuò)返回EIDRM;
- 進(jìn)程捕捉到信號(hào),并從信號(hào)處理函數(shù)返回,在此情況將此信號(hào)量的semncnt值減1,函數(shù)semop出錯(cuò)返回EINTR
- 當(dāng)信號(hào)量已經(jīng)為0,函數(shù)立即返回。
- 如果信號(hào)量的值不為0,則依據(jù)sem_flg決定函數(shù)動(dòng)作:
在semctl函數(shù)中的命令有多種,這里就說(shuō)兩個(gè)常用的:
- SETVAL:用于初始化信號(hào)量為一個(gè)已知的值。所需要的值作為聯(lián)合semun的val成員來(lái)傳遞。在信號(hào)量第一次使用之前需要設(shè)置信號(hào)量。
- IPC_RMID:刪除一個(gè)信號(hào)量集合。如果不刪除信號(hào)量,它將繼續(xù)在系統(tǒng)中存在,即使程序已經(jīng)退出,它可能在你下次運(yùn)行此程序時(shí)引發(fā)問(wèn)題,而且信號(hào)量是一種有限的資源。
-
Linux
+關(guān)注
關(guān)注
87文章
11304瀏覽量
209543 -
IPC
+關(guān)注
關(guān)注
3文章
347瀏覽量
51921 -
進(jìn)程間通信
+關(guān)注
關(guān)注
0文章
16瀏覽量
2434
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論