Linux system programming 64 processes, inter-thread communication 2-message queue

XSI -> SysV

IPC -> Inter process communication 进程间通信的三种机制
主动端:先发包的一方
被动端:先收包的一方 ,一定是被动端先运行 等着收包

mhr@ubuntu:~/Desktop/xitongbiancheng/communication$ ipcs
Message Queues 消息队列 ,双工
key        msqid      owner      perms      used-bytes   messages 
msgget();
msgop();
msgctl();

Shared Memory Segments 信号量数组
key        shmid      owner      perms      bytes      nattch     status 
 
Semaphore Arrays  共享内存
key        semid      owner      perms      nsems  

About key value:

Insert picture description here

key: ftok(), generate IPC Key value, convert path name and project identifier to System V IPC key

NAME
       ftok - convert a pathname and a project identifier to a System V IPC key

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

       key_t ftok(const char *pathname, int proj_id);

The parameter fname is the specified file name. This file must exist and be accessible. id is the sub-sequence number, which is an 8-bit integer. That is, the range is 0~255. When the function is executed successfully, it will return the key_t value, otherwise it will return -1. In general UNIX, the index node of the file is usually taken out, and then the sub-sequence number is added to the front to get the value of key_t.

msgget(): used to create a new message queue or get an existing message queue

NAME
       msgget - get a System V message queue identifier 获取一个消息队列的ID

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

/*
key: The key value of the message queue. The function compares it with the key of the existing message queue object to determine whether the message queue object has been created
.

IPC_CREAT:如果消息队列对象不存在,则创建之,否则则进行打开操作;
IPC_EXCL:和IPC_CREAT 一起使用(用”|”连接),如果消息对象不存在则创建,否则产生一个错误并返回。

*/

 int msgget(key_t key, int msgflg);

RETURN VALUE
       If successful, the return value will be the message queue identifier (a nonnegative integer), otherwise -1 with errno indicating the error.

If the IPC_CREAT flag is used alone, the msgget() function will either return the identifier of an existing message queue object or the identifier of a newly created message queue object. If the IPC_CREAT and IPC_EXCL flags are used together, msgget() will return the identifier of a newly created message object, or -1 if the message queue object already exists. The IPC_EXCL flag itself does not have much meaning, but it can be used together with the IPC_CREAT flag to ensure that the resulting message queue object is a newly created object instead of an existing object that is opened

msgsnd(),msgrcv(): send and receive message queue

NAME
       msgrcv, msgsnd - System V message queue operations

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

//发送
/*
msqid:消息队列ID
msgp :待发送数据位置
msgsz :待发送数据大小
msgflg :特殊要求
*/
       int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);


//接收
/*
msqid:消息队列ID
msgp :收取消息存放位置,注意空间格式
msgsz :真正收取有效数据信息的大小,而不是全部的数据信息大小:sizeof(rbuf)-sizeof(long)
msgtyp:是否挑选消息来接收,比如接收第几个包,所以msg消息队列本质上已经不算是队列了,因为队列一定是先进先出。
msgflg:特殊指定操作
*/
       ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,
                      int msgflg);

注意:
       The msgp argument is a pointer to a caller-defined structure of the following general form:

           struct msgbuf {
               long mtype;       /* message type, must be > 0 */
               char mtext[1];    /* message data */
           };

RETURN VALUE
       On failure both functions return -1 with errno indicating the error, otherwise msgsnd() returns 0 and msgrcv() returns the number of bytes actually copied into the mtext array.

msgctl(): Control a message queue, such as destruction, setting, etc.

NAME
       msgctl - System V message control operations

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

/* 对消息队列msqid 执行 cmd命令,buf表示是否需要传参
cmd:
IPC_STAT
IPC_SET
IPC_RMID  删除当前消息队列
IPC_INFO (Linux-specific)
MSG_INFO (Linux-specific)
MSG_STAT (Linux-specific)
*/
       int msgctl(int msqid, int cmd, struct msqid_ds *buf);

Experiment: Inter-process communication-message queue, here is the unrelated inter-process communication. Of course, related processes can also communicate using message queues.

