下面来说说如何用不用消息队列来进行进程间的通信,消息队列与命名管道有很多相似之处。有关命名管道的更多内容可以参阅我的另一篇文章:Linux进程间通信——使用命名管道
一、什么是消息队列
消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法。 每个数据块都被认为含有一个类型,接收进程可以独立地接收含有不同类型的数据结构。我们可以通过发送消息来避免命名管道的同步和阻塞问题。但是消息队列与命名管道一样,每个数据块都有一个最大长度的限制。
Linux用宏MSGMAX和MSGMNB来限制一条消息的最大长度和一个队列的最大长度。
二、在Linux中使用消息队列
Linux提供了一系列消息队列的函数接口来让我们方便地使用它来实现进程间的通信。它的用法与其他两个System V PIC机制,即信号量和共享内存相似。
1、msgget函数
该函数用来创建和访问一个消息队列。它的原型为:
int msgget(key_t, key, int msgflg);
与其他的IPC机制一样,程序必须提供一个键来命名某个特定的消息队列。msgflg是一个权限标志,表示消息队列的访问权限,它与文件的访问权限一样。msgflg可以与IPC_CREAT做或操作,表示当key所命名的消息队列不存在时创建一个消息队列,如果key所命名的消息队列存在时,IPC_CREAT标志会被忽略,而只返回一个标识符。
它返回一个以key命名的消息队列的标识符(非零整数),失败时返回-1.
2、msgsnd函数
该函数用来把消息添加到消息队列中。它的原型为:
int msgsend(int msgid, const void *msg_ptr, size_t msg_sz, int msgflg);
msgid是由msgget函数返回的消息队列标识符。
msg_ptr是一个指向准备发送消息的指针,但是消息的数据结构却有一定的要求,指针msg_ptr所指向的消息结构一定要是以一个长整型成员变量开始的结构体,接收函数将用这个成员来确定消息的类型。所以消息结构要定义成这样:
struct my_message{
long int message_type;
};
msg_sz是msg_ptr指向的消息的长度,注意是消息的长度,而不是整个结构体的长度,也就是说msg_sz是不包括长整型消息类型成员变量的长度。
msgflg用于控制当前消息队列满或队列消息到达系统范围的限制时将要发生的事情。
如果调用成功,消息数据的一分副本将被放到消息队列中,并返回0,失败时返回-1.
3、msgrcv函数
该函数用来从一个消息队列获取消息,它的原型为
int msgrcv(int msgid, void *msg_ptr, size_t msg_st, long int msgtype, int msgflg); msgid, msg_ptr, msg_st 함수는 msgsnd 함수와 동일합니다.
msgtype은 단순 수신 우선순위를 구현할 수 있습니다. msgtype이 0이면 대기열의 첫 번째 메시지를 가져옵니다. 해당 값이 0보다 크면 동일한 메시지 유형의 첫 번째 메시지가 획득됩니다. 0보다 작으면 유형이 msgtype의 절대값보다 작거나 같은 첫 번째 메시지를 가져옵니다.
msgflg는 수신할 대기열에 해당 유형의 메시지가 없을 때 발생하는 상황을 제어하는 데 사용됩니다.
이 함수가 성공적으로 호출되면 수신 버퍼에 있는 바이트 수를 반환하고, 메시지는 msg_ptr이 가리키는 사용자 할당 버퍼에 복사된 후 메시지 큐에서 해당 메시지가 삭제됩니다. 실패 시 -1을 반환합니다.
4. msgctl 함수
이 함수는 공유 메모리의 shmctl 함수와 유사합니다.
일반 사본 보기
인쇄?
int msgctl(
int msgid,
int command,
struct msgid_ds *buf);
명령은 수행할 작업입니다. 3가지 값을 사용할 수 있습니다.
- buf는 msgid_ds 구조에 대한 포인터입니다. 대기열 모드 및 액세스 권한의 메시지 구조를 나타냅니다. msgid_ds 구조에는 최소한 다음 멤버가 포함됩니다:
[cpp] view plain copy
print?
struct msgid_ds
{
uid_t shm_perm. uid;
uid_t shm_perm.gid;
};
-
- 3. 메시지를 사용하세요. 큐 프로세스 간 통신
- 논스톱 메시지 큐의 정의와 사용 가능한 인터페이스를 소개한 후 프로세스가 어떻게 통신할 수 있는지 살펴보겠습니다. 관련되지 않은 프로세스가 통신할 수 있으므로 여기서는 정보 수신 및 전송을 나타내기 위해 msgreceive 및 msgsned라는 두 개의 프로그램을 작성하겠습니다. 일반적인 상황에서는 두 프로그램 모두 메시지를 생성하도록 허용하지만 수신자만 마지막 메시지를 받은 후 삭제합니다.
- 정보 수신용 프로그램 소스 파일은 msgreceive.c이고 소스 코드는
- [cpp]
일반 사본 보기
인쇄?
#include
#include
#include
#include
#include
#include
struct msg_st
{
long int msg_type;
문자 텍스트[BUFSIZ];
};
int main()
{
int 실행 중 = 1;
int msgid = -1;
struct msg_st 데이터;
long int msgtype = 0;
msgid = msgget ((key_t)1234, 0666 | IPC_CREAT);
if(msgid == -1)
{
fprintf(stderr, "msgget이 실패하고 오류가 발생했습니다: %dn" , 오류);
exit(EXIT_FAILURE);
}
(실행 중)
{
if(msgrcv(msgid , (void*)&data, BUFSIZ, msgtype, 0) == -1)
{
fprintf(stderr, "msgrcv 실패 오류 번호: %dn", 오류 번호);
exit(EXIT_FAILURE);
}
printf("당신이 쓴 글: %sn",data.text);
if(strncmp(data.text, "end", 3) == 0)
실행 중 = 0;
}
if(msgctl(msgid, IPC_RMID, 0) == -1)
{
fprintf(stderr, "msgctl(IPC_RMID) 실패n");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
发送信息的程序的源文件msgsend.c的源代码为:
#include
#include
#include
#include
#include
#include
#define MAX_TEXT 512
struct msg_st
{
-
long int msg_type;
문자 텍스트[MAX_TEXT];
};
int main()
{
int 실행 중 = 1;
struct msg_st 데이터;
문자 버퍼[BUFSIZ];
int msgid = -1;
msgid = msgget((key_t)1234, 0666 | IPC_CR 먹다);
if(msgid == -1)
{
fprintf(stderr, "msgget이 실패하고 오류가 발생했습니다: %dn" , 오류);
exit(EXIT_FAILURE);
}
-
(실행 중)
{
printf("일부 텍스트를 입력하세요: ");
fgets(버퍼, BUFSIZ, stdin);
data.msg_type = 1;
strcpy(data.text, buffer);
if(msgsnd(msgid, (void*)&data, MAX_TEXT, 0) == - 1)
{
fprintf(stderr, "msgsnd 실패함");
exit(EXIT_FAILURE);
}
if(strncmp(버퍼, "종료", 3) == 0)
실행 중 = 0;
수면(1);
}
exit(EXIT_SUCCESS);
}
运行结果如下:
IV. 예제 분석 - 메시지 유형
여기서는 주로 msgreceive.c 파일의 주요 함수에 정의된 msgtype 변수에 대해 설명합니다. 참고 1)로 주석을 달았으며, msgrcv 함수의 수신 정보 유형 매개변수의 값으로 사용되며, 그 값은 0이며, 이는 큐에서 사용 가능한 첫 번째 메시지를 가져오는 것을 의미합니다. msgsend.c 파일의 while 루프에 있는 data.msg_type = 1 문을 살펴보겠습니다(참고 2). 보내는 정보의 정보 유형, 즉 보내는 정보의 유형을 1로 설정하는 데 사용됩니다. . 따라서 msgceive 프로그램은 msgsend 프로그램이 보낸 정보를 받을 수 있습니다.
참고 1, 즉 msgreceive.c 파일의 주요 함수에 있는 명령문이 long int msgtype = 0;에서 long int msgtype = 2;로 변경되면 msgreceive가 수신할 수 없게 됩니다. msgsend 프로그램이 보낸 정보입니다. 왜냐하면 msgrcv 함수를 호출할 때 msgtype(네 번째 매개변수)이 0보다 크면 동일한 메시지 유형을 가진 첫 번째 메시지만 가져오기 때문입니다. 수정 후 얻은 메시지 유형은 2이고 msgsend에서 보낸 메시지 유형은 다음과 같습니다. 1. 따라서 msgreceive 프로그램에서는 이를 수신할 수 없습니다. msgreceive.c 파일을 다시 컴파일하고 다시 실행해 보면 다음과 같습니다.
msgreceive가 정보와 출력을 받지 못하고, msgsend 입력 종료 시 msgreceive가 종료되지 않는 것을 확인할 수 있습니다. ., jobs 명령을 통해 여전히 백그라운드에서 실행되고 있음을 확인할 수 있습니다.
5. 메시지 큐와 명명된 파이프의 비교
메시지 대기열과 명명된 파이프 사이에는 많은 유사점이 있습니다. 메시지 대기열을 통해 통신하는 프로세스는 모두 전송 및 전송을 통해 데이터를 전송하는 것과 관련이 없습니다. 전수. 명명된 파이프에서 쓰기는 데이터를 보내는 데 사용되고 읽기는 데이터를 받는 데 사용됩니다. 메시지 큐에서 msgsnd는 데이터를 보내는 데 사용되고 msgrcv는 데이터를 받는 데 사용됩니다. 그리고 각 데이터마다 최대 길이 제한이 있습니다.
명명된 파이프와 비교할 때 메시지 대기열의 장점은 다음과 같습니다. 1. 메시지 대기열은 전송 및 수신 프로세스와 독립적으로 존재할 수도 있으므로 명명된 파이프 열기 및 닫기를 동기화하는 데 발생할 수 있는 어려움을 제거합니다. 2. 동시에 메시지를 보내면 명명된 파이프의 동기화 및 차단 문제를 피할 수 있으며 프로세스 자체에서 동기화 방법을 제공할 필요가 없습니다. 3. Named Pipe처럼 기본적으로 데이터만 수신하는 것이 아니라, 수신 프로그램이 메시지 유형을 통해 선택적으로 데이터를 수신할 수 있습니다.
위 내용은 메시지 대기열이란 무엇입니까? Linux에서 메시지 대기열 사용의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!