node35






WYWOŁANIE SYSTEMOWE: msgsnd()






















Next: WYWOŁANIE SYSTEMOWE: msgctl()
Up: Kolejki wiadomości
Previous: WYWOŁANIE SYSTEMOWE: msgget()
  Contents





WYWOŁANIE SYSTEMOWE: msgsnd()



Kiedy posiadamy identyfikator kolejki możemy przeprowadzać operacje na niej.
Aby wysłać wiadomość do kolejki możemy posłużyć się wywołaniem msgsnd:



WYWOŁANIE SYSTEMOWE: msgsnd();

PROTOTYP: int msgsnd ( int msqid, struct msgbuf *msgp, int msgsz, int msgflg );
ZWRACA: 0 - sukces
-1 - błąd: errno = EAGAIN ( kolejka jest pełna i IPC_NOWAIT jest ustawione )
EACCES ( brak dostępu, brak prawa zapisu )
EFAULT ( adres msgp jest niedostępny lub nieprawidłowy )
EIDRM ( kolejka została usunięta )
EINTR ( otrzymano sygnał podczas próby zapisu )
EINVAL ( nieprawidłowy identyfikator, ujemny typ
lub nieprawidłowy rozmiar wiadomości )
ENOMEM ( brak pamięci do skopiowania bufora wiadomości )
UWAGI:


Pierwszy agrument ( msgsnd ) jest identyfikatorem zwróconym przez msgget.
Drugi ( msgp ) to wskaźnik do naszego bufora wiadomości. Argument msgsz
zawiera rozmiar wiadomości w bajtach, wyłączając długość typu ( 4 bajty ).


Argument msgflg może być ustawiony na 0 ( ignorowany ) lub na:



IPC_NOWAIT



Jeżeli kolejka jest pełna wiadomość nie jest zapisywana, kontrol powraca
do procesu wywołującego. Jeżeli nie podana proces będzie czekał na możliwość zapisu.





Utwórzmy następną przykładową funkcję wysyłającą wiadomości:



int send_message( int qid, struct mymsgbuf *qbuf )
{
int result, length;

/* lenght jest rozmiarem struktury minus sizeof(mtype) */
length = sizeof(struct mymsgbuf) - sizeof(long);

if((result = msgsnd( qid, qbuf, length, 0)) == -1)
{
return(-1);
}

return(result);
}


Ta mała funkcja próbuje wysłać wiadomość pobraną z podanego adresu
w kolejkę o podanym identyfikatorze.


Oto przykładowy kod używający naszych dwóch funkcji:



#include <stdio.h>
#include <stdlib.h>
#include <linux/ipc.h>
#include <linux/msg.h>

main()
{
int qid;
key_t msgkey;
struct mymsgbuf {
long mtype; /* typ wiadomości */
int request; /* numer żądania danego działania */
double salary; /* zapłata od pracodawcy */
} msg;

/* tworzymy wartość klucza IPC */
msgkey = ftok(".", 'm');

/* otwieramy/tworzymy kolejkę */
if(( qid = open_queue( msgkey)) == -1) {
perror("otwieranie_kolejki");
exit(1);
}

/* nasze przykładowe dane */
msg.mtype = 1; /* typ wiadomości musi być dodatni */
msg.request = 1; /* element #1 */
msg.salary = 1000.00; /* element #2 ( mój roczny zarobek! ) */

/* Bomby poszły! */
if((send_message( qid, &msg )) == -1) {
perror("wysyłanie_wiadomości");
exit(1);
}
}


Po utworzeniu/otwarciu naszej kolejki tworzymy bufor z danymi testowymi
(zauważ brak danych znakowych - w celu zademonstrowania możliwości przesyłania informacji binarnej).
Wywołanie send_message przesyła wiadomość do kolejki.


Mamy naszą wiadomość w kolejce, aby sprawdzić status kolejki odpal polecenie ipcs. Teraz zajmijmy się odberaniem informacji z kolejki, do tego celu
służy wywołanie systemowe msgrcv():



