Linux 커널에서 메시지 큐가 어떻게 구현되는지 알고 싶습니다.
답변1
Linux 커널(2.6)은 두 개의 메시지 대기열을 구현합니다. (
구현은 연결된 목록을 사용하여 수행되고 선입선출 원칙을 엄격하게 따르지 않기 때문에 "메시지 목록" 대신)
시스템 V IPC 메시지
System V의 메시지 큐.
메시지를 보내기 위해 프로세스를 호출할 수 있습니다 msgsnd()
. 그는 수신 메시지 대기열의 IPC 식별자, 메시지 크기 및 메시지 유형과 텍스트를 포함한 메시지 구조를 전달해야 합니다.
반면, 프로세스 호출은 msgrcv()
메시지를 수신하여 메시지 큐의 IPC 식별자, 메시지가 저장되어야 하는 위치, 크기 및 값을 전달합니다.티.
티큐에서 반환된 메시지를 지정합니다. 양수 값은 유형이 다음과 같은 첫 번째 메시지를 나타냅니다.티반환, 음수 값은 유형과 동일한 마지막 메시지를 반환합니다.티0은 대기열의 첫 번째 메시지를 반환합니다.
이러한 함수는 다음에 정의되어 있습니다.include/linux/msg.h그리고 구현ipc/msg.c
메시지 크기(최대), 총 메시지 수(mni) 및 대기열에 있는 모든 메시지의 총 크기(mnb)는 다음과 같이 제한됩니다.
$ sysctl kernel.msg{max,mni,mnb}
kernel.msgmax = 8192
kernel.msgmni = 1655
kernel.msgmnb = 16384
위 출력은 Ubuntu 10.10 시스템의 출력이며 기본값은 다음에 정의되어 있습니다.메시지.h.
이전 System V 메시지 대기열의 내용에 대한 더 놀라운 설명여기.
POSIX 메시지 큐
POSIX 표준은 System V IPC 메시지 대기열을 기반으로 메시지 대기열 메커니즘을 정의하고 일부 기능을 확장합니다.
- 간단한 파일 기반 애플리케이션 인터페이스
- 지원 메시지 우선순위
- 비동기 알림 지원
- 차단 작업 시간이 초과되었습니다.
바라보다ipc/mqueue.c
예
util-linux
메시지 대기열을 분석하고 수정하기 위해 일부 프로그램이 제공되며 POSIX 사양은 몇 가지 C 예제를 제공합니다.
ipcmk
다음을 사용하여 메시지 대기열을 생성합니다. 일반적으로 ftok()
다음과 같은 C 함수를 호출하여 이 작업을 수행 합니다 msgget()
.
$ ipcmk -Q
ipcs
or 를 사용하여 어떤 일이 일어나는지 봅시다 cat /proc/sysvipc/msg
:
$ ipcs -q
------ Message Queues --------
key msqid owner perms used-bytes messages
0x33ec1686 65536 user 644 0 0
이제 대기열을 일부 메시지로 채웁니다.
$ cat <<EOF >msg_send.c
#include <string.h>
#include <sys/msg.h>
int main() {
int msqid = 65536;
struct message {
long type;
char text[20];
} msg;
msg.type = 1;
strcpy(msg.text, "This is message 1");
msgsnd(msqid, (void *) &msg, sizeof(msg.text), IPC_NOWAIT);
strcpy(msg.text, "This is message 2");
msgsnd(msqid, (void *) &msg, sizeof(msg.text), IPC_NOWAIT);
return 0;
}
EOF
마찬가지로 일반적으로 코드에 msqid를 하드코딩하지 않습니다.
$ gcc -o msg_send msg_send.c
$ ./msg_send
$ ipcs -q
------ Message Queues --------
key msqid owner perms used-bytes messages
0x33ec1686 65536 user 644 40 2
상대방은 다음 메시지를 받게 됩니다.
$ cat <<EOF >msg_recv.c
#include <stdio.h>
#include <sys/msg.h>
int main() {
int msqid = 65536;
struct message {
long type;
char text[20];
} msg;
long msgtyp = 0;
msgrcv(msqid, (void *) &msg, sizeof(msg.text), msgtyp, MSG_NOERROR | IPC_NOWAIT);
printf("%s \n", msg.text);
return 0;
}
EOF
보자:
$ gcc -o msg_recv msg_recv.c
$ ./msg_recv
This is message 1
$ ./msg_recv
This is message 2
$ ipcs -q
------ Message Queues --------
key msqid owner perms used-bytes messages
0x33ec1686 65536 user 644 0 0
두 번의 수신 후에는 대기열이 다시 비어 있습니다.
-Q
그런 다음 key( ) 또는 msqid( )를 지정하여 -q
삭제합니다 .
$ ipcrm -q 65536