Detailed explanation of linux inter-process communication - message queue

Preface: The inter-process communication methods of signals and pipes were discussed earlier, and message queues will be discussed next.

  1. System V IPC

  There are many similarities between the three System V IPCs : message queues, semaphores, and shared memory (shared memory).

  Each kernel IPC structure (message queue, semaphore, or shared memory segment) is referenced by a non-negative integer identifier
( identifier ) .

  Whenever you create an IPC structure (call msgget , semget or shmget ) , you should specify a key ( key ) , the data type of the key is specified by the system as key_t , usually in the header file <sys/types.h> is specified as a long integer. Keywords are transformed into identifiers by the kernel.


  The above briefly introduces IPC, which is helpful for understanding the message queue, semaphore and shared memory introduced next.

  Second, the message queue

  1 Introduction

  A message queue is a linked list of messages , stored in the kernel and identified by a message queue identifier. We will call the message queue
"queue" and its identifier is "queue ID ". msgget is used to create a new queue or open an existing queue. msgsnd
is used to add new messages to the end of the queue. Each message contains a positive long type field, a non-negative length, and the actual
data bytes (corresponding to the length), all of which are passed to msgsnd when the message is added to the queue . msgrcv is used
to fetch messages from the queue. We don't have to fetch messages in FIFO order, we can also fetch messages by their type field.

  2. Function introduction

  • ftok function

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

key_t ftok(const char *pathname, int proj_id);//"/home/linux", 'a'
function: generate a key (key value)

  • msgget function

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

int msgget(key_t key, int msgflg);

Function: Create or get a message queue object
Return: The id of the message queue object The same key gets the same object
Format: msgget(key,flag|mode);
flag: can be 0 or IPC_CREAT (create if it does not exist)
mode: same as file permissions

  • msgsnd function

int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
function: write msgp message to message queue
msgp identified as msgid:
struct msgbuf {
long mtype; /* message type, must be > 0 */ The type of the message must be >0
char mtext[1]; /* message data */length is optional
};

msgsz: The size of the message to be sent does not include the 4 bytes occupied by the type of the message
msgflg: If it is 0, it will block
when the message queue is full. If it is IPC_NOWAIT, it will not block and return immediately when the message queue is full.

Return value: success returns id, failure returns -1

  • msgrcv function

ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,
int msgflg);

Function: Receive a message of a specified type from the message queue with the identifier msgid and store it in msgp. After reading, delete the message from the message queue.
msgtyp: 0 means that no matter what type can receive
msgp: the structure that stores the message
msgsz: The size of the message to be received does not include the 4 bytes occupied by the message type
msgflg: If it is 0, it means that if there is no message of the specified type, it will wait all the time.
If it is IPC_NOWAIT, it means not waiting

  • msgctl function

int msgctl(int msqid, int cmd, struct msqid_ds *buf);
msgctl(msgid, IPC_RMID, NULL);//Delete message queue object

  Program 2-2 will simply demonstrate the message queue:

  ---  snd.c  ---

#include "my.h"

typedef struct{
    long type;
    char name[20];
    int age;
}Msg;

intmain ()
{
    key_t key = ftok("/home/liudw",'6');
    printf("key:%x\n",key);

    int msgid = msgget(key,IPC_CREAT|O_WRONLY|0777);
    if(msgid<0)
    {   
        perror("msgget error!");
        exit(-1);
    }   

    Msg m;
    puts("please input your type name age:");
    scanf("%ld%s%d",&m.type,m.name,&m.age);
    msgsnd(msgid,&m,sizeof(m)-sizeof(m.type),0);

    return 0;
}

  ---  rcv.c  ---

#include "my.h"
 
typedef struct{
    long type;
    char name[20];
    int age;
}Msg;

intmain ()
{
    key_t key = ftok("/home/liudw",'6');
    printf("key:%x\n",key);

    int msgid = msgget(key,O_RDONLY);
    if(msgid<0)
    {   
        perror("msgget error!");
        exit(-1);
    }   

    Msg rcv;
    long type;
    puts("please input type you want!");
    scanf("%ld",&type);

    msgrcv(msgid,&rcv,sizeof(rcv)-sizeof(type),type,0);
    printf("rcv--name:%s age:%d\n",rcv.name,rcv.age);

    msgctl(msgid,IPC_RMID,NULL);
    return 0;
}

  Run the demo:

  3. Explain the ftok function in detail 

  • ftok extracts the file information according to the path name, and then synthesizes the key according to the file information and project ID. The path can be set arbitrarily.
  • The path must exist, and ftok only takes a value based on the uniqueness of the file inode in the system, regardless of the file's permissions.
  • proj_id can be set at will according to your own convention. This number, some call it the project ID; on UNIX systems, its value is 1 to 255;

 

  In order to verify the above point of view, slightly modify the program 2-2, modify the path and proj_id:

  Procedure 3-1 is as follows:

  ---  snd.c  ---

#include "my.h"

typedef struct{
    long type;
    char name[20];
    int age;
}Msg;

intmain ()
{
    key_t key = ftok("/home",'a');
    printf("key:%x\n",key);

    int msgid = msgget(key,IPC_CREAT|O_WRONLY|0777);
    if(msgid<0)
    {   
        perror("msgget error!");
        exit(-1);
    }   

    Msg m;
    puts("please input your type name age:");
    scanf("%ld%s%d",&m.type,m.name,&m.age);
    msgsnd(msgid,&m,sizeof(m)-sizeof(m.type),0);

    return 0;
}

  ---  rcv.c  ---

#include "my.h"

typedef struct{
    long type;
    char name[20];
    int age;
}Msg;

intmain ()
{
    key_t key = ftok("/home",'a');
    printf("key:%x\n",key);

    int msgid = msgget(key,O_RDONLY);
    if(msgid<0)
    {   
        perror("msgget error!");
        exit(-1);
    }   

    Msg rcv;
    long type;
    puts("please input type you want!");
    scanf("%ld",&type);

    msgrcv(msgid,&rcv,sizeof(rcv)-sizeof(type),type,0);
    printf("rcv--name:%s age:%d\n",rcv.name,rcv.age);

    msgctl(msgid,IPC_RMID,NULL);
    return 0;
}

  Run the demo as shown below:

 

  Summary: It mainly introduces the message queue of inter-process communication. If you have any questions, you can leave a message and answer it immediately.

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325155472&siteId=291194637