signal 函数只能接受一次信号? The naughty signal function
来源:互联网 发布:如何用java编写游戏 编辑:程序博客网 时间:2024/06/04 19:59
The naughty signal function
#include <signal.h> typedef void (*sighandler_t)(int); sighandler_t signal(int signum, sighandler_t handler);
#include"apue.h"#include"stdio.h"#include"myerr.h"static void sig_usr(int);int main(){ if(signal(SIGUSR1,sig_usr) == SIG_ERR) { err_sys("signal error\n"); } if(signal(SIGUSR2,sig_usr) == SIG_ERR) { err_sys("can't catch SIGUSR2"); } for(;;) { pause(); } return 0;}static void sig_usr(int signo){ if(signo == SIGUSR1) { printf("received SIGUSR1\n"); } else if(signo == SIGUSR2) { printf("received SIGUSR2\n"); } else { err_dump("received signal %d\n",signo); }}
jasonleaster@ubuntu:/Ad_Pro_in_Unix/chapter_10$ ./a.out &
[1] 3310
jasonleaster@ubuntu:/Ad_Pro_in_Unix/chapter_10$ kill -USR1 3310
jasonleaster@ubuntu:/Ad_Pro_in_Unix/chapter_10$ received SIGUSR1
kill -USR2 3310
received SIGUSR2
jasonleaster@ubuntu:/Ad_Pro_in_Unix/chapter_10$ ps
PID TTY TIME CMD
3187 pts/0 00:00:00 bash
3310 pts/0 00:00:00 a.out
3311 pts/0 00:00:00 ps
jasonleaster@ubuntu:/Ad_Pro_in_Unix/chapter_10$ ps
PID TTY TIME CMD
3187 pts/0 00:00:00 bash
3310 pts/0 00:00:00 a.out
3312 pts/0 00:00:00 ps
jasonleaster@ubuntu:/Ad_Pro_in_Unix/chapter_10$ kill -USR1 3310
[1]+ User defined signal 1 ./a.out
jasonleaster@ubuntu:/Ad_Pro_in_Unix/chapter_10$ ps
PID TTY TIME CMD
3187 pts/0 00:00:00 bash
3313 pts/0 00:00:00 ps
for(;;){ pause();}
挂起是指在操作系统进程管理将前台的进程暂停并转入后台的动作。将进程挂起可以让用户在前台执行其他的进程。挂起的进程通常释放除CPU以外已经占有的系统资源,如内存等。
在需要时用户可以恢复进程的运行,将被挂起的进程从后台转入前台,并从暂停处开始继续运行。
jasonleaster@ubuntu:/Ad_Pro_in_Unix/chapter_10$ ./a.out &[1] 3310jasonleaster@ubuntu:/Ad_Pro_in_Unix/chapter_10$ kill -USR1 3310jasonleaster@ubuntu:/Ad_Pro_in_Unix/chapter_10$ received SIGUSR1
但是为什么送第二次相同的信号就死掉了呢?
原因在这里
if(signal(SIGUSR1,sig_usr) == SIG_ERR) { err_sys("signal error\n"); } if(signal(SIGUSR2,sig_usr) == SIG_ERR) { err_sys("can't catch SIGUSR2"); }这个就是创建signal handler函数的语句。
我们必须非常仔细的注意,这里的signal handler的declaration:
static void sig_usr(int);
static的作用并不是把函数放在 静态内存区域,而是限定函数的作用域。signal handler是在stack上面的!
这才是问题的关键!这么以来,上面的code就只将sig_usr 载入了两次,一次给SIGUSR 1,一次给SIGUSR2
触发signal handler之后是会被弹栈的!这个时候signal handler就木有了!
之后如果继续向signal handler 发送信号就会触发default behaviour for SIGUSR1 and SIGUSR2.
他们的default behaviour就是termination 。。。so 程序挂掉。
if(signal(SIGUSR1,sig_usr) == SIG_ERR){ err_sys("signal error\n");}if(signal(SIGUSR2,sig_usr) == SIG_ERR){ err_sys("can't catch SIGUSR2");}
/*********************************************************************code writer : EOFcode date : 2014.03.31e-mail : jasonleaster@gmail.comcode purpose : I would like to share my code with someone like me.Just a demo for signal function. The signal would be loadedto stack.Load once, pop once.**********************************************************************/#include"apue.h"#include"stdio.h"#include"myerr.h"static void sig_usr(int);int main(){ int temp = 0; if(signal(SIGUSR1,sig_usr) == SIG_ERR) { err_sys("signal error\n"); } if(signal(SIGUSR2,sig_usr) == SIG_ERR) { err_sys("can't catch SIGUSR2"); } for(temp = 0;1;temp++) { pause(); if(temp < 1) { if(signal(SIGUSR1,sig_usr) == SIG_ERR) { err_sys("signal error\n"); } if(signal(SIGUSR2,sig_usr) == SIG_ERR) { err_sys("can't catch SIGUSR2"); } } } return 0;}static void sig_usr(int signo){ if(signo == SIGUSR1) { printf("received SIGUSR1\n"); } else if(signo == SIGUSR2) { printf("received SIGUSR2\n"); } else { err_dump("received signal %d\n",signo); }}
[1] 3372
liuzjian@ubuntu:/Ad_Pro_in_Unix/chapter_10$ kill -USR1 3372
received SIGUSR1
liuzjian@ubuntu:/Ad_Pro_in_Unix/chapter_10$ kill -USR1 3372
received SIGUSR1
liuzjian@ubuntu:/Ad_Pro_in_Unix/chapter_10$ kill -USR1 3372
[1]+ User defined signal 1 ./a.out
#include <stdio.h>#include <unistd.h>#include <signal.h>#include <stdlib.h>void handler1(int sig){ pid_t pid; if((pid = waitpid(-1,NULL,0)) < 0) { printf("waitpid error\n"); } printf("Handler reaped child %d\n",(int)pid); sleep(2); return;}int main(){ int i,n; pid_t pid; char buf[BUFSIZ]; if(signal(SIGCHLD,handler1) == SIG_ERR) { printf("signal error\n"); } for(i = 0;i < 3;i++) { if((pid = fork()) < 0) { printf("fork error\n"); } else if(pid == 0) { printf("Hello from child%d\n",(int)getpid()); sleep(2); exit(0); } } if((n = read(STDIN_FILENO,buf,sizeof(buf)-1)) < 0) { printf("read error\n"); } printf("parent processsing input\n"); while(1) { } exit(0);}
waitpid(-1,NULL,0)
#include <stdio.h>#include <stdlib.h>int main(){ pid_t pid; int temp = 0; for(temp = 0;temp < 3;temp++) { if((pid = fork()) == 0) { sleep(1); exit(0); } } while((pid = waitpid(-1,NULL,0)) > 0) { printf("Handler reaped child %d\n",(int)pid); } printf("pid %d\n",pid); return 0;}
Handler reaped child 10228
Handler reaped child 10227
Handler reaped child 10229
pid -1
<span style="font-size:14px;">#include <stdio.h>#include <stdlib.h>#include <signal.h>void sig_handler(void){ printf("hello world!\n");}int main(){ int temp = 0; struct sigaction act; sigemptyset(&act.sa_mask); act.sa_flags = 0; act.sa_handler = sig_handler; if(sigaction(SIGCHLD,&act,NULL) < 0) { printf("sigaction error\n"); } for(;;) { } return 0;}</span>jasonleaster@ubuntu:/CSAPP/chapter_8$ ./a.out &
[1] 3461
jasonleaster@ubuntu:/CSAPP/chapter_8$ kill -CHLD 3461
hello world!
jasonleaster@ubuntu:/CSAPP/chapter_8$ kill -CHLD 3461
hello world!
jasonleaster@ubuntu:/CSAPP/chapter_8$ kill -CHLD 3461
hello world!
jasonleaster@ubuntu:/CSAPP/chapter_8$ kill -CHLD 3461
hello world!
jasonleaster@ubuntu:/CSAPP/chapter_8$ kill -CHLD 3461
hello world!
#include <stdio.h>#include <unistd.h>#include <signal.h>#include <stdlib.h>#include <errno.h>void handler1(int sig){ pid_t pid; if((pid = waitpid(-1,NULL,0)) < 0) { printf("waitpid error\n"); } printf("Handler reaped child %d\n",(int)pid); sleep(2); return;}int main(){ int i,n; pid_t pid; struct sigaction act; sigemptyset(&act.sa_mask); act.sa_flags = 0; act.sa_handler = handler1; act.sa_flags |= SA_RESTART;// sigaddset(&act.sa_mask,SIGCHLD); char buf[BUFSIZ]; if(sigaction(SIGCHLD,&act,NULL) != 0) { printf("signal error\n"); } for(i = 0;i < 3;i++) { if(fork() == 0) { printf("Hello from child%d\n",(int)getpid()); sleep(1); exit(0); } } if((n = read(STDIN_FILENO,buf,sizeof(buf)-1)) < 0) { printf("read error\n"); } printf("parent processsing input\n"); while(1) { } exit(1);}
Hello from child10283
Hello from child10284
Hello from child10285
Handler reaped child 10284
Handler reaped child 10283
jasonleaster
parent processsing input
Here’s what happened: The first signal is received and caught by the parent. While the handler is still processing the first signal, the second signal is delivered and added to the set of pending signals. However, since SIGCHLD signals are blocked by theSIGCHLD handler the second signal is not received. Shortly there after, while the handler is still processing the first signal, the third signal arrives. Sincethere is already a pending SIGCHLD, this third SIGCHLD signal is discarded. Sometimelater, after the handler hasreturned, the kernel notices that there is a pending SIGCHLD signal and forces the parent to receive the signal. The parent catches the signal and executes the handler a second time. After the handler finishes processing the second signal,there are no more pending SIGCHLD signals, and there never will be, because all knowledge of the third SIGCHLD has beenlost.
Hello from child10315
Hello from child10316
Hello from child10317
Handler reaped child 10315
Handler reaped child 10316
jasonleaster
parent processsing input
^Z
[1]+ Stopped ./a.out
jasonleaster@ubuntu:/CSAPP/chapter_8$ ps
PID TTY TIME CMD
9955 pts/4 00:00:00 bash
10314 pts/4 00:00:01 a.out
10317 pts/4 00:00:00 a.out <defunct>
10318 pts/4 00:00:00 ps
#include <stdio.h>#include <unistd.h>#include <signal.h>#include <stdlib.h>#include <errno.h>void handler1(int sig){ pid_t pid; while((pid = waitpid(-1,NULL,0)) > 0) { printf("Handler reaped child %d\n",(int)pid); } if(errno != ECHILD) { printf("waitpid error\n"); } sleep(2); return;}int main(){ int i,n; pid_t pid; struct sigaction act; sigemptyset(&act.sa_mask); act.sa_flags = 0; act.sa_handler = handler1; act.sa_flags |= SA_RESTART;// sigaddset(&act.sa_mask,SIGCHLD); char buf[BUFSIZ]; if(sigaction(SIGCHLD,&act,NULL) != 0) { printf("sigaction error\n"); } for(i = 0;i < 3;i++) { if(fork() == 0) { printf("Hello from child%d\n",(int)getpid()); sleep(1); exit(0); } } if((n = read(STDIN_FILENO,buf,sizeof(buf)-1)) < 0) { printf("read error\n"); } printf("parent processsing input\n"); while(1) { } exit(0);}
Hello from child10352
Hello from child10353
Hello from child10354
Handler reaped child 10352
Handler reaped child 10354
Handler reaped child 10353
jasonleaster
parent processsing input
^Z
[1]+ Stopped ./a.out
jasonleaster@ubuntu:/CSAPP/chapter_8$ ps
PID TTY TIME CMD
9955 pts/4 00:00:00 bash
10351 pts/4 00:00:01 a.out
10355 pts/4 00:00:00 ps
#include <stdio.h>#include <unistd.h>#include <signal.h>#include <stdlib.h>#include <errno.h>int number = 1;//global variblevoid handler1(int sig){ pid_t pid; printf("pid :%d sig : %d\n",getpid(),sig); while((pid = waitpid(-1,NULL,0)) > 0) { printf("Handler reaped child %d\n",(int)pid); } printf("number :%d pid :%d sig : %d\n",number,getpid(),sig); fflush(NULL); if(errno != ECHILD) { printf("waitpid error\n"); } sleep(2); number++; return;}int main(){ int i,n; pid_t pid; struct sigaction act; sigemptyset(&act.sa_mask); act.sa_flags = 0; act.sa_handler = handler1; act.sa_flags |= SA_RESTART;// sigaddset(&act.sa_mask,SIGCHLD); char buf[BUFSIZ]; if(sigaction(SIGCHLD,&act,NULL) != 0) { printf("sigaction error\n"); } for(i = 0;i < 5;i++) { if(fork() == 0) { printf("Hello from child%d\n",(int)getpid()); sleep(1); exit(0); } } if((n = read(STDIN_FILENO,buf,sizeof(buf)-1)) < 0) { printf("read error\n"); } printf("parent processsing input\n"); while(1) { } exit(0);}
Hello from child4330
Hello from child4331
Hello from child4334
Hello from child4332
Hello from child4333
pid :4329 sig : 17
Handler reaped child 4331
Handler reaped child 4332
Handler reaped child 4334
Handler reaped child 4330
Handler reaped child 4333
number :1 pid :4329 sig : 17
pid :4329 sig : 17
number :2 pid :4329 sig : 17
jasonleaster
parent processsing input
^C
while((pid = waitpid(-1,NULL,0)) > 0) { printf("Handler reaped child %d\n",(int)pid); }
number :2 pid :4329 sig : 17
- signal 函数只能接受一次信号? The naughty signal function
- 信号处理函数 signal
- signal 函数捕捉信号
- Linux 信号函数-signal
- 信号之signal函数
- linux 信号 signal函数
- Linux 信号signal处理函数
- Linux 信号signal处理函数
- Linux 信号signal处理函数
- Linux 信号signal处理函数
- Linux 信号signal处理函数
- Linux 信号signal处理函数
- Linux 信号signal处理函数
- Linux 信号signal处理函数
- signal信号函数个人见解
- Linux 信号signal处理函数
- Linux signal() 信号处理函数
- 信号编程之signal函数
- centos6.4安装搭建pptp vpn服务
- web.xml(1)_icon,display-name,description,distributable
- C++11自学
- 请说出作用域public,private,protected,以及不写时的区别
- 第一次开通博客
- signal 函数只能接受一次信号? The naughty signal function
- Chrome 的查看源代码
- ios常用空间UIScrollViewIndicator的一些属性
- html 关于块级元素和行内元素
- kinect学习NO2
- H3CSE题库有关问题
- hadoop集群默认配置和常用配置
- js 的CheckBox 的全选总结 (Table或GridView中所有的CheckBox处理) j-query的处理
- XP下双硬盘安装linux