Assoc. Prof. Wiroon Sriborrirux, Founder of Advance Innovation Center (AIC) and Bangsaen Design House (BDH), Electrical Engineering Department, Faculty of Engineering, Burapha University
// signal1.c#include<stdio.h>#include<signal.h>#include<unistd.h>voidsignalHandler(int signo) {if (signo == SIGINT)printf(" received SIGINT\n");}intmain(void) {printf("My pid is %d.\n", getpid());if (signal(SIGINT, signalHandler)== SIG_ERR)printf("\n Can't catch SIGINT\n");// A long long wait so that we can easily issue a signal to this processwhile (1)sleep(1);return0;}
$ gcc -o signal1 signal1.c -Wall
$ ./signal1
My pid is 21231
(ให้กด Ctrl+C เพื่อส่งสัญญาณให้กับโปรแกรม)
^C received SIGINT
^C received SIGINT
^C received SIGINT
^C received SIGINT
^C received SIGINT
^C received SIGINT
(ให้กด Ctrl+Z เพื่อส่งสัญญาณให้กับโปรแกรม)
^Z
[1]+ Stopped ./signal1
หน้าต่าง Terminal 1 ให้ทำการ compile และรันโปรแกรม signal1จะสังเกตเห็นว่าโปรแกรมจะแสดง Process ID (PID) ของตัวเอง เพื่อให้โปรเซสอื่น ๆ สามารถสื่อสารได้
$ gcc -o signal1 signal1.c -Wall
$ ./signal1
My pid is 21231
ให้เปิด terminal ใหม่อีกหน้าต่าง (Terminal 2) แล้วให้พิมพ์คำสั่ง kill เพื่อส่งสัญญาณ SIGINT ไปยัง Process ID หมายเลข 21231 ซึ่งก็คือโปรแกรม signal1 นั่นเอง ดังแสดงข้างล่าง
$ gcc -o signal1 signal1.c -Wall
$ ./signal1
My pid is 21231
received SIGINT <--------- แสดงข้อความเมื่อตรวจจับสัญญาณ SIGINT จาก Terminal 2
ตัวอย่างที่ 2
แสดงตัวอย่างโปรเซสลูกจะวนรอรับ signal ที่จะถูกส่งมาจากผู้ใช้เช่น Ctrl+C เป็นต้น โดยโปรเซสแม่จะรอโปรเซสลูกจนกว่าจะทำงานสิ้นสุด
// signal2.c#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<sys/wait.h>#include<signal.h>voidHandlerChild() {printf("Sigint received by child \n");}voidHandlerParent() {printf("Sigint received by Parent \n");signal(SIGINT, HandlerParent);}int n, statusp;intmain(void) {// signal(SIGINT,HandlerParent); n =fork();if (n ==0) {printf("Child ID %d\n", getpid());signal(SIGINT, HandlerChild);for (;;) { }; } else {printf("Parent ID %d \n", getpid());// signal(SIGINT,HandlerParent);wait(&statusp);// kill(n,SIGKILL);exit(0); }return0;}
$ gcc -o signal2 signal2.c -Wall
$ ./signal2
Parent ID 4564
Child ID 4565
^CSigint received by child
// signal3.c#include<stdio.h>#include<signal.h>#include<unistd.h>int r, count =0, n;voidHL_AlarmSig(int al) {printf(" I am active every 5 sec ");signal(SIGALRM, HL_AlarmSig); r =alarm(5); count++;printf(" .... Now the time is %d sec \n", count *5);}voidHL_AllSig(int s) {printf(" Oh ! I just received signal number %d \n", s);signal(s, HL_AllSig);}intmain(void) {for (n =1; n <=31; n++) {signal(n, HL_AllSig); }signal(SIGALRM, HL_AlarmSig); r =alarm(5);while (count <12) { };printf(" Program Terminate !! ");return0;}
$ gcc -o signal3 signal3.c -Wall
$ ./signal3
^C Oh ! I just received signal number 2
^C Oh ! I just received signal number 2
^C Oh ! I just received signal number 2
I am active every 5 sec .... Now the time is 5 sec
^Z Oh ! I just received signal number 20
^\ Oh ! I just received signal number 3
I am active every 5 sec .... Now the time is 10 sec
I am active every 5 sec .... Now the time is 15 sec
^C Oh ! I just received signal number 2
^C Oh ! I just received signal number 2
^C Oh ! I just received signal number 2
^Z Oh ! I just received signal number 20
^Z Oh ! I just received signal number 20
I am active every 5 sec .... Now the time is 20 sec
I am active every 5 sec .... Now the time is 25 sec
I am active every 5 sec .... Now the time is 30 sec
I am active every 5 sec .... Now the time is 35 sec
I am active every 5 sec .... Now the time is 40 sec
I am active every 5 sec .... Now the time is 45 sec
I am active every 5 sec .... Now the time is 50 sec
I am active every 5 sec .... Now the time is 55 sec
I am active every 5 sec .... Now the time is 60 sec
// signal4.c#include<stdio.h>#include<signal.h>#include<unistd.h>int r, n;voidHL_AlarmSig(int al) {printf(" Every 5 sec I have to tell you this PID \n");printf(" ....... THIS PROCESS ID = %d ....... \n", getpid());signal(SIGALRM, HL_AlarmSig); r =alarm(5);}voidNothing(int s) {signal(s, Nothing);}voidInfiniteLoop(int s) {printf(" No ! I don't care signal number %d \n", s);printf("If you want to stop this process send signal number 9 ONLY!!!\n");signal(s, InfiniteLoop);for (;;) {printf("Loop\n"); }; /* infinite loop */}intmain(void) {for (n =1; n <=31; n++) {signal(n, Nothing); }signal(SIGINT, InfiniteLoop);signal(SIGALRM, HL_AlarmSig);printf(" If you want to go into the infinite loop \n");printf(" .......press ^C within 5 sec...... \n "); r =alarm(5);for (;;) { };printf(" Program Terminate !! \n");return0;}
$ gcc -o signal4 signal4.c -Wall
$ ./signal4
If you want to go into the infinite loop
.......press ^C within 5 sec......
Every 5 sec I have to tell you this PID
....... THIS PROCESS ID = 21538 .......
Every 5 sec I have to tell you this PID
....... THIS PROCESS ID = 21538 .......
(ถ้ากด Ctrl+C โปรแกรมจะเข้าลูปอนันต์)
ตัวอย่างที่ 5
แสดงตัวอย่างโปรแกรม
// signal5.c#include<stdio.h>#include<stdlib.h>#include<signal.h>#include<unistd.h>#include<sys/wait.h>int n, status;voidHL_Child(int s) {printf("**Child**I received signal No. %d .. you can't kill me \n", s);signal(s, HL_Child);}voidHL_Parent(int s) {printf("***Parent*** I received signal number %d \n", s);signal(s, HL_Parent);}voidHL_Parent14(int s) {printf("***Parent*** I received signal No. %d == Alarm Signal \n", s);signal(s, HL_Parent14);}voidHL_Child14(int s) {printf("***Child*** I received signal No %d == Alarm Signal \n", s);signal(s, HL_Child14);}voidHL_Child3(int s) {printf("***Child*** I received signal No %d .. I will exit \n", s);exit(5);}intmain(void) {int i;for (i =1; i <=31; i++)signal(i, HL_Parent); n =fork();if (n ==0) /* Child Process */ {for (i =1; i <=31; i++)signal(i, HL_Child);signal(SIGALRM, HL_Child14);signal(3, HL_Child3);alarm(2);printf("--c-- Child ID = %d \n", getpid());printf("--c-- Child Process goes into the infinite loop \n");printf("--c-- Signal number 3 (^\\) can kill me \n");for (;;) { }; } else /* Parent Process */ {printf("--p-- Parent ID = %d \n", getpid());signal(SIGALRM, HL_Parent14); /* alarm(2); */printf("--p-- I am waiting for child exit or any signal \n");wait(&status);printf("--p-- Wait completed !! and I am waiting again ...\n");wait(&status);printf("--p-- Wait completed !! ...exit status = %d\n", status >>8);printf("--p-- I am pausing for check signal from child exit ... \n");pause();wait(&status);printf("--p-- Wait completed !! ...exit status = %d \n", status >>8);printf("--p-- I will execute newprog now !! \n");for (i =1; i <=31; i++)signal(i, SIG_IGN);signal(3, SIG_DFL);signal(2, HL_Parent); i =execl("newprog","newprog",0);printf("--p-- Parent Process terminated !!\n");exit(0); }return0;}
$ gcc -o signal5 signal5.c -Wall
$ ./signal5
--p-- Parent ID = 22119
--p-- I am waiting for child exit or any signal
--c-- Child ID = 22120
--c-- Child Process goes into the infinite loop
--c-- Signal number 3 (^\) can kill me
(กด Ctrl+C เพื่อส่งสัญญาณให้ child process)
^C***Parent*** I received signal number 2
**Child**I received signal No. 2 .. you can't kill me
(กด Ctrl+C เพื่อส่งสัญญาณให้ child process)
^C***Parent*** I received signal number 2
**Child**I received signal No. 2 .. you can't kill me
***Child*** I received signal No 14 == Alarm Signal
(กด Ctrl+Z เพื่อส่งสัญญาณให้ child process)
^Z**Child**I received signal No. 18 .. you can't kill me
***Parent*** I received signal number 18
(ถ้ากด Ctrl+\ เพื่อส่งสัญญาณให้ child process เพื่อเรียกฟังก์ชัน HL_Child3() )
^\***Parent*** I received signal number 3
***Child*** I received signal No 3 .. I will exit
***Parent*** I received signal number 20
--p-- Wait completed !! and I am waiting again ...
--p-- Wait completed !! ...exit status = 5
--p-- I am pausing for check signal from child exit ...
(กด Ctrl+C เพื่อสั่งหยุดโปรแกรม)
^C***Parent*** I received signal number 2
--p-- Wait completed !! ...exit status = 5
--p-- I will execute newprog now !!
--p-- Parent Process terminated !!
/* * signal6.c * * The parent process pulls a child exit status whenever the OS notifies * a child status change. * * Created by Mij <mij@bitchx.it> on 04/01/05. * Original source file available at http://mij.oltrelinux.com/devel/unixprg/ * *//* for printf() and fgetc() */#include<stdio.h>/* for fork() */#include<sys/types.h>#include<unistd.h>/* for srandom() and random() */#include<stdlib.h>/* for time() [seeding srandom()] */#include<time.h>/* for waitpid() */#include<sys/wait.h>/* for signal(), kill() and raise() */#include<signal.h>/* how many childs to raise */#defineNUM_PROCS5/* handler prototype for SIGCHLD */voidchild_handler(int);intmain(int argc,char*argv[]) {int i, exit_status; /* execute child_handler() when receiving a signal of type SIGCHLD */signal(SIGCHLD,&child_handler); /* initialize the random num generator */srandom(time(NULL));printf("Try to issue a \'ps\' while the process is running...\n"); /* produce NUM_PROCS childs */for (i =0; i < NUM_PROCS; i++) {if (!fork()) { /* child */ /* choosing a random exit status between 0 and 99 */ exit_status = (int) (random()%100);printf(" -> New child %d, will exit with %d.\n", (int) getpid(), exit_status); /* try to skip signals overlapping */sleep((unsignedint) (random() %3)); /* choosing a value to exit between 0 and 99 */exit(exit_status); } /* father */sleep((unsignedint) (random() %2)); } /* checkpoint */printf("parent: done with fork()ing.\n"); /* why this is not equivalent to sleep(20) here? */for (i =0; i <10; i++) {sleep(1); } /* all the child processes should be done now */printf("I did not purge all the childs. Timeout; exiting.\n"); /* terminate myself => exit */kill(getpid(),15); /* this won't be actually executed */return0;}/* handler definition for SIGCHLD */voidchild_handler(int sig_type) {int child_status;pid_t child;staticint call_num =0; /* getting the child's exit status */ child =waitpid(0,&child_status,0);printf("<- Child %d exited with status %d.\n", child, WEXITSTATUS(child_status)); /* did we get all the childs? */if (++call_num >= NUM_PROCS) {printf("I got all the childs this time. Going to exit.\n");exit(0); }return;}
$ gcc -o signal6 signal6.c -Wall
$ ./signal6
Try to issue a 'ps' while the process is running...
-> New child 12274, will exit with 68.
-> New child 12275, will exit with 57.
-> New child 12276, will exit with 96.
parent: done with fork()ing.
-> New child 12277, will exit with 18.
-> New child 12278, will exit with 72.
<- Child 12275 exited with status 57.
<- Child 12274 exited with status 68.
<- Child 12277 exited with status 18.
<- Child 12276 exited with status 96.
<- Child 12278 exited with status 72.
I got all the childs this time. Going to exit.