10.4.2. Хабарламалармен жұмыс жасауға
арналған жүйелік шақыртулар
213
UNIX хабарламаларымен жұмыс жасау үшін интерфейс файлдармен
жұмыс істейтін интерфейсті еске түсіреді — мұнда объектілерді жасау
үшін функциялар, одан ақпараттарды жазу мен оқу, оның жағдайын
басқару бар. Обьекті ретіндегі файлдар үшін екілік жолдар немесе
мәтіндік файлдардың ақпараттары рөліндегі хабарламалар түседі.
Файлдың күйі — оған қолжеткізу құқығы мен режимі. Обьектілер
рөліндегі хабарламалар үшін хабарламалардың кезегі, ақпараттар
рөліне — хабарламалардың өзі түседі, кезектің күйі оған қол жеткізудің
құқығы мен режимін анықтайды.
Осыған сәйкес, кезекпен жұмыс жасау үшін төрт негізгі функциялар
бар. Бұл функциялардың барлығы тақырыптық файлдардың sys/types.h,
sys/ipc.h және sys/msg.h қосылуын талап етеді:
#include
#include
#include
int msgget( key_t key, int flag);
Кезекті құру және ашу үшін msgget() функциясы қызмет етеді. Бұл
функцияның key параметрі ретінде, бірегей сандық идентификатор
кезегі беріледі (файлдармен жұмыс жасауға арналған fopen() тәрізді
функцияның аналогы). Егер key параметрі ретінде IPC_PRIVATE
тұрақты шамасы берілсе, онда оны құрған процеспен ғана
қолданылатын кезек жасалады. Flag параметрі кезекті құруға арналған
параметрлерді береді. Параметр ретінде IPC_CREAT тұрақты шамасын
берілсе, онда msgget шақыртуы бірегей идентификаторлы берілген
кезекті құрады. Кезекке қолжетімділік құқығын анықтау үшін
IPC_CREAT тұрақты шамасын қолжетімділік құқығы жазбасының
сандық формасын біріктіреді, мынадай:
m_id= msgget (500, IPC_CREAT | 0644);
Сонымен қатар r құқығы кезектен хабрламаларды оқу мүмкіндігін
береді, w құқығы — кезекке хабарламаларды сыйғызады, ал x құқығы
— кезектегі параметрлерді басқаруға мүмкіндік береді.
Мsgget() функциясы кезектің дескрипторын қайтарады, одан кейін
ол жіберілімдер және хабарламаларды қабылдау функциясымен
қолданылады (файлдармен жұмыс жасау үшін дескриптордың аналогы,
FILE* типтік файлдық дескрипторы болып табылады).
Егер msgget() функциясының параметрі ретінде 0 жіберуге болады,
ол идентификатормен берілген кезекті ашады және оның дескрипторын
қайтарады. Егер кезекті құруды IPC_EXCL тұрақты шамасымен
біріктірсе, және кезекті құру және ашу сәтсіз болса, функция -1
қайтарады.
214
Хабарламалар құрылым ретінде ұсынылып, мына параметрлерге ие
болады:
#define LENGTH 25 6
struct message
{
long m_type;
char m_text[LENGTH];
}
Ұзақ бүтін m_type хабарлама түріндегі идентификаторды, m_text
символдар алабын — хабарламалар мәтінін береді. Бағдарламалармен
өңделген хабарламалардың, максималды мүмкін болатын ұзындығын
беретін LENGTH тұрақты шамасы (қаралатын мысалда — 256 символ),
кезекке сыйған хабарламалардың мүмкін болатын ұзындығын беретін
MSGMAX жүйелік тұрақты шамасына тең немесе аз болуы керек:
int msgsnd (int msgfd, void *msgPtr, int len, int
flag);
Кезекке хабарламаларды жіберу үшін msgsnd() функциясы қызмет
етеді, ол msgget() шақыртуының нәтижесінде болатын, msgfd
параметрі ретінде кезектің дескрипторын қабылдайды, msgPtr
шақыртуы ретінде — хабарламалардан тұратын ақпараттар құрылымын
көрсетеді; len параметрі хабарламаның m_text элементінің ұзындығын
береді. Егер flag параметрі ретінде 0 берсе, онда процестің
орындалуын, хабарламаны кезекке сәтті орналастырған сәтке дейін
тоқтата тұруға болады дегенді білдіреді. Мұндай кідірістер, хабарлама
кезегі, msgsnd() шақыртуы кезінде толып және кезектен оның орнын
босатуы үшін хабарламалардың, жеткілікті алуын күту қажеттілігімен
байланысты болуы мүмкін. Егер flag параметрі ретінде IPC_NOWAIT
тұрақты
шамасын
көрсетсе,
онда
операциялардың
сәтсіз
орындалуындағыдай, функция орындалуы тоқтатылады және -1
қайтарады.
Келесі бағдарлама кезек құрады және оған хабарлама жібереді:
#include
#include
#include
#include
#include
struct message
215
{
long length;
char text[256];
} my_msg = { 25, "Sample text message" };
int main()
{
int fd;
fd = msgget(500, IPC_CREAT | IPC_EXCL |0644 );
if (fd != -1 )
{
msgsnd(fd, &my_msg, strlen(my_msg.text)+1,
IPC_NOWAIT);
}
return 0;
}
Келтірілген үлгіде, msgget() функциясының сәтісз қайтару кодының
қарапайым өңделуі енгізілген — кезекті құру мүмкін болмаған
жағдайда (мысалы, кезекті сақтауға арналған жүйелік жады облысы
толып қалса немесе мұндай сандық идентификаторлы кезек болған
болса) хабарлама кезекке жіберілмейді.
Кезектегі хабарламаны алу үшін msgrcv() функциясы қызмет етеді:
int msgrcv(int msgfd, void *msgPtr, int len, int mtype,
int flag);
Мsgfd параметрі ретінде, оған кезектің дескрипторы беріледі;
параметр msgPtr, түскен хабарламаны сыйғызатын, жады облысының
көрсеткішін анықтайды; параметр len, қабылданатын хабарламаның
максималды мүмкін болатын ұзындығын береді. Mtype мәні
қабылданатын хабарламаның типін береді. Бұл параметр келесі
мәндерді қабылдайды:
■
0 — кезектен кез келген типтен ең көне хабарлама алынатын
болады;
■
Оң бүтін сан — кезектен, осы санға тең типті, ең көне хабарлама
алынатын болады;
■
Теріс бүтін сан — кезектен, осы санға тең немесе кіші типті ең көне
хабарлама алынатын болады. Егер кезекте, осы белгіні
қанағаттандыратын бірден көп хабарлама болса, типтің аз мәніне ие
хабарлама қабылданатын болады.
Flag параметрі ретінде 0 көрсетуге болады, бұл жағдайда кезектегі
216
хабарламалардың жоқтығы кезінде, процесс хабарлама алғанға дейін
өзінің орындалуын тоқтатады. Егер параметр ретінде, IPC_NOWAIT
тұрақты шамасын көрсетсе, онда кезектегі қабылдауға арналған қол
жетімді хабарламалар болмаған жағдайда, процесс өзінің орындалуын
жалғастырады. Функция хабарламаны сәтті қабылдаған кезде немесе -
1 сәтсіз болғанда, мысалы хабарлама ұзындығы, len параметрімен
берген ұзындықтан асып кетсе хабарламаның мәтіндік бөлігінің
байттар санын қайтарады. Мұндай жағдайдың алдын алу үшін және
алғашқы len символдарын қабылдау үшін flag параметрі ретінде
MSG_NOERROR тұрақты шамасын көрсетуге болады. Барлық
көрсетілген тұрақты шамаларды ИЛИ операциясының топтары арқылы
біріктіруге болады.
Келесі бағдарламаға алдыңғы бағдарламаның кезекке салған
хабарламалардын қабылдайды және оның мәтіндік бөлігін экранға
шығарады:
#include
#include
#include
#include
#include
struct message
{
long length;
char text[256];
} my_msg = { 0, " --------------- " };
int main()
{
int fd, rcv_res;
fd = msgget(500, IPC_EXCL ) ;
if (fd != -1)
{
rcv_msg = msgrcv(fd, &my_msg, 1024, MSG_NOERROR); if
(rcv_msg != 1)
{
printf("%s\n", &my_msg.text)
}
}
return 0;
}
Хабарламаны сәтсіз қабылдаған кезде бағдарлама экранға ештеңе
217
msqid ds {
ipc perm msg perm; /* кезекке қол жетімділік
права доступа к очереди
msg *msg first
;
/*
кезектегі
алғашқы
хабарламаны көрсетуші */
msg *msg last
;
/*
кезектегі
соңғы
хабарламаны көрсетуші */
msg stime;
/* msgsnd соңғы шақыртуының
уақыты*/
msg rtime;
/* msgrcv соңғы шақыртылған
уақыты*/
msg ctime;
/* кезектегі соңғы өзгерістің
уақыты */
msg cbytes;
/* кезектегі барлық
хабарламалардың сомалық өлшемі
суммарный размер всех сообщений
в очереди */
msg qnum;
/* кезектегі хабарламалар саны
*/
msg qbytes;
/* кезектің байтпен максималды
өлшемі */
msg lspid;
/* кезектегі мәндерді оқитын
соңғы процесс PID */
msg lrpid;
/* кезекке мәндерді жазатын PID
соңғы процесі *
Достарыңызбен бөлісу: |