標籤:linux ipc 訊息佇列 建立 控制
訊息佇列基本概念
訊息佇列提供了一個從一個進程向另外一個進程發送一塊資料的方法(僅局限與本機)
每個資料區塊都被認為是有一個類型,接收者進程接收的資料區塊可以有不同的類型值
訊息佇列也有管道一樣的不足,就是每個訊息的最大長度是有上限的(MSGMAX),每個訊息佇列的總的位元組數是有上限的(MSGMNB),系統上訊息佇列的總數也有一個上限(MSGMNI)
管道 vs. 訊息佇列:
管道:流管道 訊息:有邊界
先進先出 可以後進入、先出來
訊息佇列大小三大限制
cat /proc/sys/kernel/msgmax #最大訊息長度限制
cat /proc/sys/kernel/msgmnb #訊息佇列總的位元組數
cat /proc/sys/kernel/msgmni #訊息條目數
IPC對象資料結構
核心為每個IPC對象維護一個資料結構
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 */};
訊息佇列特有的結構
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) */};
訊息佇列在核心中的表示
訊息佇列函數樣本
msgget函數
功能:用來建立和訪問一個訊息佇列
原型:
int msgget(key_t key, int msgflg);
參數:
key: 某個訊息佇列的名字
msgflg:由九個許可權標誌構成,如0644,它們的用法和建立檔案時使用的mode模式標誌是一樣的(但是訊息佇列沒有x(執行)許可權)
傳回值:
成功返回訊息佇列編號,即該訊息佇列的標識碼;失敗返回-1
編程實踐
//實踐1:IPC_PRIVATE:宏,值為0int main(){ //IPC_PRIVATE每次建立的訊息佇列的描述符都是不同的! //因此,計時MessageID(key)傳送給其他進程(除非有關聯的進程), //其他進程也無法使用該訊息佇列(血緣fork除外) int msgid = msgget(IPC_PRIVATE,0666); if (msgid < 0) { //如果訊息佇列不存在,則開啟錯誤,errno=ENOENT if (errno == ENOENT) { cout << "ENOENT" << endl; } err_exit("mesget error"); } else { cout << "msgid = " << msgid << endl; } return 0;}/** IPC_PRIVATE建立的訊息佇列,只能用在與當前進程有關係的進程中使用!*/
//實踐2:IPC_CREATint main(){ //指定IPC_CREAT,則一定會建立訊息佇列 int msgid = msgget(0x1235,0666|IPC_CREAT); if (msgid < 0) { //如果訊息佇列不存在,則開啟錯誤,errno=ENOENT if (errno == ENOENT) { cout << "ENOENT" << endl; } err_exit("mesget error"); } else { cout << "msgid = " << msgid << endl; } return 0;}
//實踐3:IPC_CREAT|IPC_EXCLint main(){ //指定IPC_EXCL, 如果已經存在,則報告檔案已經存在(錯誤) int msgid = msgget(0x1235,0666|IPC_CREAT|IPC_EXCL); if (msgid < 0) { err_exit("mesget error"); } else { cout << "msgid = " << msgid << endl; } return 0;}
//實踐4:低許可權建立,高許可權開啟int main(){ //低許可權建立 int msgid = msgget(0x255,0444 | IPC_CREAT); if (msgid < 0) { err_exit("mesget error"); } else { cout << "Create Mes OK, msgid = " << msgid << endl; } //高許可權開啟 msgid = msgget(0x255,0644 | IPC_CREAT); if (msgid < 0) { err_exit("mesget error"); } else { cout << "Create Mes OK, msgid = " << msgid << endl; } return 0;}
msgget函數參數關係圖
msgctl函數
功能:對訊息佇列進行控制
原型:
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
參數:
msqid: 由msgget函數返回的訊息佇列標識碼
cmd:是將要採取的動作(見下)
傳回值:
成功返回0,失敗返回-1
cmd:將要採取的動作(有三個可取值),分別如下:
Linux訊息佇列基礎