Linux消息隊列實踐(2)
來源:程序員人生 發布時間:2014-12-15 09:27:17 閱讀次數:4489次
消息隊列函數
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgget(key_t key, int msgflg);
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
msgctl函數
功能:獲得/設置消息隊列的信息
原型:
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
參數:
msqid: 由msgget函數返回的消息隊列標識碼
cmd:是將要采取的動作(見下)
返回值:
成功返回0,失敗返回⑴
cmd:將要采取的動作(有3個可取值),分別以下:

消息隊列數據結構
struct msqid_ds
{
struct ipc_perm msg_perm; /* Ownership and permissions */
time_t msg_stime; /* Time of last msgsnd(2) */
time_t msg_rtime; /* Time of last msgrcv(2) */
time_t msg_ctime; /* Time of last change */
unsigned long __msg_cbytes; /* Current number of bytes in
queue (nonstandard) */
msgqnum_t msg_qnum; /* Current number of messages
in queue */
msglen_t msg_qbytes; /* Maximum number of bytes
allowed in queue */
pid_t msg_lspid; /* PID of last msgsnd(2) */
pid_t msg_lrpid; /* PID of last msgrcv(2) */
};
Ipc_perm數據結構
struct ipc_perm
{
key_t __key; /* Key supplied to msgget(2) */
uid_t uid; /* Effective UID of owner */
gid_t gid; /* Effective GID of owner */
uid_t cuid; /* Effective UID of creator */
gid_t cgid; /* Effective GID of creator */
unsigned short mode; /* Permissions */
unsigned short __seq; /* Sequence number */
};
//實踐:IPC_STAT
int main()
{
int msgid = msgget(0x1234, 0666);
if (msgid == ⑴)
{
err_exit("msgget error");
}
struct msqid_ds buf;
if (msgctl(msgid,IPC_STAT,&buf) == ⑴)
{
err_exit("msgctl error");
}
printf("buf.msg_perm.mode = %o
",buf.msg_perm.mode); //%o以8進制打印
cout << "buf.__msg_cbytes = " << buf.__msg_cbytes << endl;
cout << "buf.msg_qbytes = " << buf.msg_qbytes << endl;
cout << "buf.msg_lspid = " << buf.msg_lspid << endl;
}
//實踐:IPC_SET,1般需要先獲得,然后再設置
int main()
{
int msgid = msgget(0x1234, 0666);
if (msgid == ⑴)
{
err_exit("msgget error");
}
//獲得消息隊列的屬性
struct msqid_ds buf;
if (msgctl(msgid,IPC_STAT,&buf) == ⑴)
{
err_exit("msgctl get error");
}
//設置消息隊列的屬性
buf.msg_perm.mode = 0644;
if (msgctl(msgid,IPC_SET,&buf) == ⑴)
{
err_exit("msgctl set error");
}
//獲得并打印
if (msgctl(msgid,IPC_STAT,&buf) == ⑴)
{
err_exit("msgctl get error");
}
printf("buf.msg_perm.mode = %o
",buf.msg_perm.mode); //%o以8進制打印
}
//實踐:IPC_RMID,刪除消息隊列
/**說明:可以通過在多個窗口上運行幾個該程序,測試出:
消息隊列并沒有應用”援用計數”的功能!
*/
int main()
{
int msgid = msgget(0x1234, 0666);
if (msgid == ⑴)
{
err_exit("msgget error");
}
int choice = 0;
cout << "Please input Your choice: 0-delete, other-continue: ";
cin >> choice;
if (!choice)
{
//delete msg
if (msgctl(msgid,IPC_RMID,NULL) == ⑴)
{
err_exit("msgctl IPC_RMID error");
}
else
{
cout << "msgid = " << msgid << ", IPC_RMID OK!" << endl;
}
}
}
消息的發送和接收
msgsnd函數
功能:把1條消息添加到消息隊列中
原型
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
參數
msgid: 由msgget函數返回的消息隊列標識碼
msgp:是1個指針,指針指向準備發送的消息,
msgsz:是msgp指向的消息長度,這個長度不含保存消息類型的那個long int長整型
msgflg:控制著當前消息隊列滿或到達系統上限時將要產生的事情
返回值:
成功返回0;失敗返回⑴
msgflg=IPC_NOWAIT表示隊列滿不等待,返回EAGAIN毛病。
消息結構在兩方面遭到制約。首先,它必須小于系統規定的上限值;其次,它必須以1個long int長整數開始,接收者函數將利用這個長整數肯定消息的類型
消息結構參考情勢以下:
struct msgbuf
{
long mtype; /* message type, must be > 0 */
char mtext[1]; /* message data */
};
//實踐
/**發送結構*/
struct msgBuf
{
long mtype; /* message type, must be > 0 */
char mtext[1024]; /* message data */
};
int main()
{
int msgid = msgget(0x1234,0666|IPC_CREAT);
if (msgid == ⑴)
{
err_exit("msgget error");
}
//初始化消息結構
struct msgBuf myBuffer;
myBuffer.mtype = 1;
strcpy(myBuffer.mtext,"Hello XiaoFang!");
//向消息隊列發送消息
if (msgsnd(msgid,&myBuffer,strlen(myBuffer.mtext),IPC_NOWAIT) == ⑴)
{
err_exit("msgsnd error");
}
return 0;
}
msgrcv函數
功能:是從1個消息隊列接收消息
原型
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
參數
msgid: 由msgget函數返回的消息隊列標識碼
msgp:是1個指針,指針指向準備接收的消息,
msgsz:是msgp指向的消息長度,這個長度不含保存消息類型的那個long int長整型
msgtype:它可以實現接收優先級的簡單情勢
msgflg:控制著隊列中沒有相應類型的消息可供接收時將要產生的事
返回值:
成功->返回實際放到接收緩沖區里去的字節數;失敗->返回⑴
msgtyp |
msgtyp=0 | 返回隊列第1條信息 |
msgtyp>0 | 返回隊列第1條類型等于msgtype的消息 |
msgtyp<0 | 返回隊列第1條類型小于等于msgtype絕對值的消息,并且是滿足條件的消息類型最小的消息 |
msgflg |
msgflg=IPC_NOWAIT | 隊列沒有可讀消息不等待,返回ENOMSG毛病。 |
msgflg=MSG_NOERROR | 消息大小超過msgsz時被截斷 |
msgtyp>0且msgflg=MSG_EXCEPT | 接收類型不等于msgtype的第1條消息 |
//實踐:消息發送
int main()
{
int msgid = msgget(0x1234,0666|IPC_CREAT);
if (msgid == ⑴)
{
err_exit("msgget error");
}
struct msgBuf myBuffer;
for (int i = 0; i < 128; ++i)
{
myBuffer.mtype = i+1;
sprintf(myBuffer.mtext,"Hello, My number is %d",i+1);
if (msgsnd(msgid,&myBuffer,strlen(myBuffer.mtext),IPC_NOWAIT) == ⑴)
{
err_exit("msgsnd error");
}
}
return 0;
}
//實踐:消息接收:從隊首不斷的取數據
int main()
{
int msgid = msgget(0x1234,0666);
if (msgid == ⑴)
{
err_exit("msgget error");
}
//從隊首不斷的取數據,連續取10個
struct msgBuf myBuffer;
for (int i = 0; i < 10; ++i)
{
int recvBytes = 0;
if ((recvBytes = msgrcv(msgid,&myBuffer,sizeof(myBuffer.mtext),0,IPC_NOWAIT)) == ⑴)
{
err_exit("msgrcv error");
}
else
{
cout << "receive recvBytes = " << recvBytes << endl;
cout << "myBuffer.mtype = " << myBuffer.mtype << endl;
cout << " " << myBuffer.mtext << endl;
}
}
cout << "strlen(myBuffer.mtext) = " << strlen(myBuffer.mtext) << endl;
return 0;
}
生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