Wie ist eine Message Queue im Linux-Kernel implementiert?

29

Ich möchte wissen, wie Message Queues im Linux-Kernel implementiert sind.

Sen
quelle
IPC_NOWAIT wir verwenden es nur im Empfänger
Anwaar Qa 20.07.14

Antworten:

41

Der Linux-Kernel (2.6) implementiert zwei Nachrichtenwarteschlangen:
(eher 'Nachrichtenlisten', da die Implementierung über eine verknüpfte Liste erfolgt, die nicht strikt dem FIFO-Prinzip folgt.)

System V IPC-Nachrichten

Die Nachrichtenwarteschlange von System V.

Ein Prozess kann msgsnd()zum Senden einer Nachricht aufgerufen werden. Er muss die IPC-Kennung der empfangenden Nachrichtenwarteschlange, die Größe der Nachricht und eine Nachrichtenstruktur einschließlich Nachrichtentyp und Text übergeben.

Auf der anderen Seite ruft ein Prozess auf msgrcv(), um eine Nachricht zu empfangen, und übergibt die IPC-Kennung der Nachrichtenwarteschlange, in der die Nachricht gespeichert werden soll, die Größe und einen Wert t .

t gibt die von der Warteschlange zurückgegebene Nachricht an. Ein positiver Wert bedeutet, dass die erste Nachricht mit dem Typ t zurückgegeben wird. Ein negativer Wert gibt die letzte Nachricht mit dem Typ t zurück und null gibt die erste Nachricht der Warteschlange zurück.

Diese Funktionen sind in include / linux / msg.h definiert und in ipc / msg.c implementiert

Es gibt Einschränkungen hinsichtlich der Größe einer Nachricht (max), der Gesamtzahl der Nachrichten (mni) und der Gesamtgröße aller Nachrichten in der Warteschlange (mnb):

$ sysctl kernel.msg{max,mni,mnb}
kernel.msgmax = 8192
kernel.msgmni = 1655
kernel.msgmnb = 16384

Die Ausgabe oben stammt von einem Ubuntu 10.10-System, die Standardeinstellungen sind in msg.h definiert .

Weitere Informationen zu unglaublich alten System V-Nachrichtenwarteschlangen finden Sie hier .

POSIX-Nachrichtenwarteschlange

Der POSIX-Standard definiert einen Nachrichtenwarteschlangenmechanismus, der auf der Nachrichtenwarteschlange von System V IPC basiert und diese um einige Funktionen erweitert:

  • Einfache dateibasierte Schnittstelle zur Anwendung
  • Unterstützung für Nachrichtenprioritäten
  • Unterstützung für asynchrone Benachrichtigung
  • Zeitüberschreitungen für das Blockieren von Vorgängen

Siehe ipc / mqueue.c

Beispiel

util-linux stellt einige Programme zum Analysieren und Ändern von Nachrichtenwarteschlangen bereit, und die POSIX-Spezifikation enthält einige C-Beispiele:

Erstellen Sie eine Nachrichtenwarteschlange mit ipcmk; Im Allgemeinen würden Sie dies tun, indem Sie C-Funktionen wie ftok()und aufrufen msgget():

$ ipcmk -Q

Mal sehen, was passiert ist mit ipcsoder mit cat /proc/sysvipc/msg:

$ ipcs -q

------ Message Queues --------
key        msqid      owner      perms      used-bytes   messages    
0x33ec1686 65536      user       644        0            0           

Füllen Sie nun die Warteschlange mit einigen Nachrichten:

$ 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

Auch hier codieren Sie die msqid im Allgemeinen nicht fest im Code.

$ 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        

Und die andere Seite, die die Nachrichten erhalten wird:

$ 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

Schau was passiert:

$ 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           

Nach zwei Empfängen ist die Warteschlange wieder leer.

Entfernen Sie es anschließend, indem Sie key ( -Q) oder msqid ( -q) angeben :

$ ipcrm -q 65536
wedeln
quelle
Wird die Nachricht (Typ und Text) geklont / kopiert und diese Kopie dann in die Nachrichtenwarteschlange des Systems gestellt?
Trusktr
sehr schön ausgedrückt. Vielen Dank für diese erstaunliche Erklärung.
User9102d82