为了节省篇幅所有测试都忽略错误检查
SIGABRT:
调用abort函数时产生此信号。默认终止进程,可捕捉
6 void sig_abort(int signo){
7 printf("get signal:%s\n",strsignal(signo));
8 }
9
10 int main(void){
11 signal(SIGABRT,sig_abort);
/*
* 给自己发送 SIGABRT信号
*/
12 kill(getpid(),SIGABRT);
13 exit(0);
14 }
输出:
feng@ubuntu:~/learn_linux_c_second/chapter_10$ ./a.out
get signal:Aborted
SIGALRM:
在用alarm函数设置的计时器超时或setitime函数以ITIMER_REAL参数设置的计时器超时,产生此信号,默认终止进程。可捕捉
我们用setitime函数来举例.
3 void sig_alrm(int signo){
4 printf("get signal:%s\n",strsignal(signo));
5 exit(0);
6 }
7
8 int main(void){
9 signal(SIGALRM,sig_alrm);
10 struct itimerval value;
/*
*设置暂停2.5秒
*/
11 value.it_value.tv_sec=2;
12 value.it_value.tv_usec=50000;
13 value.it_interval.tv_sec=0;
14 value.it_interval.tv_usec=0;
15
16 setitimer(ITIMER_REAL,&value,NULL);
17 while(1);
18 }
输出:
feng@ubuntu:~/learn_linux_c_second/chapter_10$ ./a.out
get signal:Alarm clock
SIGBUS:
指示一个实现定义的硬件故障。当出现某些内存故障时,尝尝产生此信号。例如访问用mmap映射的存储区的某一部分。而在访问这一部分时,该部分实际
上已经不存在了。怎会产生该信号。默认终止。可捕捉:
4 void sig_bus(int signo){
5 printf("get signal:%s\n",strsignal(signo));
6 exit(0);
7 }
8
9 int main(void){
10 int fd;
11 fd=open("test",O_RDWR);
12
13 char *buf;
/*
* 映射前五个字符
*/
14 buf=mmap(0,5*sizeof(char),PROT_READ,MAP_SHARED,fd,0 );
/*
* 截断文件使映射区已不存在
*/
15 ftruncate(fd,0);
/*
* 尝试访问 映射区
*/
17 printf("%c\n",buf[1]);
18 exit(0);
19 }
输出如下
feng@ubuntu:~/learn_linux_c_second/chapter_10$ ./a.out
get signal:Bus error
SIGCHLD:
在一个进程终止或停止时,将该信号发送给其父进程。默认忽略。可捕捉。该信号可以使当子进程终止时,父进程收到信号后,在信号处理函数中
调用wait获得子进程终止状态。从而避免父进程阻塞在等待子进程结束上。
3 void sig_chld(int signo){
4 wait(NULL);
5 printf("get signal:%s\n",strsignal(signo));
6 }
7
8 int main(){
9 signal(SIGCHLD,sig_chld);
10 pid_t pid;
11 if((pid=fork())==-1){
12 perror("fork error");
13 exit(1);
14 }else if(pid==0){ //child
15 exit(0);
16 }else{ //parent
17 sleep(1);
18 }
19 exit(0);
20 }
输出如下:
feng@ubuntu:~/learn_linux_c_second/chapter_10$ ./a.out
get signal:Child exited
SIGTSTP:
交互式停止信号,当用户在终端上按挂起键(ctrl+z)时,终端驱动程序产生此信号,该信号送至前台进程组中的所有进程。默认暂停进程,可捕捉。
6 void sig_tstp(int signo){
7 printf("get signal:%s\n",strsignal(signo));
8 exit(0);
9 }
10
11 int main(void){
12 signal(SIGTSTP,sig_tstp);
13 while(1){
14 printf("a\n");
15 sleep(1);
16 }
17 return 0;
18 }
输出:
feng@ubuntu:~/learn_linux_c_second/chapter_10$ ./a.out
a
a
a
^Zget signal:Stopped
SIGCONT:
当前处于暂停状态的进程接受到此信号时会继续运行。可捕捉。
a程序如下
3 int main(void){
4 printf("we will stop\n");
5 kill(getpid(),SIGTSTP);
6 printf("continue\n");
7 exit(0);
8 }
运行时输出:
feng@ubuntu:~/learn_linux_c_second/chapter_10$ ./a.out
we will stop
[1]+ Stopped ./a.out
我们用ps命令查看a 程序pid:
6108 pts/0 00:00:00 a.out
再用b 程序向a程序发送SIGCONT信号:
3 int main(void){
4 kill(6108,SIGCONT);
5 exit(0);
6 }
输出如下:
feng@ubuntu:~/learn_linux_c_second/chapter_10$ ./b.out
feng@ubuntu:~/learn_linux_c_second/chapter_10$ continue
[1]- Done ./a.out
我们看到 a 进程收到信号后继续运行。
SIGFPE:
此信号表示一个算数运算异常:
3 void sig_fpe(signo){
4 printf("get signal:%s\n",strsignal(signo));
5 exit(0);
6 }
7
8 int main(void){
9 signal(SIGFPE,sig_fpe);
10 int a=1/0;
11 exit(0);
12 }
输出如下:
feng@ubuntu:~/learn_linux_c_second/chapter_10$ ./a.out
get signal:Floating point exception
SIGINT:
当用话按下中断键(ctrl+c)时,中断驱动程序产生此信号并送至前台进程组中的每一个进程。默认终止进程,可捕捉
4 void sig_int(int signo){
5 printf("\nget signal:%s\n",strsignal(signo));
6 exit(0);
7 }
8
9 int main(void){
10 signal(SIGINT,sig_int);
11 while(1);
12 exit(0);
13 }
输出如下:
feng@ubuntu:~/learn_linux_c_second/chapter_10$ ./a.out
^C
get signal:Interrupt
SIGIO:
SIGPOLL:
linux中这两个信号相同,都指示一个异步i/o事件
关于下面例子中中的poll函数使用方法,请查找相关资料。
4 void sig_io(int signo){
5 printf("get signal:%s\n",strsignal(signo));
6 }
7
8 int main(void){
9 signal(SIGPOLL,sig_io);
10
11 fcntl(1,F_SETOWN,getpid());//设置接收 对于标准输入(1)的信号
12 fcntl(1,F_SETFL,O_ASYNC); //设置可进行异步i/o
13
struct pollfd test;
14 test.fd=1;
15 test.events=POLLRDNORM;//等待事件为 不阻塞的可读普通数据
16 poll(&test,1,-1); //无限等待
17
18 exit(0);
19 }
运行输出如下:
feng@ubuntu:~/learn_linux_c_second/chapter_10$ ./a.out
get signal:I/O possible
标准输出 应该总是不阻塞可读的,所以进程受到 SIGIO 信号
SIGKILL:
该信号都不能捕捉,用来终止进程
3 void sig_kill(int signo){
4 printf("get SIGKILL\n");
5 }
6
7 int main(void){
8 signal(SIGKILL,sig_kill);
9 kill(getpid(),SIGKILL);
10 exit(0);
11
12 }
我们试图捕获该信号。如果捕获 应该会 打印 "get SIGKILL"
输出如下:
feng@ubuntu:~/learn_linux_c_second/chapter_10$ ./a.out
Killed
从输出 我们看到 该进程只是被杀死了。但是该信号并未被捕获
SIGPIPE:
如果在写数据到管道时读进程已经终止,则产生此信号。当类型为SOCK_STREAM的套接字已不再
链接时,进程写数据到该套接字也产生此信号
我们以管道来举例:
读进程:以读方式打开管道,随后关闭。
4 int main(void){
5 int fd;
6 fd=open("fifo",O_RDONLY);
7
8 close(fd);
9 exit(0);
10 }
写进程:以写方式打开,并睡眠 一秒 等待 读进程关闭管道读端
5 void sig_pipe(int signo){
6 printf("get signal:%s\n",strsignal(signo));
7 }
8 int main(void){
9 signal(SIGPIPE,sig_pipe);
10 mkfifo("fifo",0666);
11
12 int fd;
13 fd=open("fifo",O_WRONLY);
14 sleep(1);
15 char c='a';
16 write(fd,&c,1);
17
18 exit(0);
19 }
输出如下:
feng@ubuntu:~/learn_linux_c_second/chapter_10$ ./w &
[1] 8494
feng@ubuntu:~/learn_linux_c_second/chapter_10$ ./r
feng@ubuntu:~/learn_linux_c_second/chapter_10$ get signal:Broken pipe
SIGPROF:
以ITIMER_PROF参数调用的setitimer设置的时间到期时产生此信号:
3 void sig_prof(int signo){
4 printf("get signal:%s\n",strsignal(signo));
5 exit(0);
6 }
7
8 int main(void){
9 signal(SIGPROF,sig_prof);
10
11 struct itimerval val;
12 val.it_interval.tv_sec=0;
13 val.it_interval.tv_usec=0;
14 val.it_value.tv_sec=1;
15 val.it_value.tv_usec=0;
16
17 setitimer(ITIMER_PROF,&val,NULL);
18 while(1);
19 exit(0);
20 }
输出如下
feng@ubuntu:~/learn_linux_c_second/chapter_10$ ./a.out
get signal:Profiling timer expired
SIGQUIT:
当用户在终端按下退出键时,产生此信号,并送至前台进程组中的所有进程。此信号不仅会终止
前台进程组,同时还会产生一个core文件
4 void sig_quit(int signo){
5 printf("\nget signal:%s\n",strsignal(signo));
6 exit(0);
7 }
8 int main(void){
9 signal(SIGQUIT,sig_quit);
while(1);
10 exit(0);
11 }
输出:
feng@ubuntu:~/learn_linux_c_second/chapter_10$ ./a.out
^\
get signal:Quit
SIGSEGV:
该信号只是进程进行了一次无效内存引用
3 void sig_segv(int signo){
4 printf("get signal:%s\n",strsignal(signo));
5 exit(1);
6 }
7 int main(void){
8 signal(SIGSEGV,sig_segv);
9
10 printf("%s",(char *)00100110);
11 exit(0);
12 }
我们 试图 随意访问一个 内存地址
输出如下:
feng@ubuntu:~/learn_linux_c_second/chapter_10$ ./a.out
get signal:Segmentation fault
SIGSTOP:
用于暂停一个进程。他类似于SIGTSTP,但是SIGSTOP信号不能被捕获
3 void sig_stop(int signo){
4 printf("get SIGSTOP\n");
5 }
6
7 int main(void){
8 printf("a\n");
9 kill(getpid(),SIGSTOP);
10 printf("b\n");
11 exit(0);
12 }
我们试图捕获该信号。(若能捕获 应打印get SIGSTOP)
输出如下:
feng@ubuntu:~/learn_linux_c_second/chapter_10$ ./a.out
a
[1]+ Stopped ./a.out
feng@ubuntu:~/learn_linux_c_second/chapter_10$ fg %1
./a.out
b
从输出中我们看到并未捕获到该信号。进程暂停后,我们又让他继续运行才输出 ‘b’
SIGUSR1:
SIGUSR2:
这两个是用户定义的信号。可用于应用程序。比如在程序执行的某处你想临时让程序处理别的事,那么就可以向
他自己发送一个 该信号。然后在信号处理程序中处理需要做的事。
我之前 写过一个关于 父子进程之间的同步处理。就是用这两个信号来实现的http://blog.chinaunix.net/uid-28852942-id-3732251.html
SIGTTIN:
当一个后台进程试图读气控制终端时,终端驱动程序产生此信号。默认是暂停进程,
7 int main(void){
8 char buf[1];
9 read(0,buf,1);
10 printf("Done\n");
11 sleep(1);
12 exit(0);
13 }
如果不处理我们看下输出:
feng@ubuntu:~/learn_linux_c_second/chapter_10$ ./a.out &
[1] 10763
feng@ubuntu:~/learn_linux_c_second/chapter_10$ //按下回车键
[1]+ Stopped ./a.out //进程被暂停了
feng@ubuntu:~/learn_linux_c_second/chapter_10$ fg %1 //恢复运行
./a.out
Done
现在我们捕获该信号
3 void sig_ttin(int signo){
4 printf("get signal:%s\n",strsignal(signo));
5 exit(0);
6 }
7 int main(void){
8 signal(SIGTTIN,sig_ttin);
9 char buf[1];
10 read(0,buf,1);
11 sleep(1);
12 exit(0);
13 }
输出如下:
feng@ubuntu:~/learn_linux_c_second/chapter_10$ ./a.out &
[1] 11009
feng@ubuntu:~/learn_linux_c_second/chapter_10$ get signal:Stopped (tty input)
[1]+ Done ./a.out
SIGTTOU:
当一个后台进程试图读其控制终端时,终端驱动程序产生此信号
3 void sig_ttou(int signo){
4 printf("\nget signal:%s\n",strsignal(signo));
5 exit(0);
6 }
7
8 int main(void){
9 signal(SIGTTOU,sig_ttou);
10
11 write(1,"\nhello\n",7);
12 exit(0);
13 }
默认是允许后台作业输出至终端。这不会产生信号
运行输出:
feng@ubuntu:~/learn_linux_c_second/chapter_10$ ./a.out &
[1] 11158
feng@ubuntu:~/learn_linux_c_second/chapter_10$
hello
[1]+ Done ./a.out
如果我们不允许后台程序输出至终端,则会产生信号:
feng@ubuntu:~/learn_linux_c_second/chapter_10$ ./a.out &
[1] 11355
feng@ubuntu:~/learn_linux_c_second/chapter_10$
get signal:Stopped (tty output)
[1]+ Done ./a.out
SIGXCPU:
如果进程运行超过了其软cpu时间限制,则产生SIGXCPU
4 void sig_xcpu(int signo){
5 printf("get signal:%s\n",strsignal(signo));
6 exit(0);
7 }
8 int main(void){
9 signal(SIGXCPU,sig_xcpu);
10 struct rlimit val;
11 val.rlim_cur=1; //将cpu软时间限制设置为1秒,则1秒后会产生SIGXCPU信号
12
13 setrlimit(RLIMIT_CPU,&val); //设置CPU时间
14 while(1);
15 }
输出如下:
feng@ubuntu:~/learn_linux_c_second/chapter_10$ ./a.out
get signal:CPU time limit exceeded
运行改成序1 秒后我们能看到上面的输出
SIGXFSZ:
如果进程超过了其软文件长度限制,则产生此信号
4 void sig_xfsz(int signo){
5 printf("get signal:%s\n",strsignal(signo));
6 exit(0);
7 }
8
9 int main(void){
10 signal(SIGXFSZ,sig_xfsz);
11 struct rlimit val;
12 val.rlim_cur=0; //将文件大小限制 设置为0
13 setrlimit(RLIMIT_FSIZE,&val);
14 int fd;
15 fd=open("new_file",O_RDWR|O_CREAT|O_TRUNC,0666);
16 write(fd,"aaa",3);
17 fsync(fd);
18 while(1);
19 }
输出如下:
feng@ubuntu:~/learn_linux_c_second/chapter_10$ ./a.out
get signal:File size limit exceeded
当我们写数据到 文件,就会造成超过 文件大小限制,就会产生SIGXFSZ信号。
阅读(945) | 评论(0) | 转发(0) |