proto.h

#ifndef PROTP_H_
#define PROTO_H_


#define KEYPATH "/etc/services"
#define KEYPROJ 'g'

#define NAMESIZE 32

struct msg_st
{
 long mtype;// 仿照   struct msgbuf 
	char name[NAMESIZE];
	int math;
	int chinese;
};

#endif

rcver.c receiver process

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

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

#include "proto.h"

int main(void)
{
	key_t key;
	int msgid;
	struct msg_st rbuf;

	key = ftok(KEYPATH,KEYPROJ);//获取IPC 键值
	if(key < 0)
	{
		perror("ftok");
		exit(1);
	}

	msgid = msgget(key,IPC_CREAT|0600); //创建 消息队列 返回IP
	if(msgid < 0)
	{
		perror("msgget");
		exit(1);
	}

	while(1)
	{
 //从目标消息队列 接受数据,注意接收数据的大小是有效数据的大小
		if(msgrcv(msgid,&rbuf,sizeof(rbuf)-sizeof(long),0,0) < 0)
		{
			perror("msgrcv");
			exit(1);
		}
		printf("NAME = %s\n",rbuf.name);
		printf("MATH = %d\n",rbuf.math);
		printf("CHINESE = %s\n",rbuf.chinese);

	}

	msgctl(msgid,IPC_RMID,NULL);//销毁消息队列

	
	exit(0);
}

snder.c sender process

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <sys/msg.h>
#include <string.h>
#include "proto.h"

int main()
{
	key_t key;
	int msgid;
	struct msg_st sbuf;

	key = ftok(KEYPATH,KEYPROJ);//获取消息队列 IPC 键值
	if(key < 0)
	{
		perror("ftok");
		exit(1);
	}


	msgid = msgget(key,0);//获得已创建好的目标消息队列 的 ID
	if(msgid < 0)
	{
		perror("msgget");
		exit(1);
	}

//初始化数据
	sbuf.mtype = 1;
	strcpy(sbuf.name,"MHR");
	sbuf.math = rand()%100;
	sbuf.chinese = rand()%100;

// 发送数据
	if(msgsnd(msgid,&sbuf,sizeof(sbuf)-sizeof(sbuf),0) < 0)
	{
		perror("msgsnd");
		exit(1);
	}

	puts("OK");
	
	exit(0);
	

}

It should be noted that if the sender process is executed 10 times first, and then the receiver process is executed again, the receiver will accept the data sent by the sender 10 times before. This is because the
message queue has the ability to cache messages, how much data can be cached, you can check ulimit -a

mhr@ubuntu:~/Desktop/xitongbiancheng/communication/msg/basic$ ulimit -a
...
POSIX message queues     (bytes, -q) 819200
...
mhr@ubuntu:~/Desktop/xitongbiancheng/communication/msg/basic$ 

ipcs view current IPC

ipcrm: ipcrm-remove certain IPC resources delete the specified IPC parameters into the next

Such as deleting the specified message queue:

First check the target message queue id
mhr@ubuntu:~/Desktop/xitongbiancheng/communication/msg/basic$ ipcs
------ Message Queues --------
key msqid owner perms used-bytes messages
0x670100d2 0 mhr 600 0 0

Delete:
mhr@ubuntu:~/Desktop/xitongbiancheng/communication/msg/basic$ ipcrm -q 0

OPTIONS

   -M, --shmem-key shmkey
          Remove the shared memory segment created with shmkey after the last detach is performed.

   -m, --shmem-id shmid
          Remove the shared memory segment identified by shmid after the last detach is performed.

   -Q, --queue-key msgkey
          Remove the message queue created with msgkey.

   -q, --queue-id msgid
          Remove the message queue identified by msgid.

   -S, --semaphore-key semkey
          Remove the semaphore created with semkey.

   -s, --semaphore-id semid
          Remove the semaphore identified by semid.

   -V, --version
          Display version information and exit.

   -h, --help
          Display help text and exit.

Guess you like

Origin blog.csdn.net/LinuxArmbiggod/article/details/114849370