[linux basic]基础--信号
2016-03-26 12:08
288 查看
线程-》信号 信号,是unix和linux系统响应某些条件而产生的一个事件。接收到该信号的进程会相应地采取一些行动。 raise生成表示一个信号的产生 catch捕获表示接受到一个信号的产生;信号是由于某些错误条件而产生,内存段冲突,浮点处理器错误或者非法指令等。它们由shell和终端处理器生成 引起中断,可以作为进程见传递消息或修改行为的一种方式,明确地由一个进程发送给另一个进程。无论什么情况,它们的编程接口都是相同的,信号可以被 生成,捕获,响应,忽略。 signal.h====== sigabort*进程异常终止 sigalrm超时警告 sigfpe*浮点运算错误 sighup链接挂断 sigill*非法指令 sigint终端中断 sigkill终止进程(此信号不能被不或忽略) sigpipe向无读进程的管道写数据 sigquit中断退出 sigsegv*无效内存段访问 sigterm终止 siguser1用户定义信号 siguser2用户定义信号2 注意:*表示系统对信号的响应随具体实现而定 -----------》如果进程接受到这些信号中的一个,但事先没有安排不或他,进程将会立刻终止。通常系统会生产核心转储文件core,并将其放在当前 目录下。该文件是进程自爱内存中的印象,他对程序的调试很有帮助。 其他信号 sigchld子进程已经停止或退出 sigcont继续执行暂停进程 sigstop停止执行(此信号不能被捕获或忽略) sigstsp终端挂起 sigttin后台进程尝试读操作 sigttou后台进程尝试写操作 如果shell和终端驱动程序是按通常情况配置的话,在键盘上敲入中断字符(Ctrl+C)就会向前台(即当前正在执行的程序)发生sigint信号,这将引起该 进程的终止,除非它事先安排了捕获这个信号。 如果想发送一个命令给进程,但该进程不是当前的前台进程,就需要使用kill命令,该命令需要 一个可选的信号代码或信号名称和 一个接受信号的目标进程的PID(pid一般需要ps命令查看) kill--发送一个命令给一个进程,常用的信号包括HUP,INT,KILL,STOP,CONT,0. 程序可以使用signal库函数来处理信号, #include<signal.h> void(*signal(intsig,void(*func)(int)))(int); signal是一个带有sig和func两个参数的函数; 准备捕获/忽略的信号有参数sig给出,接受到指定的信号后将要调用的函数由参数func给出, 信号处理函数必须有一个int类型的参数(即接收到的信号代码)并且返回类型为void, signal函数本身也返回一个同类型的函数,即先前用来处理这个信号的函数(不是func函数); 返回的是先前对指定信号进行处理的信号处理函数的函数指针,如果未定义信号处理函数,则返回SIG_ERR,并设置errno为一个正整数值, 如果给出的是一个无效的信号,或者尝试处理的信号不可捕获/不可忽略(如SIGKILL),errno将被设置为EINVAL。 也可以使用特殊值(sig_ign,sig_dfl)来代替信号处理函数; sig_ign忽略信号 sig_dfl恢复默认信号 ----------------------- 信号处理例子:编写一个程序ctrlc.c,来响应用户敲入的Ctrl+c组合键,在屏幕上打印一条适当的消息而不是终止程序的运行;再次ctrl+c时,结束。
#include<signal.h> #include<stdio.h> #include<unistd.h> voidouch(intsig) { printf("ouch!-Igotsignal%d\n",sig); (void)signal(SIGINT,SIG_DFL); } intmain(){ (void)signal(SIGINT,ouch); while(1){ printf("helloworld\n"); sleep(1); } }
main()的作用是捕获ctrl+c产生的SIGINT信号,没有信号产生时,它会在一个无限循环中打印字符; (void)signal(SIGINT,ouch),在捕获SIGINT信号后,会调用ouch函数进行处理; (void)signal(SIGINT,SIG_DFL),再次捕获SIGINT信号,SIG_DFL来恢复信号的默认行为; ------------ 发送信号 进程可以通过调用kill函数将包括它在内的其他进程发送一个信号,如果程序没有发送该信号的权限,对kill函数的调用就会失败; 失败的常见原因,是目标进程由另一个用户所拥有; #include<sys/types.h> #include<signal.h> intkill(pid_tpid,intsig); kill函数吧参数sig给定的信号发送给参数pid给出的进程号所指定的进程,成功时它返回0; kill调用失败返回-1并设置errno变量, 失败原因: 给定的信号无效errno=EINVAL 发送权限不够errno=EPERM 目标进程不存在errno=ESRCH -- 信号的闹钟功能,进程可以通过调用alarm()在经过预定时间后发送一个sigalrm信号, #include<unistd.h> unsignedintalarm(unsignedintseconds);
/************************************************************************* >FileName:alarm.c >Author: >Mail: >CreatedTime:2016年03月26日星期六12时30分10秒 ************************************************************************/ #include<stdio.h> #include<sys/types.h> #include<signal.h> #include<unistd.h> #include<stdlib.h> staticintalarm_fired=0; voidding(intsig){ alarm_fired=1; } intmain(){ pid_tpid; printf("alarmapplicationstarting\n"); pid=fork(); switch(pid){ case-1: //failure perror("forkfailed"); exit(1); case0: //child printf("Itisachildprocess,anditwillsleep5s\n"); printf("childprocessPid=%d\n",getpid()); sleep(5); printf("5shaspast,childprocesswillgenerateasigalrm\n"); kill(getppid(),SIGALRM); printf("childprocesshasgeneratedasigalrmsignal\n"); exit(0); } //ifwegethere,wearetheparentprocess printf("itisaparentprocess,itpId=%d\n",getpid()); printf("waitingforalarmtogooff\n"); (void)signal(SIGALRM,ding); pause(); if(alarm_fired) printf("Ding!\n"); printf("done\n"); exit(0); }
执行结果:
lizhen@lizhen:~/basic$./a.out alarmapplicationstarting itisaparentprocess,itpId=3908 waitingforalarmtogooff Itisachildprocess,anditwillsleep5s childprocessPid=3909 5shaspast,childprocesswillgenerateasigalrm childprocesshasgeneratedasigalrmsignal Ding! done
---
getpid,getppid--getprocessidentification
#include<sys/types.h>
#include<unistd.h>pid_tgetpid(void)
pid_tgetppid(void)
getpid()returntheprocessIDofthecallingprocess(thisisoftenusedbyroutines
thatgenerateuniquetemporayfilenames.)
getppid()returnstheprocessIDoftheparentofthecallingprocess.
----
pause-waitforsignal
#include<unstd.h>
intpause(void)
pause()causesthecallingprocess(orthread)tosleepuntilasignal
isdeliveredthateitherterminatestheprocessorcausestheinvocationofasignal-catching
function.就是程序的执行挂起直到有一个信号出现为止,当程序接受到一个信号时,预设好的信号处理函数将开始运行,程序也恢复
正常的执行。当它被一个信号中断是,将返回-1(如果下一个接受到的信号没有导致程序终止的话)并把errno设为EINTR,
当需要等待信号时,一个更常见的做法就是使用sigsuspend函数;===
使用信号并挂起程序的执行是linux程序设计的一个重要部分,意味着程序不需要总是在执行着;
程序不必在一个循环中无休止地检查某个事件是否已发生,他可以等待事件的发生。
这在只有一个cpu的多用户环境中很重要;
进程共享着一个cpu,繁忙的等待将会对系统的性能造成很大的影响。
一个特殊的问题,“如果信号出现在系统调用的执行过程中会发生什么情况?”
在编写程序中处理信号部分的代码时,应该非常小心,因为在使用信号的程序中会出现各种“竞态条件“,
例如,想调用pause等待一个信号,可信号却出现在调用pause之前,就会使程序无限期地等待一个不会发生的时间。
这些竞态条件都是一些对时间要求很苛刻的问题,所以在检查和信号相关的代码时总会非常小心;---
一个健壮的信号接口
sigaction
#include<signal.h>
intsigaction(intsig,conststructsigaction*act,structsigaction*oact);
sigaction结构定义在文件signal.h中,作用是定义接受到sig指定的信号后应该采取的动作;
相关文章推荐
- linux嵌入式qt的屏幕旋转与字体大小问题
- Linux操作系统 sleep(0)、sleep(1)和sleep(-1)的区别,他们各有什么作用
- linux挂载的磁盘类型
- win32平台而非linux平台下 深入分析Sleep(0)与Sleep(1)的区别
- ubuntu 交叉编译arm linux 内核小例子
- 交叉编译工具链介绍《Building Embedded Linux Systems》
- Linux并发(易混淆的基本API)
- Centos版Linux 一些常用操作命令
- linux内核用户地址空间分配与管理
- Linux下环境变量的设置
- Linux telnet简单实用方法
- Linux telnet简单实用方法
- 在Linux下安装python package到指定目录
- linux源码Makefile的详细分析
- linux 允许 icmp
- 虚拟机VMware自定义安装Linux redhat 之企业版CentOS
- [Linux]获取域名的ip地址和hostname(待续)
- Java开发必会的Linux命令
- Linux下查看用户列表
- linux的root登录password问题