Chinaunix首页 | 论坛 | 博客
  • 博客访问: 23270
  • 博文数量: 11
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 18
  • 用 户 组: 普通用户
  • 注册时间: 2013-05-31 22:46
文章分类
文章存档

2013年(11)

我的朋友

分类: LINUX

2013-06-07 00:53:29

原文地址:linux下20种信号实例说明 作者:ifndef



为了节省篇幅所有测试都忽略错误检查



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信号。

阅读(961) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~