Comunicación entre procesos de Linux | cola de mensajes

cola de mensajes

1. Descripción general de Message Queue Server

La cola de mensajes es una lista de algunos mensajes. Los usuarios pueden agregar mensajes y leerlos en la cola de mensajes. La cola de mensajes tiene ciertas características FIFO, pero puede realizar consultas aleatorias de mensajes, lo que tiene mayores ventajas que FIFO. Al mismo tiempo, estas ventajas de mensajes existen en el kernel y se identifican mediante el "ID de cola".

2. Programación de la cola de mensajes

2.1 Instrucciones de programación

La realización de la cola de mensajes incluye las siguientes 4 operaciones:

  • Para crear o abrir una cola de mensajes, use la función msgget ()
  • Para agregar un mensaje, use la función msgsnd ()
  • Para leer el mensaje, use la función msgrcv ()
  • Para controlar la cola de mensajes, use la función msgctl ()
2.2 Introducción a la función

función msgget ()

/*****msgget()函数*****/
函数原型:int msgget(key_t key, int msgflg)
传 入 值:key 消息队列的键值,多个进程可通过它访问同一个消息队列。IPC_PRIVATE用于创建私有消息队列
		 msgflg 权限标志位
返 回 值:成功:消息队列ID;
		 失败:返回-1

función msgsnd ()

/*****msgsnd()函数*****/
函数原型:int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg)
传 入 值:msqid 消息队列的队列ID
		 msgp 指向消息结构的指针
		 msgsz 消息正文的字节数
		 msgflg 若为0表示调用阻塞直到发送成功为止;IPC_NOWAIT表示若消息无法立即发送,函数会立即返回
返 回 值:成功:返回0;失败:返回-1

//消息结构msgbuf的定义
struct msgbuf{
    
    
	long mtype;		//消息类型,该结构必须从这个域开始
	char mtext[1];	//消息正文
}

función msgrcv ()

/*****msgrcv()函数*****/
函数原型:int msgrcv(int msgid, void *msgp, size_t msgsz, long int msgtyp, int msgflg)
传 入 值:msqid 消息队列的队列ID
		 msgp 指向消息结构的指针,msgsnd()函数的msgp
		 msgsz 消息正文的字节数
		 msgtyp -->0表示接收消息队列中第一消息;
		 		-->大于0表示接收消息队列中第一个类型为msgtyp的消息;
		 		-->小于0表示接收消息队列中第一个类型值不小于msgtyp绝对值且类型值最小的消息
		 msgflg -->MSG_NOERROR 若返回的消息比msgsz字节多,则消息就会截短到msgsz字节,且不通知消息发送进程;
		 		-->IPC_NOWAIT 若在消息队列中没有相应类型的消息可以接收,则函数立即返回;
		 		-->0 msgsnd()调用阻塞直到接收一条相应类型的消息位置;
返 回 值:成功:返回0
		 失败:返回-1

función msgctl ()

/*****msgctl()函数*****/
函数原型:int msgctl(int msgid, int cmd, struct msqid_ds *buf)
传 入 值:msqid 消息队列的队列ID
		 cmd -->IPC_STAT 读取消息队列的数据结构msqid_ds,并将其存储在buf指定的地址中;
		     -->IPC_SET 设置消息队列的数据结构msgid_ds中的ipc_perm域值,这个值取自buf参数;
		 	 -->IPC_RMID 从系统内核中删除消息队列;
		 buf 描述消息队列的msqid_ds结构类型变量
返 回 值:成功:返回0
		 失败:返回-1
2.3 Ejemplos de funciones

El siguiente ejemplo muestra cómo utilizar las colas de mensajes para la comunicación entre dos procesos (emisor y receptor). El proceso de finalización de envío de mensajes y el proceso de finalización de recepción de mensajes no necesitan sincronización adicional entre procesos.
El mensaje al código del remitente es el siguiente:

/*****msgsnd.c*****/
//省略头文件
#define BUFFER_SIZE 512

struct message{
    
    
	long msg_type;
	char msg_text[BUFFER_SIZE];
};

int main(){
    
    
	int qid;
	key_t key;
	strcut message msg;

	if((key = ftok(".",'a')) == -1){
    
    
		perror("ftok");
		exit(1);
	}
	
	if((qid = msgget(key, IPC_CREAT|0666)) == -1){
    
    
		perror("msgget");
		exit(1);
	}
	printf("Open queue %d\n",qid);
	while(1){
    
    
		printf("Enter some message to the queue:");
		if((fgets(msg.msg_text,BUFFER_SIZE,stdin)) == NULL){
    
    
			puts("no message");
			exit(1);
		}

		msg.msg_type = getpid();
		if((msgsnd(qid, &msg, strlen(msg.msg_text), 0)) < 0){
    
    
			perror("message posted");
			exit(1);
		}
		if((strncmp(msg.msg_text, "quit", 4)) == 0)
			break;
	}
	exit(0);
}

El código del extremo receptor de la cola de mensajes es el siguiente:

/*****msgrcv.c*****/
//省略头文件
#define BUFFER_SIZE 512

struct message{
    
    
	long msg_type;
	char msg_text[BUFFER_SIZE];
};

int main(){
    
    
	int qid;
	key_t key;
	strcut message msg;

	if((key = ftok(".",'a')) == -1){
    
    
		perror("ftok");
		exit(1);
	}
	
	if((qid = msgget(key, IPC_CREAT|0666)) == -1){
    
    
		perror("msgget");
		exit(1);
	}
	printf("Open queue %d\n",qid);
	do{
    
    
		memset(msg.msg_text, 0, BUFFER_SIZE);
		if((msgrcv(qid, (void *)&msg, BUFFER_SIZE, 0, 0)) < 0){
    
    
			perror("msgrcv");
			exit(1);
		}
		printf("The message from process %d : %s",msg.msg_type,msg_msg_text);		
	}while(strncmp(msg.msg_text, "quit", 4));
	
	if((msgctl(qid, IPC_RMID, NULL)) < 0){
    
    
		perror("msgctl");
		exit(1);
	}	
	exit(0);
}

Supongo que te gusta

Origin blog.csdn.net/Chuangke_Andy/article/details/108306421
Recomendado
Clasificación