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();
}
在需要时用户可以恢复进程的运行,将被挂起的进程从后台转入前台,并从暂停处开始继续运行。
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 : EOF
code date : 2014.03.31
e-mail : jasonleaster@gmail.com
code purpose :
I would like to share my code with someone like me.
Just a demo for signal function. The signal would be loaded
to 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 varible
void 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