IPC( InterProcess Communication ) 不同 process 之間傳遞訊系。 http://bbs3.nsysu.edu.tw/txtVersion/treasure/mis-OS/M.952573483.A/M.952663880.A.html man ipcs man msgget, msgctl, msgsnd, msgrcv 簡單來說,就是跟系統註冊一個郵政信箱,然後要傳送訊息和接受訊息都經過此信箱。 Message Send 先使用 msgget( key_t, msgflg ),跟系統註冊一個郵政信箱。 使用 key_t 做為註冊的代號,注意 key_t 為十六進位。 msgget 回傳 messagequeue 的 id,之後 msgsnd 就使用此 id。 msgsnd( int msgid, const void *msgp, size_t msgs, int msgflg ); msgid 為 使用 msgget 傳回的 id msgp 為 傳送資料的 pointer msgs 為 傳送資料的大小 msgflg 不同的 flag 有不同的作用,請查 man 送出資料後,可利用 ipcs -a ,可以看到系統有多出 Message Queues 等待著。 Message Receive 同樣先使用 msgget 取得相同 key_t 之下的 id。 msgrcv( int msgid, void *msgp, size_t msgs, long msgtyp, int msgflg ); msgid 和 msgsnd 一樣,藉由 msgget 取得的 messagequeue 的 id msgp 為 接收資料的 pointer msgs 為 接收的大小 msgtyp 為 接收資料的型態,稍後說明 msgflg 請查 man msgrcv 之後,也可使用 ipcs -a,來查看系統 Message Queues 的狀態。 通常我們會把要傳送的資料定義為一個結構 struct msg { long type; char[1]; } long type 可為這次發送的訊息指定類別。 char[1] 只是個簡單的範例,可以擴展到不只一個資料型態。 送出訊息的時候,可以指定這次訊息的 type。 想像 msgget 已經跟系統要到一個郵政信箱,但是我們還是可以再加上 type 來指定不同的收信人。 msgrcv 假設指定 type 為 100,則會去尋找在 messagequeue 中送訊息的 type 也是 100 的。 這樣可以利用同一個 key_t 再加上不同的 type,可以只利用同個 messagequeue 但卻讓不同的 process 收到不一樣的消息。 在 msgflg 中可以用不同的 flag ,讓 type 在接收訊息的時候更有彈性。 ----------------------------- /*msgsnd.c *euphonium *2008/12/05 */ #include #include #include #include #include struct msgbuf { long type; int var; char text[20]; }sndbuf, *msgp; int main() { int msgid; key_t KEY = 0x200; int msgtyp = 1000; msgp = &sndbuf; sndbuf.type = msgtyp; sndbuf.var = 10; strcpy( sndbuf.text, "Test File" ); if( ( msgid = msgget(KEY, 0) ) == -1 ) {//msgqueue not exist if( ( msgid = msgget(KEY, IPC_CREAT|0666) ) == -1 ) {//create msgqueue failed printf("呼叫失敗,錯誤號碼 %d\n", errno ); exit(0); } } if( msgsnd(msgid, msgp, sizeof(sndbuf)-sizeof(long), IPC_NOWAIT) != -1 ) printf("Send success\n"); else printf("send failed, errno:%d\n", errno); return 0; } -------------------------- /*msgrcv.c *euphonium *2008/12/05 */ #include #include #include #include struct msgbuf { long type; int var; char text[20]; }rcvbuf, *msgp; int main() { int msgid; key_t KEY = 0x200; int msgtyp = 1000; int i; int rtrn; msgp = &rcvbuf; if( ( msgid = msgget(KEY, 0) ) < 0 ) {//msgqueue not exist if( ( msgid = msgget(KEY, IPC_CREAT|0666) ) == -1 ) {//create msgqueue failed printf("呼叫失敗,錯誤號碼 %d\n", errno ); exit(0); } } msgp->type = msgtyp; rtrn = msgrcv(msgid, msgp, sizeof(struct msgbuf) - sizeof(long), msgtyp, IPC_NOWAIT | MSG_NOERROR); if( rtrn != -1 ) { printf("Receive success %d\n", rtrn); printf("%d, %s\n", rcvbuf.var, rcvbuf.text ); } else printf("send failed, errno:%d\n", errno ); return 0; }