SystemV message queue to simulate multiple "client" and a "server" multi-process communication

Linux message queue is among Linux system processes for implementing communication mechanism, POSIX and System V provides corresponding message queue API implementation for Linux, the following is an application of System V message queue (Message Queue is not in fact SystemV very common, and usually with POSIX message queues to communicate between processes! but still feel the need to learn to summarize.).

Message queue memory in the form of

Message queue in the form of the kernel is a linked list, each process to store a message sent by the information as shown in (picture from the network, established infringement deleted!):
Here Insert Picture Description

Message queue kernel data structures

struct msqid_ds {
	struct ipc_perm msg_perm;     //IPC对象数据结构
	time_t	msg_stime;    //最后一次往消息队列中发送数据的时间
	time_t	msg_rtime;    //最后一次从消息队列中接收数据的时间
	time_t	msg_ctime;    //最后一次改变的时间
	unsigned long    __msg_cbytes; //当前队列中消息的字节数
	msgqnum_t	msg_qnum;     //当前队列中消息的个数
	msglen_t	msg_qbytes;   //队列中允许存放的最大字节数
	pid_t       msg_lspid;      //最后一个往消息队列中发送数据的进程号
	pid_t       msg_lrpid;      //最后一个从消息队列中接收数据的进程号
};

Operation message queue

  • The above information can be obtained in the following ways:
struct msqid_ds  buf;
msgctl(msgid, IPC_STAT, &buf) ;
  • Other information about the system v Queue API provided
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

key_t ftok( const char * fname, int id )
int msgget(key_t key,int msgflg);
int msgsnd(int msqid,const void *msgp,size_t msgsz,int msgflg);
ssize_t msgrcv(int msqid,void *msgp,size_t msgsz,long msgtype,int msgflg);
int msgctl(int msqid,int cmd,struct msqid_ds *buf);

Description:

Must specify an ID value (1) ftok IPC system establishes communication (message queues, semaphores, and shared memory). Typically, the value obtained by ftok id function.
fname for the specified file name, id number is a child. Although it is an int, but only 8bits (1-255).
(2) msgget: used to create a new or open an existing message queue, the message queue corresponding to the key.
key: the name of a message queue.
msgflg: consists of nine permission flags, the same mode mode flag used when their usage and create files, such as file mode mode there is O_CREAT, the message queue has IPC_CREAT and so on.
(3) msgsnd: add messages to the message queue.
msgid: msgget returned by the function code in the message queue.
msgp: is a pointer to the message to be sent.
msgsz: msgp is directed message length that does not comprise save the message type long int that a long integer.
msgflg: controls things on the current message queue is full or reaches the limit of the system is going to happen.

msgflg = IPC_NOWAIT indicates that the queue is full not wait to return EAGAIN error.

(4) msgrcv: get messages from the message queue.

msgid: msgget returned by the function code in the message queue.
msgp: it is a pointer to a received message ready.
msgsz: msgp is directed message length that does not comprise save the message type long int that a long integer.
msgtype: receiving priority can be realized a simple form.

msgtype = 0 returns the first message queue
msgtype> 0 returned to the queue equal to the first type of message msgtype
msgtype <0 returned to the queue equal to the first type is less than the absolute value of the message msgtype

msgflg: controls the queue is no corresponding message type for things to happen when receiving.

msgflg = IPC_NOWAIT, no-readable message without waiting queue, returns an error ENOMSG
msgflg = MSS_NOERROR, truncated message size exceeds The msgsz
the msgflg> 0 and msgflg = MSC_EXCEPT, the type is not equal to the received first message msgtype

Return Value: returns the number of characters actually successfully into the receive buffer to the failure -1

(5) msgctl see this, understand that this is about a universal function, it can be removed through a message queue, you can obtain the number of messages in the message queue, and so on.

msqid: msgget returned by the function code in the message queue.
cmd: actions to be taken (there are three possible values).

IPC_STAT Get message information kernel message queues by this structure.
IPC_STAT
read msqid_ds message queue data structure and stores the address specified in buf.
IPC_SET
setting value msqid_ds ipc_perm element data structure in the message queue. This value is taken from the buf argument.
IPC_RMID
removed from the message queue system kernel.

buf: a message queue maintained by the kernel structure.

Message Queuing applications

客户端

#include <iostream>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<thread>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<unistd.h>
using namespace std ;

struct data {
    pid_t pid ;
    char info[1024] ;
} ;

typedef struct msg {
    long type ;
    struct data buf ;
} msg_t;

void sendmsg(int msgid) {
    
    msg_t msg ;
    bzero(&msg, sizeof(msg));
    msg.buf.pid = getpid();;
    cout << msgid << endl;
    while(1) {
        msg.type = 1 ;
        cout << "输入发送的内容:";
        cin >>msg.buf.info ;
        int ret = msgsnd(msgid, (void*)&msg, sizeof(msg_t)-sizeof(long), 0) ;
        if(ret < 0) {
                cout <<errno << endl;
                exit(1) ;
        }
    }
}

void recvmsg(int msgid) {
    
    msg_t msg ;
    msg.type = getpid();
    while(1) {
       while(1){
        int ret = msgrcv(msgid, (void*)&msg, sizeof(msg_t)-sizeof(long), msg.type, 0) ;
           if(ret > 0) {
                break ;
            }
        }
        cout << "\n接收到内容:"<< msg.buf.info << endl;
    }
}

int main()
{
    key_t key = ftok(".", 1) ;
    int msgid = msgget(key, 0) ;
    if(msgid < 0) {
        perror("msgget") ;
    }
    cout << msgid << endl;
    thread sendto(sendmsg, msgid) ;
    thread receive(recvmsg, msgid) ;
    sendto.join() ;
    receive.join() ;
    return 0;
}

服务器

#include <iostream>
#include<sys/msg.h>
#include<sys/msg.h>
#include<unistd.h>
#include<thread>
using namespace std ;

struct data {
    pid_t pid ;
    char info[1024] ;
} ;

typedef struct msg {

    long type ;
    struct data buf ;
} msg_t;

void hand(int msgid,int pid);
int main() {
    
    msg_t msg ;
    key_t key = ftok(".", 1) ;
    int msgid = msgget(key, IPC_CREAT|IPC_EXCL|0666) ;
    if(msgid < 0) {
        perror("msgget") ;
    }
    
    while(1) {
        msg.type = 1 ;
        int ret = 0 ;
        while(1){
        ret = msgrcv(msgid, (void*)&msg, sizeof(msg_t) - sizeof(long), msg.type, 0) ;    
            if(ret > 0) {
                break;
            }
        }
        cout << "接收到进程"<<msg.buf.pid <<"的连接:"<< msg.buf.info <<endl ;
        thread t(hand,msgid,msg.buf.pid);
        t.detach();

    }
}   

void hand(int msgid,int pid)
{
    msg_t msg;
    msg.type = pid;
    cout << "请输入发给"<<pid<<"进程"<<"的消息:" ;
    cin>> msg.buf.info ;
    int ret = msgsnd(msgid, (void*)&msg, sizeof(msg_t) - sizeof(long),  0) ;    
    if(ret < 0) {
        perror("msgsnd") ;
        exit(1) ;
    }
}

Program running, first running of "servers" to create a message queue, and then run multiple "clients"! Realization bug encountered in the process of a lot, too much food, and always write bug!

  • Run shot

Here Insert Picture Description

Guess you like

Origin blog.csdn.net/qq_41681241/article/details/90052212