您的位置:首页 > 运维架构 > Linux

[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指定的信号后应该采取的动作;


                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: