Chapter 11 Inter-Process Communication (2) _ message queue

3.  Message Queuing

3.1 System V IPC

(1) System V IPC Overview

  The basic inter-process communication device presence signal mechanism, and named pipes, etc. ①Unix pipe system.

  ②System V introduces a communication mechanism between three high-level processes : the message queue and share the shared semaphore .

  ③IPC object (message queues, semaphores, and shared memory) is present in the kernel rather than the file system , the controlled release by the user (the user lifecycle management object ipc), unlike the release conduit controlled by the kernel.

  ④IPC object referenced by identifying and accessing all IPC objects in kernel space has a unique identification ID , in the user space of the unique identification of the called Key .

  ⑤Linux IPC inherited from System V IPC

Access (2) System V IPC objects

  ①IPC object is a global object: Available ipcs, picrm commands to view or delete .

  ② Each IPC objects created by the get function: msgget, shmget, semget. Keyword key must be specified when invoking the get function.

Permissions and owner of the structure (3) IPC objects

3.2  Message Queuing

(1) Introduction message queue

  ① message queue is a linked list of kernel ;

  ② The user process will transfer data to the kernel, the kernel to add back in as a user ID, group ID, the ID read process and priority related information and encapsulated into a data message packet called.

  ③ allows one or more processes to write messages in the message queue and read the message, but the message can only be a process of reading, reading is automatically deleted after completion.

  ④ message queue has a FIFO certain characteristics , the order may be sent to the message queue, several different ways can be read from the queue. Each IPC message queue a unique identification ID expressed by the kernel .

  ⑤ implement the message queue comprises a queue creation and opening, send a message, read a message and a control message queue four operations.

(2) the structure of the message queue (the msqid_ds)

(3) open and create a message queue

head File

#include <sys/msg.h>

function

int msgget(key_t key, int flag);

parameter

key:  the message queue specified user key

Flag : IPC_CREAT, and other combinations of privileges IPC_EXCL

Features

Open or create a message queue

return value

Successful return kernel message queue identifier ID, Error -1

Remark

① To create a message queue, key can specify the key, it can also be set to IPC_PRIVATE.

② If you open a query, the key can not be zero, must be a non-zero value, otherwise it can not find.

(4) a control message queue

head File

#include <sys/msg.h>

function

int msgctl(int msgqid, int cmd, struct msqid_ds* buf);

parameter

msgqid : Message Queue ID

buf : a pointer message queue attributes

cmd

(1) IPC_STAT: Get message queue attributes, taking msqid_ds structure this queue, and store it in buf specified structure.

(2) IPC_SET: set properties, according to the value of buf pointed structure, provided the queue associated with this field structure.

(3) IPC_RMID: delete a queue, the message queue and delete all the data is still in the queue from the system.

Features

A control message queue

return value

0 returns successfully, an error -1

(5) sends a message

head File

#include <sys/msg.h>

function

int msgsnd(int msgqid, const void* ptr, size_t nbytes, int flag);

parameter

the msqid : Message Queue ID

ptr : user-defined structure, but the first members must be mtype.

struct mymesg{

  long mtype; // positive message type, message type, and can only be an integer greater than 0.

  char mtext [512]; // message data, of length nbytes, message data itself

}

nbytes : Specifies the size of the message does not include the size of mtype.

flag

(1) 0, blocked. (2) IPC_NOWAIT: similar to a file I / O non-blocking I / O flag.

(3) If the message queue has full (or the total number of bytes equal to the total number of system message queue limit, or queue limit is equal to the system), using the specified IPC_NOWAIT msgsnd immediately return an error EAGAIN. If 0 is specified, then the process:. A block until space can accommodate a message to be sent. B. queue or delete from the system;. C or capture a signal and returns the signal handler.

Features

send messages

return value

0 returns successfully, an error -1

Remark

In linux, the maximum message length is 4056 bytes, including MTYPE, which occupies 4 bytes.

(6) receiving a message

head File

#include <sys/msg.h>

function

int msgrcv(int msgqid, void* ptr, size_t nbytes, int flag);

parameter

the msqid : Message Queue ID

ptr : points to the buffer to store messages

nbytes : message buffer size, the size does not include the mtype. Calculation:

nbytes = sizeof(struct mymesg) – sizeof(long);

type:消息类型

(1)type == 0:获取消息队列中的第一个消息

(2)type > 0: 获取消息队列中类型为type的第一个消息

(3)type < 0: 获取消息队列中小于或等于type绝对值的消息(类型最小的)

flag:0或IPC_NOWAIT

功能

接收消息

返回值

成功返回消息的数据部分长度,出错返回-1

【编程实验】消息队列

//msq_snd.c //发送进程(要单独编译成一个可执行文件)

复制代码

#include <stdio.h>
#include <stdlib.h>
#include <sys/msg.h>

//消息结构体
typedef struct{
    long type;  //消息类型
    int  start; //消息数据本身(包括start和end)
    int  end;
}MSG;

/*往消息队列中发送消息*/

