1. 程式人生 > >訊息佇列所用到的函式 msgget() msgsnd() msgrcv() msgctl()

訊息佇列所用到的函式 msgget() msgsnd() msgrcv() msgctl()

  關於ftok函式,先不去了解它的作用來先說說為什麼要用它,共享記憶體,訊息佇列,訊號量它們三個都是找一箇中間介質,來進行通訊的,這種介質多的是。就是怎麼區分出來,就像唯一一個身份證來區分人一樣。你隨便來一個就行,就是因為這。只要唯一就行,就想起來了檔案的裝置編號和節點,它是唯一的,但是直接用它來作識別好像不太好,不過可以用它來產生一個號。ftok()就出場了。ftok函式具體形式如下:

    key_t ftok(const char *pathname, int proj_id);

    其中引數fname是指定的檔名,這個檔案必須是存在的而且可以訪問的。id是子序號,它是一個8bit的整數。即範圍是0~255。當函式執行成功,則會返回key_t鍵值,否則返回-1。在一般的UNIX中,通常是將檔案的索引節點取出,然後在前

面加上子序號就得到key_t的值。

int msgget(key_t key, int msgflg);建立一個訊息佇列

返回值: message queue identifier on success   -1 on error: errno = EACCESS (permission denied)

msgget()函式的第一個引數是訊息佇列物件的關鍵字(key),函式將它與已有的訊息隊
列物件的關鍵字進行比較來判斷訊息佇列物件是否已經建立。而函式進行的具體操作是由
第二個引數,msgflg 控制的。它可以取下面的幾個值:
IPC_CREAT :
如果訊息佇列物件不存在,則建立之,否則則進行開啟操作;
IPC_EXCL:
和IPC_CREAT 一起使用(用”|”連線),如果訊息物件不存在則建立之,否則產生一個
錯誤並返回。
如果單獨使用IPC_CREAT 標誌,msgget()函式要麼返回一個已經存在的訊息佇列物件
的識別符號,要麼返回一個新建立的訊息佇列物件的識別符號。如果將IPC_CREAT 和IPC_EXCL
標誌一起使用,msgget()將返回一個新建的訊息物件的識別符號,或者返回-1 如果訊息佇列
物件已存在。IPC_EXCL 標誌本身並沒有太大的意義,但和IPC_CREAT 標誌一起使用可
以用來保證所得的訊息佇列物件是新建立的而不是開啟的已有的物件。
除了以上的兩個標誌以外,在msgflg 標誌中還可以有存取許可權控制符。這種控制符的
意義和檔案系統中的許可權控制符是類似的。

最後,我們將使用msgget()函式建立一個更加簡便的封裝函式來作為本節的例子:
int open_queue( key_t keyval )
{
int qid;
if((qid = msgget( keyval, IPC_CREAT | 0660 )) == -1)
{
return(-1);
}
return(qid);
}
這個簡單的例子中唯一需要注意的一點就是在msgflg 中加入了存取許可權控制符0660。
其餘的部分請讀者自行分析。

 int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);往訊息佇列傳送

返回值: 0 on success-1 on error: errno = EAGAIN (queue is full, and IPC_NOWAIT was asserted)

 傳給msgsnd()函式的第一個引數msqid 是訊息佇列物件的識別符號(由msgget()函式得
到),第二個引數msgp 指向要傳送的訊息所在的記憶體,第三個引數msgsz 是要傳送資訊的
長度(位元組數),可以用以下的公式計算:
msgsz = sizeof(struct mymsgbuf) - sizeof(long);
第四個引數是控制函式行為的標誌,可以取以下的值:
0,忽略標誌位;
IPC_NOWAIT,如果訊息佇列已滿,訊息將不被寫入佇列,控制權返回呼叫函式的線
程。如果不指定這個引數,執行緒將被阻塞直到訊息被可以被寫入。

smgbuf結構體定義如下:

struct msgbuf

{

                     long   mtype;

                    char   mtext [x] ;  //長度由msgsz決定

}

msgflg 可設定為 IPC_NOWAIT 。如果訊息佇列已滿或其他情況無法送入訊息,則立即 返回 EAGIN

返回: 0 on success

-1 on error: errno = EAGAIN (queue is full, and IPC_NOWAIT was asserted)EACCES (permission denied, no write permission)EFAULT (msgp address isn't accessable – invalid)EIDRM (The message queue has been removed)EINTR (Received a signal while waiting to write)EINVAL (Invalid message queue identifier, nonpositivemessage type, or invalid message size)ENOMEM (Not enough memory to copy message buffer)


ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,從訊息佇列接收
                      int msgflg);

引數:

函式的前三個引數和msgsnd()函式中對應的引數的含義是相同的。第四個引數mtype

指定了函式從佇列中所取的訊息的型別。函式將從佇列中搜索型別與之匹配的訊息並將之返回。不過這裡有一個例外。如果mtype 的值是零的話,函式將不做型別檢查而自動返     回佇列中的最舊的訊息。第五個引數依然是是控制函式行為的標誌,取值可以是:0,表示忽略;IPC_NOWAIT,如果訊息佇列為空,則返回一個ENOMSG,並將控制權交回呼叫函式的程序。如果不指定這個引數,那麼程序將被阻塞直到函式可以從佇列中得到符合條件的訊息為止。如果一個client 正在等待訊息的時候佇列被刪除,EIDRM 就會被返回。如果     進程在阻塞等待過程中收到了系統的中斷訊號,EINTR 就會被返回。MSG_NOERROR,如果函式取得的訊息長度大於msgsz,將只返回msgsz 長度的資訊,剩下的部分被丟棄了。如果不指定這個引數,E2BIG 將被返回,而訊息則留在佇列中不     被取出。當訊息從佇列內取出後,相應的訊息就從佇列中刪除了。

msgbuf:結構體,定義如下:

struct msgbuf

{

                      long  mtype ;  //資訊種類

                       char   mtest[x];//資訊內容   ,長度由msgsz指定

}

msgtyp:  資訊型別。 取值如下:

 msgtyp = 0 ,不分型別,直接返回訊息佇列中的第一項

 msgtyp > 0 ,返回第一項 msgtyp與 msgbuf結構體中的mtype相同的資訊

msgtyp <0 , 返回第一項 mtype小於等於msgtyp絕對值的資訊

msgflg:取值如下:

IPC_NOWAIT ,不阻塞

IPC_NOERROR ,若資訊長度超過引數msgsz,則截斷資訊而不報錯。

返回值:

成功時返回所獲取資訊的長度,失敗返回-1,錯誤資訊存於error

Number of bytes copied into message buffer-1 on error: errno = E2BIG (Message length is greater thanmsgsz,no MSG_NOERROR)EACCES (No read permission)EFAULT (Address pointed to by msgp is invalid)EIDRM (Queue was removed during retrieval)EINTR (Interrupted by arriving signal)EINVAL (msgqid invalid, or msgsz less than 0)ENOMSG (IPC_NOWAIT asserted, and no message exists in the queue to satisfy the request)

訊息佇列傳輸資料的大小是有限制的,可以用ulimit -a命令檢視:

POSIX message queues     (bytes, -q) 819200