WYWOŁANIE SYSTEMOWE: msgrcv();
PROTOTYP: int msgrcv ( int msqid, struct msgbuf *msgp, int msgsz, long mtype, int msgflg );
ZWRACA: ilość bajtów skopiowaną do bufora wiadomości
-1 - błąd: errno = E2BIG ( długość wiadomości jest większa niż msgsz,
brak MSG_NOERROR)
EACCES ( odczyt zabroniony )
EFAULT ( adres wskazywany przez msgp jest nieprawidłowy ) EIDRM (Queue was removed during retrieval)
EINTR ( przerwano z powodu nadchadzącego sygnału )
EINVAL ( nieprawidłowy msgqid invalid lub msgsz ujemny )
ENOMSG ( ustawiono IPC_NOWAIT, a nie ma w kolejce
wiadomości spełniającej żądanie )
UWAGI:


Pierwszy argument określa kolejkę ( powinniśmy go dostać po wywołaniu msgget).
Drugi argument (msgp) jest adresem bufora dla otrzymanej wiadomości. Trzeci
argument (msgsz) określa rozmiar struktury bufora wiadomości, wyłączając
rozmiar członka mtype. Pamietaj, że można to łatwo obliczyć:



msgsz = sizeof(struct mymsgbuf) - sizeof(long);


Czwarty argument (mtype) określa type typ wiadomości do odbioru.
Jądro przeszyka kolejkę w poszukiwaniu najstarszej wiadomości o podanym typie
i prześle jej kopie pod adres wskazywany przez argument msgp. Istnieje jeden
wyjątek: jeżeli mtype ma wartość zero zostanie przesłana najstarsza wiadomość
nie zwracając uwagi na typ.


Jeżeli podano IPC_NOWAIT jako flagę, i brak wiadomości w kolejce wywołanie
zwróci ENOMSG. W innym wypadku proces będzie czekał na wiadomość spełniającą wymagania
msgrcv(). Jeżeli kolejka została skasowana podczas gdy klient czekał na wiadomość
zostanie zwrócone EIDRM. Natomiast EINTR otrzymamy jeżeli sygnał nadszedł gdy
proces oczekiwał na wiadomość.


Oto prosta funkcja odbierająca wiadomość z kolejki:



int read_message( int qid, long type, struct mymsgbuf *qbuf )
{
int result, length;

/* lenght jest rozmiarem struktury minus sizeof(mtype) */
length = sizeof(struct mymsgbuf) - sizeof(long);

if((result = msgrcv( qid, qbuf, length, type, 0)) == -1)
{
return(-1);
}

return(result);
}


Po szczęśliwym odebraniu wiadomości jest ona usuwana z kolejki.


Bit MSG_NOERROR w argumencie msgflg daje nam dodatkowe możliwości.
Jeżeli rozmiar wiadomości jest większy niż msgsz, a my ustawiliśmy flagę
MSG_NOERROR wiadomość zostanie obcięta, otrzymamy tylko msgsz bajtów.
Normalnie wywołanie msgrcv() zwraca -1 (E2BIG), a wiadomość pozostaje
w kolejce. Takie zachowanie umożliwia nam napisanie funkcji, która będzie przeszukiwać
kolejkę w poszukiwaniu odpowiedniej wiadomości:



int peek_message( int qid, long type )
{
int result, length;

if((result = msgrcv( qid, NULL, 0, type, IPC_NOWAIT)) == -1)
{
if(errno == E2BIG)
return(TRUE);
}

return(FALSE);
}


Jak widzisz nie podaliśmy adresu bufora oraz rozmiaru. Zrobiliśmy to dlatego, iż
chcemy aby wywołanie nie powiodło się. Jednocześnie sprawdzamy E2BIG,
który wskazuje czy istnieje w kolejce wiadomość o odpowiednim typie.
Funkcja zwraca TRUE jeżeli istnieje wiadomość o poszukiwanym typie, oraz
FALSE jeżeli nie. Zauważ, że ustawiamy flagę IPC_NOWAIT, która
zapobiega czekaniu na odpowiednią wiadomość.













Next: WYWOŁANIE SYSTEMOWE: msgctl()
Up: Kolejki wiadomości
Previous: WYWOŁANIE SYSTEMOWE: msgget()
  Contents



2000-03-01








Wyszukiwarka

Podobne podstrony:
node35
node35 SIDFDTW4NSXKBALNRDZGOXK5TIVN7EFHNYCP6AI
node35
node35 SCXIOZLSFD7OD7NEGAIVJG36EAXJRUIBSIMR6YA
node35
node35 NUZOLXJWQKD2QRFGFGOSOFWXYBFL5W7E5TBXNAY
node35

więcej podobnych podstron