linux網路編程之System V 訊息佇列(一):訊息佇列核心結構和msgget、msgctl 函數

來源:互聯網
上載者:User

一、訊息佇列

1、訊息佇列提供了一個從一個進程向另外一個進程發送一塊資料的方法
2、每個資料區塊都被認為是有一個類型,接收者進程接收的資料區塊可以有不同的類型值

3、訊息佇列與管道不同的是,訊息佇列是基於訊息的,而管道是基於位元組流的,且訊息佇列的讀取不一定是先入先出。
4、訊息佇列也有管道一樣的不足,就是每個訊息的最大長度是有上限的(MSGMAX),每個訊息佇列的總的位元組數是有上限的(MSGMNB),系統上訊息佇列的總數也有一個上限(MSGMNI),這三個參數都可以查看:

simba@ubuntu:~/Documents/code/linux_programming/UNP/system_v$ cat /proc/sys/kernel/msgmax
8192
simba@ubuntu:~/Documents/code/linux_programming/UNP/system_v$ cat /proc/sys/kernel/msgmnb
16384
simba@ubuntu:~/Documents/code/linux_programming/UNP/system_v$ cat /proc/sys/kernel/msgmni
1711


二、IPC對象資料結構

核心為每個IPC對象維護一個資料結構
struct ipc_perm {
key_t          __key;       /* Key supplied to xxxget(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) */
};

可以看到第一個條目就是IPC結構體,即是共有的,後面的都是訊息佇列所私人的成員。


四、訊息佇列在核心中的表示


訊息佇列是用鏈表實現的,這裡需要提出的是MSGMAX指的是一條訊息的純資料大小的上限,是一個訊息佇列,則其純資料總和不能超過MSGMNB,像這樣一條訊息佇列,系統含有的總數不能超過MSGMNI 個。


五、msgget 和 msgctl 函數

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

(1)int msgget(key_t key, int msgflg);

功能:用來建立和訪問一個訊息佇列
參數
key: 某個訊息佇列的名字
msgflg:由九個許可權標誌構成,它們的用法和建立檔案時使用的mode模式標誌是一樣的
傳回值:成功返回一個非負整數,即該訊息佇列的標識碼;失敗返回-1

建立流程如所示:

注意,IPC_PRIVATE 不是一個msgflg 而是一個key_t 類型,如果指定key = IPC_PRIVATE,則無論某個 key_value 這個訊息佇列是否存在,都會再建立一個key_value 訊息佇列,但他們的標識碼msqid是不一樣的,且指定IPC_PRIVATE 產生的是私人的訊息佇列。

寫個小程式測試一下這個函數:

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/*************************************************************************
    > File Name: basic.c
    > Author: Simba
    > Mail: dameng34@163.com
    > Created Time: Tue 12 Mar 2013 06:54:20 PM CST
 ************************************************************************/

#include<stdio.h>
#include<stdlib.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<sys/types.h>
#include<unistd.h>
#include<errno.h>

#define ERR_EXIT(m) \
    do { \
        perror(m); \
        exit(EXIT_FAILURE); \
    } while(0)

int main(void)
{
    int msgid;
    msgid = msgget(1234, 0666 | IPC_CREAT);
    if (msgid == -1)
        ERR_EXIT("msgget");
    printf("msgget success\n");
    msgid = msgget(1234, 0);
    printf("msgid=%d\n", msgid);

    return 0;
}

程式先建立一個訊息佇列,名字為1234,接著開啟這個訊息佇列,當flags = 0 表示按原來許可權開啟。

輸出如下:

simba@ubuntu:~/Documents/code/linux_programming/UNP/system_v$ ./msgget 
msgget success
msgid=0

我們可以使用命令ipcs  -q 查看:


simba@ubuntu:~/Documents/code/linux_programming/UNP/system_v$ ipcs -q

------ Message Queues --------
key         msqid     owner      perms      used-bytes   messages    
0x000004d2     0             simba       666                0                  0   


可以看到0x4d2 也就是1234,msqid 為0。

(2)int msgctl(int msqid, int cmd, struct msqid_ds *buf);

功能:訊息佇列的控制函數
參數
msqid: 由msgget函數返回的訊息佇列標識碼
cmd:是將要採取的動作,(有三個可取值)
傳回值:成功返回0,失敗返回-1

cmd 的取值如下:

我們可以通過ipsrm -q 刪除一條訊息佇列,也可以通過msgctl 函數刪除,此時設定cmd 為 IPC_RMID,如下:

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/*************************************************************************
    > File Name: basic.c
    > Author: Simba
    > Mail: dameng34@163.com
    > Created Time: Tue 12 Mar 2013 06:54:20 PM CST
 ************************************************************************/

#include<stdio.h>
#include<stdlib.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<sys/types.h>
#include<unistd.h>
#include<errno.h>

#define ERR_EXIT(m) \
    do { \
        perror(m); \
        exit(EXIT_FAILURE); \
    } while(0)

int main(void)
{
    int msgid;
    msgid = msgget(1234, 0);
    if (msgid == -1)
        ERR_EXIT("msgget");
    printf("msgget success\n");
    printf("msgid=%d\n", msgid);

    msgctl(msgid, IPC_RMID, NULL);

    return 0;
}

如果我們想更改訊息佇列的一些參數,如許可權等,可以通過msgctl 函數,cmd 取值為IPC_SET

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
/*************************************************************************
    > File Name: basic.c
    > Author: Simba
    > Mail: dameng34@163.com
    > Created Time: Tue 12 Mar 2013 06:54:20 PM CST
 ************************************************************************/

#include<stdio.h>
#include<stdlib.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<sys/types.h>
#include<unistd.h>
#include<errno.h>

#define ERR_EXIT(m) \
    do { \
        perror(m); \
        exit(EXIT_FAILURE); \
    } while(0)

int main(void)
{
    int msgid;
    msgid = msgget(1234, 0);
    if (msgid == -1)
        ERR_EXIT("msgget");
    printf("msgget success\n");
    printf("msgid=%d\n", msgid);

    struct msqid_ds buf;
    msgctl(msgid, IPC_STAT, &buf);
    printf("permission : %o\n", buf.msg_perm.mode);

    sscanf("600", "%o", (unsigned int *)&buf.msg_perm.mode);
    msgctl(msgid, IPC_SET, &buf);

    return 0;
}

程式先通過IPC_STAT 擷取許可權,再通過IPC_SET 重新設定,輸出如下:

simba@ubuntu:~/Documents/code/linux_programming/UNP/system_v$ ./msgset
msgget success
msgid=32768
permission : 666


simba@ubuntu:~/Documents/code/linux_programming/UNP/system_v$ ipcs -q

------ Message Queues --------
key                  msqid      owner      perms      used-bytes   messages    
0x000004d2  32768      simba      600                0                 0  

參考:

《TCP/IP詳解 卷一》

《UNP》

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.