Applications:
- server: streamserver
- client: streamclient
Application sources:
- server: /home/< user>/Desktop/socket_programming/server.c
- client: < home>/source/user/efe/streamclient
Building/running applications:
- server: gcc server.c –o streamserver
- client: refer to “Building an application”, “Installing an application” and “Running/testing an application” sections.
Description/synopsis
On a target (INCA-IP2 board) will be run the “streamclient” client application and on a host computer the “streamserver” server application.
“Streamclient” tries to establish stream socket (TCP) connection with “streamserver”, which runs on the host (whos IP address is 192.168.0.98) and listens to the port 3490. When “streamserver” detects incoming connection from the remote target, it sends “Hello world” text as response. “streamclient” will display on the standard output what it has received.
Preperation
1. Enabling port 3490 in firewall
Allow port 3490 by adding following lines (before COMMIT) to “/etc/sysconfig/iptables”:
# Allow port 3490 for an example application
-A INPUT -m state --state NEW -m tcp -p tcp --dport 3490 -j ACCEPT
-A INPUT -m state --state NEW -m udp -p udp --dport 3490 -j ACCEPT
# End of port 3490 rule
After that restart firewall with “service iptables restart” command.
2. Check if port 3490 opened
After loading “streamserver”, open another terminal window and invoke “netstat –na | grep 3490” to check if the port 3490 is open and listened. If the port is open, the command should return:
tcp 0 0 0.0.0.0:3490 0.0.0.0:* LISTEN
Testing example
First, start “streamserver” on the host computer:
server
When starts, it must display:
server: waiting for connections...
Then start “streamclient” on the target. For starting “streamclient”, an IP address of the host must be given as command line argument:
streamclient 192.168.0.98
When the client starts and receives data from the server, it must display:
client: connecting to 192.168.0.98
client: received 'He'
and the server must display:
server: got connection from 192.168.0.97
Then, terminate the server application with CTRL+C command on the host and start again client connection. This time the client must return:
client: connect: Connection refused
client: failed to connect
It means the socket on port 3490 is closed.
Friday, February 12, 2010
Wednesday, February 10, 2010
Select - synchronous I/O multiplexing (оролт/гаралтыг синхрон сонгох)
Юникс програмчлалаас:
#include < sys/time.h>
int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *errorfds, struct timeval *timeout);
void FD_CLR(int fd, fd_set *fdset);
int FD_ISSET(int fd, fd_set *fdset);
void FD_SET(int fd, fd_set *fdset);
void FD_ZERO(fd_set *fdset);
Энэ select() функц нь өгөгдсөн файл тодорхойлогчуудын (file descriptor) аль нь уншихад бэлэн, эсвэл бичихэд бэлэн, эсвэл алдаатай байгааг заана. Хэрэв өгөгдсөн файл тодорхойлогчуудын хувьд заагдсан нөхцөл хангагдаагүй (FALSE) байвал эдгээр файл тодорхойлогчуудын аль нэг дээр заагдсан нөхцөл биелэх хүртэл заасан хугацааг дуустал саатна.
select() функц нь ердийн файлууд, терминал төхөөрөмжүүд, STREAMS файлууд, FIFO төхөөрөмж, pipe төхөөрөмжүүдтэй ажиллах чадвартай.
nfds аргумент нь шалгагдах/тестлэгдэх файл тодорхойлогчдын хязгаарыг заана. Өөрөөр хэлбэл 0-с nfds-1 хязгаарт багтсан файл тодорхойлогчууд шалгагдана.
Хэрэв readfds аргумент нь тэг заагч (null pointer) биш бол, оролтон дээр уншихад бэлнийг нь шалгах файл тодорхойлогчуудыг, гаралтан дээр уншихад бэлэн болсон файл тодорхойлогчуудыг заана. Эдгээр файл тодорхойлуулагчууд нь fd_set төрлийнх байна.
Хэрэв writefds аргумент нь тэг заагч (null pointer) биш бол, оролтон дээр бичихэд бэлнийг нь шалгах файл тодорхойлогчуудыг, гаралтан дээр бичихэд бэлэн болсон файл тодорхойлогчуудыг заана. Эдгээр файл тодорхойлуулагчууд нь мөн адил fd_set төрлийнх байна.
Хэрэв errorfds аргумент нь тэг заагч (null pointer) биш бол, оролтон дээр алдаатай эсэхийг нь шалгах файл тодорхойлогчуудыг, гаралтан дээр алдаа гараад хүлээгдэж байгаа файл тодорхойлогчуудыг заана. Эдгээр файл тодорхойлуулагчууд нь мөн адил fd_set төрлийнх байна.
select() хэвийн гүйцэтгэгдвэл readfds, writefds, errorfds заагчуудын зааж байгаа обьектууд тус бүр уншихад, бичихэд, эсвэл алдаатай файл тодорхойлогчуудыг зааж өөрчлөгдөнө. Мөн энэ тохиолдолд бас nfds хязгаарт багтсан файл тодорхойлогч бүрийн хувьд харгалзах бит нь 1 болно. Үүний тулд оролтонд уг харгалзах бит 1 гэж тавигдсан, тэгээд шалгалт/тестээр файл тодорхойлогчуудад харгалзах нөхцөлүүдээс (уншихад, бичихэд бэлэн, эсвэл алдаатай) биелсэн байх ёстой.
Хэрэв timeout аргумент нь тэг заагч (null pointer) биш бол, энэ аргумент select() функцыг биелж дуусахыг заасан хугацааны интервалыг агуулсан обьектыг заах ба уг обьектын төрөл нь struct timeval байх ёстой. Хэрэв timeout аргументын зааж байгаа struct timeval төрлийн обьектын гишүүд нь 0 утгатай бол select() ерөөсөө саатахгүй (блоклохгүй). Хэрэв timeout аргумент тэг заагч (null pointer) бол select() функц түүний шалгах ёстой эвэнт (event) үнэн зөв (non-zero) утга автал хүлээж саатна (блоклоно). Хэрэв түүний шалгах ёстой эвэнт болохоос өмнө заагдсан хугацааны интервал дуусвал select() 0 утга буцааж, шалгалтаа дуусгана. select()-д ашиглагдах хугацааны интервал нь бусад alarm(), ualarm(), settimer() зэрэг функцүүдээр тавигдсан таймерийн (timer) ажиллагаанд нөлөөлөхгүй. Функцын амжилттай төгссөн тохиолдолд timeout аргументаар заагдаж байсан обьектын утга өөрчлөгдсөн байх талтай.
Хэрэв readfds, writefds, errorfds аргументууд бүгд тэг заагч, харин timeout аргумент тэг заагч биш бол select() заагдсан хугацааны интервал өнгөртөл саатна эсвэл сигналаар ажиллагаа нь тасалдана. Харин эдгээр бүх аргументууд бүгд тэг заагч бол select()-н ажиллагаа зөвхөн сигналаар тасалдана.
Ердийн файлын файл тодорхойлогч ямар ч тохиолдолд уншихад бэлэн, бичихэд бэлэн, алдаатай гэсэн сонголтыг буцаана.
Хэрэв select() амжилтгүй гүйцэтгэгдвэл readfds, writefds, errorfds аргументуудын зааж буй обьектуудын утга өөрчлөгдөхгүй. Хэрэв заагдсан хугацааны интервал шалгагдах нөхцөл биелэхээс өмнө өнгөрвөл readfds, writefds, errorfds аргументын зааж буй обьектууд 0 утга авна.
Өгөгдсөн файл тодорхойлогчуудыг масклах fd_set төрлийн маскууд нь дараахь командаар тохируулагдах ба шалгагдана: FD_CLR(), FD_SET(), FD_ISSET(), FD_ZERO(). Эдгээр нь функц эсвэл макро гэдэг нь тодорхойгүй.
FD_CLR(fd, &fdset) - fdset дэх fd файл тодорхойлогчид харгалзах битийг тэглэнэ (цэвэрлэнэ).
FD_SET(fd, &fdset) - fdset дэх fd файл тодорхойлогчид харгалзах битийг нэглэнэ (тавина).
FD_ISSET(fd, &fdset) - хэрэв fdset дэх fd файл тодорхойлогчид харгалзах бит тавигдсан (нэглэсэн) бол тэгээс ялгаатай утга, үгүй бол 0 утга буцаана.
FD_ZERO(&fdset) - fdset дэх бүх файл тодорхойлогчид харгалзах битийн утгыг тэглэнэ (цэвэрлэнэ).
Хэрэв fd аргументын утга 0-с бага эсвэл FD_SETSIZE-тай тэнцүү буюу түүнээс их байвал (fd < 0, fd >= FD_SETSIZE) эдгээр командууд заагдсан ёсоор биш, харин тодорхойгүй байдлаар ажиллана.
FD_CLR(), FD_SET(), FD_ZERO() командууд ямар ч утга буцаахгүй, харин FD_ISSET() команд fdset дэх fd-д харгалзах битийн утгаас хамаарч 1 эсвэл 0 гэсэн утгыг буцаана.
Хэрэв select() амжилттай биелэгдсэн тохиолдолд бит маскад тавигдсан (нэглэгдсэн) битийн тоотой тэнцүү утга буцаана. Эсрэг тохиолдолд -1 утгыг буцааж, errno-г нэглэнэ.
Source: http://www.opengroup.org/onlinepubs/007908799/xsh/select.html
#include < sys/time.h>
int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *errorfds, struct timeval *timeout);
void FD_CLR(int fd, fd_set *fdset);
int FD_ISSET(int fd, fd_set *fdset);
void FD_SET(int fd, fd_set *fdset);
void FD_ZERO(fd_set *fdset);
Энэ select() функц нь өгөгдсөн файл тодорхойлогчуудын (file descriptor) аль нь уншихад бэлэн, эсвэл бичихэд бэлэн, эсвэл алдаатай байгааг заана. Хэрэв өгөгдсөн файл тодорхойлогчуудын хувьд заагдсан нөхцөл хангагдаагүй (FALSE) байвал эдгээр файл тодорхойлогчуудын аль нэг дээр заагдсан нөхцөл биелэх хүртэл заасан хугацааг дуустал саатна.
select() функц нь ердийн файлууд, терминал төхөөрөмжүүд, STREAMS файлууд, FIFO төхөөрөмж, pipe төхөөрөмжүүдтэй ажиллах чадвартай.
nfds аргумент нь шалгагдах/тестлэгдэх файл тодорхойлогчдын хязгаарыг заана. Өөрөөр хэлбэл 0-с nfds-1 хязгаарт багтсан файл тодорхойлогчууд шалгагдана.
Хэрэв readfds аргумент нь тэг заагч (null pointer) биш бол, оролтон дээр уншихад бэлнийг нь шалгах файл тодорхойлогчуудыг, гаралтан дээр уншихад бэлэн болсон файл тодорхойлогчуудыг заана. Эдгээр файл тодорхойлуулагчууд нь fd_set төрлийнх байна.
Хэрэв writefds аргумент нь тэг заагч (null pointer) биш бол, оролтон дээр бичихэд бэлнийг нь шалгах файл тодорхойлогчуудыг, гаралтан дээр бичихэд бэлэн болсон файл тодорхойлогчуудыг заана. Эдгээр файл тодорхойлуулагчууд нь мөн адил fd_set төрлийнх байна.
Хэрэв errorfds аргумент нь тэг заагч (null pointer) биш бол, оролтон дээр алдаатай эсэхийг нь шалгах файл тодорхойлогчуудыг, гаралтан дээр алдаа гараад хүлээгдэж байгаа файл тодорхойлогчуудыг заана. Эдгээр файл тодорхойлуулагчууд нь мөн адил fd_set төрлийнх байна.
select() хэвийн гүйцэтгэгдвэл readfds, writefds, errorfds заагчуудын зааж байгаа обьектууд тус бүр уншихад, бичихэд, эсвэл алдаатай файл тодорхойлогчуудыг зааж өөрчлөгдөнө. Мөн энэ тохиолдолд бас nfds хязгаарт багтсан файл тодорхойлогч бүрийн хувьд харгалзах бит нь 1 болно. Үүний тулд оролтонд уг харгалзах бит 1 гэж тавигдсан, тэгээд шалгалт/тестээр файл тодорхойлогчуудад харгалзах нөхцөлүүдээс (уншихад, бичихэд бэлэн, эсвэл алдаатай) биелсэн байх ёстой.
Хэрэв timeout аргумент нь тэг заагч (null pointer) биш бол, энэ аргумент select() функцыг биелж дуусахыг заасан хугацааны интервалыг агуулсан обьектыг заах ба уг обьектын төрөл нь struct timeval байх ёстой. Хэрэв timeout аргументын зааж байгаа struct timeval төрлийн обьектын гишүүд нь 0 утгатай бол select() ерөөсөө саатахгүй (блоклохгүй). Хэрэв timeout аргумент тэг заагч (null pointer) бол select() функц түүний шалгах ёстой эвэнт (event) үнэн зөв (non-zero) утга автал хүлээж саатна (блоклоно). Хэрэв түүний шалгах ёстой эвэнт болохоос өмнө заагдсан хугацааны интервал дуусвал select() 0 утга буцааж, шалгалтаа дуусгана. select()-д ашиглагдах хугацааны интервал нь бусад alarm(), ualarm(), settimer() зэрэг функцүүдээр тавигдсан таймерийн (timer) ажиллагаанд нөлөөлөхгүй. Функцын амжилттай төгссөн тохиолдолд timeout аргументаар заагдаж байсан обьектын утга өөрчлөгдсөн байх талтай.
Хэрэв readfds, writefds, errorfds аргументууд бүгд тэг заагч, харин timeout аргумент тэг заагч биш бол select() заагдсан хугацааны интервал өнгөртөл саатна эсвэл сигналаар ажиллагаа нь тасалдана. Харин эдгээр бүх аргументууд бүгд тэг заагч бол select()-н ажиллагаа зөвхөн сигналаар тасалдана.
Ердийн файлын файл тодорхойлогч ямар ч тохиолдолд уншихад бэлэн, бичихэд бэлэн, алдаатай гэсэн сонголтыг буцаана.
Хэрэв select() амжилтгүй гүйцэтгэгдвэл readfds, writefds, errorfds аргументуудын зааж буй обьектуудын утга өөрчлөгдөхгүй. Хэрэв заагдсан хугацааны интервал шалгагдах нөхцөл биелэхээс өмнө өнгөрвөл readfds, writefds, errorfds аргументын зааж буй обьектууд 0 утга авна.
Өгөгдсөн файл тодорхойлогчуудыг масклах fd_set төрлийн маскууд нь дараахь командаар тохируулагдах ба шалгагдана: FD_CLR(), FD_SET(), FD_ISSET(), FD_ZERO(). Эдгээр нь функц эсвэл макро гэдэг нь тодорхойгүй.
FD_CLR(fd, &fdset) - fdset дэх fd файл тодорхойлогчид харгалзах битийг тэглэнэ (цэвэрлэнэ).
FD_SET(fd, &fdset) - fdset дэх fd файл тодорхойлогчид харгалзах битийг нэглэнэ (тавина).
FD_ISSET(fd, &fdset) - хэрэв fdset дэх fd файл тодорхойлогчид харгалзах бит тавигдсан (нэглэсэн) бол тэгээс ялгаатай утга, үгүй бол 0 утга буцаана.
FD_ZERO(&fdset) - fdset дэх бүх файл тодорхойлогчид харгалзах битийн утгыг тэглэнэ (цэвэрлэнэ).
Хэрэв fd аргументын утга 0-с бага эсвэл FD_SETSIZE-тай тэнцүү буюу түүнээс их байвал (fd < 0, fd >= FD_SETSIZE) эдгээр командууд заагдсан ёсоор биш, харин тодорхойгүй байдлаар ажиллана.
FD_CLR(), FD_SET(), FD_ZERO() командууд ямар ч утга буцаахгүй, харин FD_ISSET() команд fdset дэх fd-д харгалзах битийн утгаас хамаарч 1 эсвэл 0 гэсэн утгыг буцаана.
Хэрэв select() амжилттай биелэгдсэн тохиолдолд бит маскад тавигдсан (нэглэгдсэн) битийн тоотой тэнцүү утга буцаана. Эсрэг тохиолдолд -1 утгыг буцааж, errno-г нэглэнэ.
Source: http://www.opengroup.org/onlinepubs/007908799/xsh/select.html
Tuesday, February 9, 2010
Signal handling (Сигнал боловсруулах)
С программчлалаас:
Сигнал гэдэг нь програм ажиллаж явцад үүсч болох онцгой нөхцөлийг (exceptional condition) хэлнэ. Тухайлбал тасалдал (interrupt), программын ажиллах явцад гарах алдаа (run-time error), эсвэл гаднаас үүсэлтэй нөхцөлүүд (program termination/break) байж болно. Сигналтай ажиллах 2 функц, мөн сигналуудын төрлийг "signal.h" гэсэн толгой файлд тодорхойлсон байдаг.
Дараахь сигналын төрлүүд тодорхойлогдсон байдаг:
SIGABRT - Abort буюу програмын хэвийн бус тасралт (abnormal termination). Жишээ нь abort() функцээр үүснэ.
SIGFPE - Floating point exception буюу алдаатай арифметик үйлдлүүд. Жишээ нь тэгд хуваах, эсвэл дүүрэлт г.м.
SIGILL - Illegal instruction буюу програм зөвшөөрөгдөөгүй/танигдахгүй инструкц (процессорын код) агуулсныг мэдээллэнэ.
SIGINT - Interrupt буюу програмын ажиллагааг зогсоох хүсэлтийн гараас буюу терминалаас тавьсныг мэдээллэнэ.
SIGSEGV - Segment violation буюу хадгалах төхөөрөмж (storage) руу хандсан хандалт буруу хийгдсэнийг мэдээллэнэ. Жишээ нь санах ойн хязгаараас давсан хандалт хийх.
SIGTERM - Terminate буюу програмыг зогсоох хүсэлт хийгдсэнийг мэдээллэнэ.
Дээрх стандарт сигналуудаас гадна өөр сигналыг нэмж тодорхойлох боломжтой. Тэр тохиолдолд сигналын нэр заавал SIG гэсэн эхлэлтэй байх ёстой.
#include
void (*signal(int sig, void (*handler)(int)))(int)
signal() фунцк нь sig сигналыг хүлээн авсан үед ямар функцыг (handler()) түүний боловсруулагчаар сонгохыг тохируулна. Уг боловсруулагч функцын аргумент нь тухайн сигнал байж болно. signal() функцын 2 дахь аргументэд SIG_DFL, SIG_IGN гэсэн тусгай утгыг бас оноож өгч болно. Эхнийх нь сигналыг системд урьдчилан зааж өгсөн байдлаар боловсруулах бол дараагийнх нь сигналыг боловсруулахгүйгээр орхино.
signal() функцээр сигнал болон түүнийг боловсруулагч функцын оноолт амжилттай хийгдсэн тохиолдолд боловсруулагч функцын (handler()) өмнөх утга буцна, харин оноолт хийгдэж чадаагүй бол SIG_ERR гэсэн утга буцах ба errno-н утга 1 болно.
Ямар нэгэн сигнал мэдээлэгдвэл, эхлээд програмын ажиллагаа зогсоно. Энэ нь signal(sig, SIG_DFL) гэсэн оноолттой адил шинжтэй. Дараа нь хэрэв тухайн сигналд боловсруулагч функц оноогдсон байвал уг функцыг дуудаж ажиллуулна. Боловсруулагч функц ажиллагаагаа хэвийн дуусгасан тохиолдолд програмын ажиллагаа зогссон цэгээсээ үргэлжлэн ажиллана. Хэрэв сигналын төрөл SIGFPE байсан бол програм үргэлжлэн ажиллахгүй, харин тодорхой байдалд орно. Иймээс SIGFPE сигнал боловсруулах функцууд нь ямагт abort, exit, эсвэл longjump гэсэн функцуудыг агуулсан байх хэрэгтэй.
Програм өөрөө сигналыг мэдээллэх шаардлага заримдаа гардаг. Энэ тохиолдолд raise() функцыг хэрэглэнэ.
#include
int raise (int sig);
Хэрэв raise() функц амжилттай биелэгдвэл 0 утга, үгүй бол тэгээс ялгаатай утга буцаана.
Дараахь жишээ програмд interrupt сигнал хүлээн авсан тохиолдолд програмын ажиллагааг хэрхэн зогсоож байгааг харууллаа.
#include < stdio.h>
#include < stdlib.h>
#include < signal.h>
FILE *temp_file;
void leave(int sig);
main() {
/* сигнал, түүнийг боловсруулагч функцын оноолтыг хийх */
(void) signal(SIGINT,leave);
/* tmp файлыг бичихээр нээх */
temp_file = fopen("tmp","w");
for(;;) {
/* ямар нэг үйлдэл хийх */
printf("Ready...\n");
/* гараас унших */
(void)getchar();
}
/* програм энд хэзээ ч хүрэхгүй ... */
exit(EXIT_SUCCESS);
}
/*
* SIGINT сигналыг хүлээн авмагц, tmp файлыг хаана
* гэхдээ стандарт функцыг (fprintf, fclose) сигнал боловсруулагчаас
* дуудах нь бүх тохиолдолд ажиллах баталгаагүй, энэ нь тухайн системээс
* хамаарна. Тиймээс энэ код ажиллахгүй бол гайхах хэрэггүй.
*/
void
leave(int sig) {
fprintf(temp_file,"\nInterrupted..\n");
fclose(temp_file);
exit(sig);
}
Сигнал гэдэг нь програм ажиллаж явцад үүсч болох онцгой нөхцөлийг (exceptional condition) хэлнэ. Тухайлбал тасалдал (interrupt), программын ажиллах явцад гарах алдаа (run-time error), эсвэл гаднаас үүсэлтэй нөхцөлүүд (program termination/break) байж болно. Сигналтай ажиллах 2 функц, мөн сигналуудын төрлийг "signal.h" гэсэн толгой файлд тодорхойлсон байдаг.
Дараахь сигналын төрлүүд тодорхойлогдсон байдаг:
SIGABRT - Abort буюу програмын хэвийн бус тасралт (abnormal termination). Жишээ нь abort() функцээр үүснэ.
SIGFPE - Floating point exception буюу алдаатай арифметик үйлдлүүд. Жишээ нь тэгд хуваах, эсвэл дүүрэлт г.м.
SIGILL - Illegal instruction буюу програм зөвшөөрөгдөөгүй/танигдахгүй инструкц (процессорын код) агуулсныг мэдээллэнэ.
SIGINT - Interrupt буюу програмын ажиллагааг зогсоох хүсэлтийн гараас буюу терминалаас тавьсныг мэдээллэнэ.
SIGSEGV - Segment violation буюу хадгалах төхөөрөмж (storage) руу хандсан хандалт буруу хийгдсэнийг мэдээллэнэ. Жишээ нь санах ойн хязгаараас давсан хандалт хийх.
SIGTERM - Terminate буюу програмыг зогсоох хүсэлт хийгдсэнийг мэдээллэнэ.
Дээрх стандарт сигналуудаас гадна өөр сигналыг нэмж тодорхойлох боломжтой. Тэр тохиолдолд сигналын нэр заавал SIG гэсэн эхлэлтэй байх ёстой.
#include
void (*signal(int sig, void (*handler)(int)))(int)
signal() фунцк нь sig сигналыг хүлээн авсан үед ямар функцыг (handler()) түүний боловсруулагчаар сонгохыг тохируулна. Уг боловсруулагч функцын аргумент нь тухайн сигнал байж болно. signal() функцын 2 дахь аргументэд SIG_DFL, SIG_IGN гэсэн тусгай утгыг бас оноож өгч болно. Эхнийх нь сигналыг системд урьдчилан зааж өгсөн байдлаар боловсруулах бол дараагийнх нь сигналыг боловсруулахгүйгээр орхино.
signal() функцээр сигнал болон түүнийг боловсруулагч функцын оноолт амжилттай хийгдсэн тохиолдолд боловсруулагч функцын (handler()) өмнөх утга буцна, харин оноолт хийгдэж чадаагүй бол SIG_ERR гэсэн утга буцах ба errno-н утга 1 болно.
Ямар нэгэн сигнал мэдээлэгдвэл, эхлээд програмын ажиллагаа зогсоно. Энэ нь signal(sig, SIG_DFL) гэсэн оноолттой адил шинжтэй. Дараа нь хэрэв тухайн сигналд боловсруулагч функц оноогдсон байвал уг функцыг дуудаж ажиллуулна. Боловсруулагч функц ажиллагаагаа хэвийн дуусгасан тохиолдолд програмын ажиллагаа зогссон цэгээсээ үргэлжлэн ажиллана. Хэрэв сигналын төрөл SIGFPE байсан бол програм үргэлжлэн ажиллахгүй, харин тодорхой байдалд орно. Иймээс SIGFPE сигнал боловсруулах функцууд нь ямагт abort, exit, эсвэл longjump гэсэн функцуудыг агуулсан байх хэрэгтэй.
Програм өөрөө сигналыг мэдээллэх шаардлага заримдаа гардаг. Энэ тохиолдолд raise() функцыг хэрэглэнэ.
#include
int raise (int sig);
Хэрэв raise() функц амжилттай биелэгдвэл 0 утга, үгүй бол тэгээс ялгаатай утга буцаана.
Дараахь жишээ програмд interrupt сигнал хүлээн авсан тохиолдолд програмын ажиллагааг хэрхэн зогсоож байгааг харууллаа.
#include < stdio.h>
#include < stdlib.h>
#include < signal.h>
FILE *temp_file;
void leave(int sig);
main() {
/* сигнал, түүнийг боловсруулагч функцын оноолтыг хийх */
(void) signal(SIGINT,leave);
/* tmp файлыг бичихээр нээх */
temp_file = fopen("tmp","w");
for(;;) {
/* ямар нэг үйлдэл хийх */
printf("Ready...\n");
/* гараас унших */
(void)getchar();
}
/* програм энд хэзээ ч хүрэхгүй ... */
exit(EXIT_SUCCESS);
}
/*
* SIGINT сигналыг хүлээн авмагц, tmp файлыг хаана
* гэхдээ стандарт функцыг (fprintf, fclose) сигнал боловсруулагчаас
* дуудах нь бүх тохиолдолд ажиллах баталгаагүй, энэ нь тухайн системээс
* хамаарна. Тиймээс энэ код ажиллахгүй бол гайхах хэрэггүй.
*/
void
leave(int sig) {
fprintf(temp_file,"\nInterrupted..\n");
fclose(temp_file);
exit(sig);
}
Subscribe to:
Posts (Atom)