int main(int argc, char* argv[])
{
    //从命令行中转入消息的key
    if(argc < 2){
        printf("usage: %s key\n", argv[0]);
        exit(1);
    }

    key_t key = atoi(argv[1]);//key由用户指定,如10
    //key_t key = IPC_PRIVATE;  //key由系统指定
    //key_t key = ftok(argv[0], 0);//要据文件名和第2个参数生成key
    printf("key: %d\n", key);

    //创建或获取消息队列
    int msq_id;
    //IPC_CREAT | IPC_EXCL:不存在则创建,存在时返回错误!(保证对象总是新的)
    //而不是打开己有的对象
    if((msq_id = msgget(key, IPC_CREAT | IPC_EXCL | 0777)) < 0){
        perror("msgget error");
    }

    printf("msq id: %d\n", msq_id);
    
    //定义要发送的消息
    MSG mArr[5] ={
                  {4, 4, 100},
                  {2, 2, 200},
                  {1, 1, 100},
                  {6, 6, 600},//注意两条type都等于6的消息。
                  {6, 60, 6000} 
                 };

    //发送消息到消息队列
    int i = 0;
    for(; i<5; i++){
        if(msgsnd(msq_id, &mArr[i], sizeof(MSG)-sizeof(long), IPC_NOWAIT) < 0){
            perror("msgsnd error");
        }
    }
    
    //发送后获得消息队列中消息的总数
    struct msqid_ds ds={0};
    if(msgctl(msq_id, IPC_STAT, &ds) < 0){
        perror("msgctl error");
    }

    printf("msg total: %d\n", ds.msg_qnum);
    
    return 0;
}
/*输出结果:
 [root@localhost 11.IPC]# bin/msq_snd 10  //其中的key(10)由用户指定
 key: 10
 msq id: 65536
 msg total: 5
 [root@localhost 11.IPC]# ipcs -q       //查看消息队列
 ------ Message Queues --------         //可以看出有5种消息
 key        msqid      owner      perms      used-bytes   messages    
 0x0000000a 65536      root       777        40           5           
 [root@localhost 11.IPC]# ipcrm -q 65536  //删除指定的消息队列
 [root@localhost 11.IPC]# ipcs -q       
 ------ Message Queues --------
 key        msqid      owner      perms      used-bytes   messages 
 */

复制代码

//msg_rcv.c //接收进程(要单独编译成一个可执行文件)

复制代码

#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>

typedef struct{
    long type;
    int start;
    int end;
}MSG;

int main(int argc, char* argv[])
{
    if(argc < 3){
        printf("usage: %s key type\n", argv[0]);
        exit(1);
    }

    key_t key = atoi(argv[1]);
    long type = atoi(argv[2]);

    //获得指定的消息队列
    int msq_id;
    if((msq_id = msgget(key, 0777)) < 0){
        perror("msgget error");
    }
    printf("msg id: %d\n", msq_id);
    
    MSG m;
    if(msgrcv(msq_id, &m, sizeof(MSG)-sizeof(long), type, IPC_NOWAIT) < 0){
        perror("msgrcv error");
    }else{
        printf("type: %d start: %d end: %d\n", m.type, m.start, m.end);
    }

    return 0;
}
/*输出结果:
 [root@localhost 11.IPC]# bin/msq_snd 10   //send进程,先创建消息队列
 key: 10
 msq id: 262144
 msg total: 5
 [root@localhost 11.IPC]# bin/msq_rcv 10 1 //receive进程,从key队列中获得type为1的消息
 msg id: 262144
 type: 1 start: 1 end: 100
 [root@localhost 11.IPC]# bin/msq_rcv 10 2 //获取type为2的消息
 msg id: 262144
 type: 2 start: 2 end: 200
 [root@localhost 11.IPC]# bin/msq_rcv 10 3 //获取type为3的消息(不存在的消息)
 msg id: 262144
 msgrcv error: No message of desired type  //获取type为4的消息
 [root@localhost 11.IPC]# bin/msq_rcv 10 4
 msg id: 262144
 type: 4 start: 4 end: 100
 [root@localhost 11.IPC]# bin/msq_rcv 10 6 //获取类型为6的第1条消息(先进先出)
 msg id: 262144
 type: 6 start: 6 end: 600
 [root@localhost 11.IPC]# bin/msq_rcv 10 6 //获取类型为6的第2条消息
 msg id: 262144
 type: 6 start: 60 end: 6000
 [root@localhost 11.IPC]# ipcs -q

 ------ Message Queues --------
 key        msqid      owner      perms      used-bytes   messages    
 0x0000000a 262144     root       777        0            0           

 [root@localhost 11.IPC]# ipcrm -q 262144 
 [root@localhost 11.IPC]# ipcs -q

 ------ Message Queues --------
 key        msqid      owner      perms      used-bytes   messages  
 */

复制代码

发布了25 篇原创文章 · 获赞 4 · 访问量 2万+

Guess you like

Origin blog.csdn.net/zhou8400/article/details/97392295