Linux 프로세스 간 통신 | 메시지 대기열

메시지 대기열

1. 메시지 큐 개요

메시지 대기열은 일부 메시지의 목록으로, 사용자는 메시지를 추가하고 메시지 대기열에있는 메시지를 읽을 수 있습니다. 메시지 큐에는 특정 FIFO 특성이 있지만 메시지의 임의 쿼리를 실현할 수있어 FIFO보다 더 큰 장점이 있습니다. 동시에 이러한 메시지 이점은 커널에 존재하며 "대기열 ID"로 식별됩니다.

2. 메시지 큐 프로그래밍

2.1 프로그래밍 지침

메시지 큐의 실현에는 다음 4 가지 작업이 포함됩니다.

  • 메시지 대기열을 만들거나 열려면 msgget () 함수를 사용하십시오.
  • 메시지를 추가하려면 msgsnd () 함수를 사용하십시오.
  • 메시지를 읽으려면 msgrcv () 함수를 사용하십시오.
  • 메시지 큐를 제어하려면 msgctl () 함수를 사용하십시오.
2.2 기능 소개

msgget () 함수

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

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];	//消息正文
}

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

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 기능 예

다음 예제는 두 프로세스 (송신자와 수신자) 간의 통신을 위해 메시지 큐를 사용하는 방법을 보여줍니다. 메시지 전송 종료 프로세스와 메시지 수신 종료 프로세스는 프로세스 간의 추가 동기화가 필요하지 않습니다.
발신자 코드에 대한 메시지는 다음과 같습니다.

/*****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);
}

메시지 큐의 수신단 코드는 다음과 같습니다.

/*****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);
}

추천

출처blog.csdn.net/Chuangke_Andy/article/details/108306421