信号与管道(fifo)(转)
转:http://blog.chinaunix.net/uid-26833883-id-3228615.html
一、信号的介绍
1 #include <stdio.h>
2 #include <sys/types.h>
3 #include <signal.h>
4 #include <stdlib.h>
5
6 int main()
7 {
8 int pid;
9
10 if((pid = fork()) < 0)
11 {
12
13 perror("Fail to fork");
14 exit(EXIT_FAILURE);
15
16 }else if(pid == 0){
17
18 while(1);
19
20 }else{
21
22 int signum;
23
24 while(scanf("%d",&signum) == 1)
25 {
26 kill(pid,signum);
27 system("ps -aux | grep a.out");
28 }
29 }
30
31 return 0;
32 }
5. 信号递达,信号未决,可靠信号,不可靠信号,信号集,信号屏蔽字
信号在进程中有两种状态:递达(Delivery)和未决(Pending)。
递达:执行信号的处理动作称为信号递达。
未决:信号已经发出,信号从产生到递达之间的状态(可能被阻塞,也可能在途中)
signal与sigaction
int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigaddset(sigset_t *set, int signo);
int sigdelset(sigset_t *set, int signo);
int sigismember(const sigset_t *set, int signo);
int sigpending(sigset_t *set); //获取当前进程未决信号,存于set信号集
int sigprocmask(int how, const sigset_t *set, sigset_t *oset);
如果oset是非空指针,则读取进程的当前信号屏蔽字通过oset参数传出。如果set是非空指针,则更改进程的信号屏蔽字,参数how指示如何更改。如果oset和set都是非空指针,则先将原来的信号屏蔽字备份到oset里,然后根据set和how参数更改信号屏蔽字。假设当前的信号屏蔽字为mask,下表说明了how参数的可选值。
6. Shell命令发送信号:kill,...
按键发送信号:ctrl+c ,ctrl+\,...
软件发送信号:
子进程结束向父进程发送信号
发送信号函数:kill,raise,sigqueue,abort,alarm,setitimer
程序发生错误发送信号终止(如段错误)
4.避免僵尸进程①signal(SIGCHLD,SIG_IGN);②wait()
调用wait或者waitpid函数,此方法父进程会被挂起(当子进程结束时会自动发送SIGCHLD信号给父进程如果不想让父进程挂起,可以在父进程中加入一条语句:signal(SIGCHLD,SIG_IGN);表示父进程忽略SIGCHLD信号,该信号是子进程退出的时候向父进程发送的。
当一个子进程结束运行时,它与其父进程之间的关联还会保持到父进程也正常地结束运行或者父进程调用了wait才告终止。
进程表中代表子进程的数据项是不会立刻释放的,虽然不再活跃了,可子进程还停留在系统里,因为它的退出码还需要保存起来以备父进程中后续的wait调用使用。它将称为一个“僵进程”。
子进程在终止时会给父进程发SIGCHLD,该信号的默认处理动作是忽略,父进程可以自定义SIGCHLD信号的处理函数,这样父进程只需要专心处理自己的工作,不必关心子进程了,子进程终止时会通知父进程,父进程在信号处理函数中调用wait清理子进程即可。
1 #include <stdio.h>
2 #include <signal.h>
3 #include <unistd.h>
4 #include <stdlib.h>
5
6 void child_exit_handler(int signum)
7 {
8 if(signum == SIGCHLD)
9 {
10 printf("Child exit.\n");
11 wait(NULL);
12 }
13 }
14
15 int main()
16 {
17 int pid;
18 int i = 0;
19
20 //想内核注册,处理 SIGCHLD信号的方式
21 signal(SIGCHLD,child_exit_handler);
22
23 if((pid = fork()) < 0)
24 {
25 perror("Fail to fork");
26 exit(EXIT_FAILURE);
27
28 }else if(pid == 0){
29
30 for(i = 0;i < 5;i ++)
31 {
32 printf("child loop.\n");
33 sleep(1);
34 }
35
36 }else{
37
38 for(i = 0;i < 5;i ++)
39 {
40 printf("Father loop.\n");
41 sleep(2);
42 }
43
44 }
45
46 exit(EXIT_SUCCESS);
47 }
1 #include <stdio.h>
2 #include <signal.h>
3 #include <stdlib.h>
4
5 void handler(int signum)
6 {
7 if(signum == SIGALRM)
8 {
9 printf("Recv SIGALARM.\n");
10 }
11
12 exit(EXIT_SUCCESS);
13 }
14
15 int main()
16 {
17 int count = 0;
18 int n = 0;
19
20 signal(SIGALRM,handler);
21
22 n = alarm(10);
23
24 printf("n = %d.\n",n);
25
26 sleep(2);
27
28 n = alarm(5);
29
30 printf("n = %d.\n",n);
31
32 while(1)
33 {
34 printf("count = %d.\n", ++count);
35 sleep(1);
36 }
37
38 return 0;
39 }
clientA:
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <signal.h>
4 #include <sys/types.h>
5 #include <sys/stat.h>
6 #include <errno.h>
7 #include <string.h>
8 #include <fcntl.h>
9
10 #define MAX 100
11
12 void signal_handler(int signum)
13 {
14 static int flag = 0;
15
16 switch(signum)
17 {
18 case SIGALRM:
19 if(flag == 0)
20 {
21 printf("The people is leaving,the system is closed in 10 seconds \
22 and you can input 'ctrl + c' cancel.\n");
23 alarm(10);
24 }else{
25
26 kill(getppid(),SIGKILL);
27 usleep(500);
28 exit(EXIT_SUCCESS);
29 }
30
31 flag = 1;
32 break;
33
34 case SIGINT:
35 printf("The alarm is cancel.\n");
36 alarm(0);
37 break;
38 }
39
40 }
41
42 int child_recv_fifo(char *fifo_name)
43 {
44 int n,fd;
45 char buf[MAX];
46
47 if((fd = open(fifo_name,O_RDONLY)) < 0)
48 {
49 fprintf(stderr,"fail to open %s : %s.\n",fifo_name,strerror(errno));
50 return -1;
51 }
52
53 signal(SIGALRM,signal_handler);
54 signal(SIGINT,signal_handler);
55 alarm(15);//璁剧疆瀹氭椂鍣?
56 while(1)
57 {
58 n = read(fd,buf,sizeof(buf));
59 buf[n] = '\0';
60
61 printf("Read %d bytes : %s.\n",n,buf);
62
63 if(strncmp(buf,"quit",4) == 0 || n == 0)
64 {
65 kill(getppid(),SIGKILL);
66 usleep(500);
67 exit(EXIT_SUCCESS);
68 }
69
70 alarm(15);
71 }
72
73 return 0;
74 }
75
76 int father_send_fifo(char *fifo_name,int pid)
77 {
78 int n,fd;
79 char buf[MAX];
80
81 if((fd = open(fifo_name,O_WRONLY)) < 0)
82 {
83 fprintf(stderr,"Fail to open %s : %s.\n",fifo_name,strerror(errno));
84 return -1;
85 }
86
87 signal(SIGINT,SIG_IGN);
88
89 while(1)
90 {
91 getchar();
92 printf(">");
93
94 fgets(buf,sizeof(buf),stdin);
95 buf[strlen(buf)-1] = '\0';
96
97 write(fd,buf,strlen(buf));
98
99 if(strncmp(buf,"quit",4) == 0)
100 {
101 kill(pid,SIGKILL);
102 usleep(500);
103 exit(EXIT_SUCCESS);
104 }
105 }
106
107 return 0;
108 }
109
110 int main(int argc,char *argv[])
111 {
112 int pid;
113
114 if(argc < 3)
115 {
116 fprintf(stderr,"usage %s argv[1].\n",argv[0]);
117 exit(EXIT_FAILURE);
118 }
119
120 if(mkfifo(argv[1],0666) < 0 && errno != EEXIST)
121 {
122 perror("Fail to mkfifo");
123 exit(EXIT_FAILURE);
124 }
125
126 if(mkfifo(argv[2],0666) < 0 && errno != EEXIST)
127 {
128 perror("Fail to mkfifo");
129 exit(EXIT_FAILURE);
130 }
131
132 if((pid = fork()) < 0)
133 {
134
135 perror("Fail to fork");
136 exit(EXIT_FAILURE);
137
138 }else if(pid == 0){
139
140 child_recv_fifo(argv[2]);
141
142 }else{
143
144 father_send_fifo(argv[1],pid);
145 }
146
147 exit(EXIT_SUCCESS);
148 }
client B
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <signal.h>
4 #include <sys/types.h>
5 #include <sys/stat.h>
6 #include <errno.h>
7 #include <string.h>
8 #include <fcntl.h>
9
10 #define MAX 100
11
12 void signal_handler(int signum)
13 {
14 static int flag = 0;
15
16 switch(signum)
17 {
18 case SIGALRM:
19 if(flag == 0)
20 {
21 printf("The people is leaving,the system is closed in 10 seconds \
22 and you can input 'ctrl + c' cancel.\n");
23 alarm(10);
24 }else{
25
26 kill(getppid(),SIGKILL);
27 usleep(500);
28 exit(EXIT_SUCCESS);
29 }
30
31 flag = 1;
32 break;
33
34 case SIGINT:
35 printf("The alarm is cancel.\n");
36 alarm(0);
37 break;
38 }
39
40 }
41
42 int child_recv_fifo(char *fifo_name)
43 {
44 int n,fd;
45 char buf[MAX];
46
47 if((fd = open(fifo_name,O_RDONLY)) < 0)
48 {
49 fprintf(stderr,"fail to open %s : %s.\n",fifo_name,strerror(errno));
50 return -1;
51 }
52
53 signal(SIGALRM,signal_handler);
54 signal(SIGINT,signal_handler);
55 alarm(15);//璁剧疆瀹氭椂鍣?
56 while(1)
57 {
58 n = read(fd,buf,sizeof(buf));
59 buf[n] = '\0';
60
61 printf("Read %d bytes : %s.\n",n,buf);
62
63 if(strncmp(buf,"quit",4) == 0 || n == 0)
64 {
65 kill(getppid(),SIGKILL);
66 usleep(500);
67 exit(EXIT_SUCCESS);
68 }
69
70 alarm(15);
71 }
72
73 return 0;
74 }
75
76 int father_send_fifo(char *fifo_name,int pid)
77 {
78 int n,fd;
79 char buf[MAX];
80
81 if((fd = open(fifo_name,O_WRONLY)) < 0)
82 {
83 fprintf(stderr,"Fail to open %s : %s.\n",fifo_name,strerror(errno));
84 return -1;
85 }
86
87 signal(SIGINT,SIG_IGN);
88
89 while(1)
90 {
91 getchar();
92 printf(">");
93
94 fgets(buf,sizeof(buf),stdin);
95 buf[strlen(buf)-1] = '\0';
96
97 write(fd,buf,strlen(buf));
98
99 if(strncmp(buf,"quit",4) == 0)
100 {
101 kill(pid,SIGKILL);
102 usleep(500);
103 exit(EXIT_SUCCESS);
104 }
105 }
106
107 return 0;
108 }
109
110 int main(int argc,char *argv[])
111 {
112 int pid;
113
114 if(argc < 3)
115 {
116 fprintf(stderr,"usage %s argv[1].\n",argv[0]);
117 exit(EXIT_FAILURE);
118 }
119
120 if(mkfifo(argv[1],0666) < 0 && errno != EEXIST)
121 {
122 perror("Fail to mkfifo");
123 exit(EXIT_FAILURE);
124 }
125
126 if(mkfifo(argv[2],0666) < 0 && errno != EEXIST)
127 {
128 perror("Fail to mkfifo");
129 exit(EXIT_FAILURE);
130 }
131
132 if((pid = fork()) < 0)
133 {
134
135 perror("Fail to fork");
136 exit(EXIT_FAILURE);
137
138 }else if(pid == 0){
139
140 child_recv_fifo(argv[1]);
141
142 }else{
143
144 father_send_fifo(argv[2],pid);
145 }
146
147 exit(EXIT_SUCCESS);
148 }
pause()会令目前的进程暂停(进入睡眠状态),直到被信号signal中断。