在做linux多任務編程的時候,難免會碰到要使用IPC技術了,但是很多人都對這些技術只知其名,不知道如何使用。為了大家都能很好的學習Linux,本人不才,貼出了自己寫的 訊息佇列 編程,用的是多線程,不是多進程,原理一樣。以後有時間會後續把其他幾個技術一一詳解,並貼上代碼。好了,廢話不多說,進入下面的執行個體講解。
/*****************************************************
**標頭檔包含
****************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h> //ftok, msgget, msgrcv, msgsnd
#include <sys/ipc.h> //ftok, msgget, msgrcv, msgsnd
#include <sys/msg.h> //ftok, msgget, msgrcv, msgsnd
#include <pthread.h> //多線程
#include <string.h> //memcpy
#include <unistd.h>
#define KEYFILE "/root/work/msgqueue" //產生系統唯一的索引值所用,這個目錄或檔案一定要存在
#define PROJID 10 //產生系統唯一的索引值項目號。
struct msg{
long type; //訊息類型
char buf[512]; //訊息內容
};
/*******************************************************
**建立系統唯一的索引值,為msgget所用,也可以不
**用調用此函數,用一個常數代替key,但是為避免
**建立的訊息佇列失敗,建議用此方法。
*******************************************************/
key_t CreateMsgKey()
{
return ftok(KEYFILE,PROJID);//系統調用,返回一個系統唯一的索引值。
}
/********************************************************
**下面是建立一個線程,並設定為分離態,這個應該
**就不需要多說了吧。
*********************************************************/
pthread_t createthread(void* (*fun)(void *),void *arg)
{
pthread_t threadId;
pthread_attr_t attr;
memset(&attr,0,sizeof(attr));
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
return pthread_create(&threadId,&attr,fun,arg);
}
/*******************************************
**待會要建立的線程工作函數,此線程
**每隔2秒向訊息佇列裡發一條訊息。
********************************************/
void *DoSndMsg(void *arg)
{
struct msg SndMsg;
long iCount=1;
SndMsg.type=100;//訊息類型為100
int msgid=0;
msgid=msgget(*(key_t *)arg,IPC_CREAT);//擷取訊息佇列的ID,arg是由進程傳進來的key,IPC_CREAT表示建立一個新的
//訊息佇列,如果,如果key已經建立了訊息佇列,則返回已經建立的訊息佇列ID。
//如果IPC_EXCL | IPC_CREAT一起用,如果key已經建立了訊息佇列,則返回錯誤。
printf("msgid is:%d\n",msgid); //列印下msgid
while(iCount>0)
{
iCount+=1;;
memcpy(SndMsg.buf,&iCount,sizeof(iCount));
msgsnd(msgid,&SndMsg,sizeof(SndMsg),IPC_NOWAIT);//把sndmsg裡的訊息發送到msgid的訊息佇列裡,IPC_NOWAIT表示
//不阻 塞。
printf("iCount is:%ld\n",iCount);
sleep(2);
}
return NULL;
}
int main()
{
pthread_t sndThread;
struct msg rcvMsg;
int msgid;
long rcvCount=0;
key_t msgkey;
msgkey=CreateMsgKey(); //建立key
sndThread=createthread(DoSndMsg,&msgkey);//建立線程。
msgid=msgget(msgkey,IPC_CREAT);//擷取訊息佇列ID
printf("msgid is:%d\n",msgid);
while(rcvCount==0)
{
msgrcv(msgid,&rcvMsg,sizeof(rcvMsg),0,IPC_NOWAIT);//接收msgid裡第一條訊息,0的位置是訊息類型,0,表示訊息佇列
//第一條訊息,大於零的值則表示收取相應訊息類型的訊息。
memcpy(&rcvCount,rcvMsg.buf,sizeof(rcvCount));
printf("msgtype:%ld\n",rcvMsg.type);
printf("rcvCount is:%ld\n",rcvCount);
sleep(2);
rcvCount=0;
}
return EXIT_SUCCESS;
}
系統調用msgrcv中的參數type非常的重要,這個形參決定讀取訊息佇列中哪一條訊息,unix環境進階編程裡做了很好的總結,現在分享給大家。
type==0, 表示讀取訊息佇列中的第一條訊息(任何類型的訊息都接收);
type>0, 表示讀取訊息佇列中類型為type的第一條訊息(如果有多條同類型訊息,一次唯讀最前面的一條訊息);
type<0, 表示讀取訊息佇列中類型為小於或者大於type絕對值的第一條訊息。