Linux下的signal信号机制
来源:互联网 发布:漫步者音响怎么样 知乎 编辑:程序博客网 时间:2024/05/09 22:56
转载地址:http://blog.csdn.net/sunboy_2050/article/details/6004352#
在Linux中,要发送一个信号相当容易。程序员需要知道两个信息:要发送哪个信号,将这个信号发送给哪个进程。可以用 man 7 signal 找到一个可以利用的信号的列表。用户可以只将信号发送给用户自己的进程,也可以以root身份运行从而将信号发送给任意一进程。
Source:
- #include<stdio.h>
- #include<signal.h>
- #include<unistd.h>
- #include<stdlib.h>
- void when_alarm();
- void when_sigint();
- void when_sigchld(int);
- void when_sigusr1();
- void when_sigio();
- int main()
- {
- int childpid;//子程序进程ID号
- printf("程序已经开始运行,5秒钟后将接收到时钟信号。/n");
- if ((childpid=fork())>0)//父进程
- {
- signal(SIGALRM,when_alarm); //当接收到SIGALRM信号时,调用when_alarm函数
- signal(SIGINT,when_sigint); //当接收到SIGINT信号时,调用when_sigint函数
- signal(SIGCHLD,when_sigchld);//当接收到SIGCHLD信号时,调用when_sigchld函数
- signal(SIGUSR1,when_sigusr1);//当接收到SIGUSR1信号时,调用when_sigusr1函数
- signal(SIGIO,when_sigio);//当接收到SIGIO信号时,调用when_sigio函数
- alarm(5); //5秒钟之后产生SIGALRM信号
- raise(SIGIO); //向自己发送一个SIGIO信号
- pause(); //将父进程暂停下来,等待SIGALRM信号到来
- pause(); //将父进程暂停下来,等待SIGUSR1信号到来
- pause(); //将父进程暂停下来,等待SIGCHLD信号到来
- printf("------此时程序会停下来等待,请按下ctrl+c送出SIGINT信号-------/n");
- pause(); //将父进程暂停下来,等待SIGINT信号到来
- }
- else if(childpid==0) //子进程
- {
- int timer;
- for(timer=7;timer>=0;timer--) //时钟计时5秒产生SIGALRM信号,再过2秒子进程退出,产生SIGCHLD信号
- {
- if(timer>2)
- printf("距离SIGALRM信号到来还有%d秒。/n",timer-2);
- if(timer==4)
- kill(getppid(),SIGUSR1); //向父进程发送一个SIGUSR1信号
- if((timer<=2)&&(timer>0))
- printf("子进程还剩%d秒退出,届时会产生SIGCHLD信号。/n",timer);
- if(timer==0) //子进程退出,产生SIGCHLD信号
- raise(SIGKILL); //子进程给自己发一个结束信号
- sleep(1); //每个循环延时1秒钟
- }
- }
- else
- printf("fork()函数调用出现错误!/n");
- return 0;
- }
- void when_alarm()
- {
- printf("5秒钟时间已到,系统接收到了SIGALRM信号!/n");
- }
- void when_sigint()
- {
- printf("已经接收到了SIGINT信号,程序将退出!/n");
- exit(0);
- }
- void when_sigchld(int SIGCHLD_num)
- {
- printf("收到SIGCHLD信号,表明我的子进程已经中止,SIGCHLD信号的数值是:%d。/n",SIGCHLD_num);
- }
- void when_sigusr1()
- {
- printf("系统接收到了用户自定义信号SIGUSR1。/n");
- }
- void when_sigio()
- {
- printf("系统接收到了SIGIO信号。/n");
- }
Result:
[work@db-testing-com06-vm3.db01.baidu.com c++]$ ./signal_test
程序已经开始运行,5秒钟后将接收到时钟信号。
距离SIGALRM信号到来还有5秒。
系统接收到了SIGIO信号。
距离SIGALRM信号到来还有4秒。
距离SIGALRM信号到来还有3秒。
距离SIGALRM信号到来还有2秒。
系统接收到了用户自定义信号SIGUSR1。
距离SIGALRM信号到来还有1秒。
5秒钟时间已到,系统接收到了SIGALRM信号!
子进程还剩2秒退出,届时会产生SIGCHLD信号。
子进程还剩1秒退出,届时会产生SIGCHLD信号。
收到SIGCHLD信号,表明我的子进程已经中止,SIGCHLD信号的数值是:17。
------此时程序会停下来等待,请按下ctrl+c送出SIGINT信号-------
已经接收到了SIGINT信号,程序将退出!
信号参考对照表:
Signal
Description
SIGABRT
由调用abort函数产生,进程非正常退出
SIGALRM
用alarm函数设置的timer超时或setitimer函数设置的interval timer超时
SIGBUS
某种特定的硬件异常,通常由内存访问引起
SIGCANCEL
由Solaris Thread Library内部使用,通常不会使用
SIGCHLD
进程Terminate或Stop的时候,SIGCHLD会发送给它的父进程。缺省情况下该Signal会被忽略
SIGCONT
当被stop的进程恢复运行的时候,自动发送
SIGEMT
和实现相关的硬件异常
SIGFPE
数学相关的异常,如被0除,浮点溢出,等等
SIGFREEZE
Solaris专用,Hiberate或者Suspended时候发送
SIGHUP
发送给具有Terminal的Controlling Process,当terminal被disconnect时候发送
SIGILL
非法指令异常
SIGINFO
BSD signal。由Status Key产生,通常是CTRL+T。发送给所有Foreground Group的进程
SIGINT
由Interrupt Key产生,通常是CTRL+C或者DELETE。发送给所有ForeGround Group的进程
SIGIO
异步IO事件
SIGIOT
实现相关的硬件异常,一般对应SIGABRT
SIGKILL
无法处理和忽略。中止某个进程
SIGLWP
由Solaris Thread Libray内部使用
SIGPIPE
在reader中止之后写Pipe的时候发送
SIGPOLL
当某个事件发送给Pollable Device的时候发送
SIGPROF
Setitimer指定的Profiling Interval Timer所产生
SIGPWR
和系统相关。和UPS相关。
SIGQUIT
输入Quit Key的时候(CTRL+/)发送给所有Foreground Group的进程
SIGSEGV
非法内存访问
SIGSTKFLT
Linux专用,数学协处理器的栈异常
SIGSTOP
中止进程。无法处理和忽略。
SIGSYS
非法系统调用
SIGTERM
请求中止进程,kill命令缺省发送
SIGTHAW
Solaris专用,从Suspend恢复时候发送
SIGTRAP
实现相关的硬件异常。一般是调试异常
SIGTSTP
Suspend Key,一般是Ctrl+Z。发送给所有Foreground Group的进程
SIGTTIN
当Background Group的进程尝试读取Terminal的时候发送
SIGTTOU
当Background Group的进程尝试写Terminal的时候发送
SIGURG
当out-of-band data接收的时候可能发送
SIGUSR1
用户自定义signal 1
SIGUSR2
用户自定义signal 2
SIGVTALRM
setitimer函数设置的Virtual Interval Timer超时的时候
SIGWAITING
Solaris Thread Library内部实现专用
SIGWINCH
当Terminal的窗口大小改变的时候,发送给Foreground Group的所有进程
SIGXCPU
当CPU时间限制超时的时候
SIGXFSZ
进程超过文件大小限制
SIGXRES
Solaris专用,进程超过资源限制的时候发送
==========================================================================
signal学习推荐:
信号(signal)介绍(Linux中国)
http://www.linux-cn.com/html/linux/system/20070505/27605.shtml
Linux 信号signal处理函数(CSDN)
http://blog.csdn.net/Sunboy_2050/archive/2010/10/16/5945535.aspx
Linux 信号signal处理机制(CSDN)
http://blog.csdn.net/Sunboy_2050/archive/2010/10/16/5945380.aspx
==========================================================================
程序员可以调用 int raise(int signo) 将一个信号发送给它自己。这个函数只带有一个参数,既要发送信号的编号。如:raise(SIGINT); raise(SIGKILL);
让人感兴趣的是函数 unsigned int alarm(unsigned int seconds) 它可以让用户进程在将来某个指定的时间接收到一个信号。alarm()的唯一参数是将来信号SIGALRM应该在多少秒以后发送给用户进程。当用户调用alarm()时,前面任何一个请求的报警信号(不包括悬挂起来被阻塞的SIGALRM信号)都将被取消,调用的返回值是前面请求的剩余时间。alarm()范例如下:
if(signal(SIGALRM,alarmhandler)==SIG_ERR)
{
printf("Couldn't register signal handler./n");
}
alarm(5); // 5秒钟以后,程序将会收到一个SIGALRM信号
for(i=0;i<10;i++)
{
sleep(3);
}
void alarmhandler(int signum)
{
printf("alarmhandler./n");
}
也可以使用 int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue) 来实现更精确更方便的定时控制。
参数which一般取ITIMER_REAL,它使得用户的计时器根据系统时钟来计算时间。当计数时间到期时,它将发送一个SIGALRM信号。其功能和alarm()一样,所以用户不能将两者同时使用。
结构itimerval的定义如下:
struct itimerval
{
struct timeval it_interval; // 每一次触发报警后应该被复位的值,为0报警被禁止
struct timeval it_value; // 下一次触发报警的时间,为0报警将只触发一次
};
结构timeval的定义如下:
strut timeval
{
long tv_sec; // 秒数
long tv_usec; // 微秒数
};
setitimer()范例如下:
struct itimerval itimer;
itimer.it_interval.tv_usec = 0; // it_interval字段指定了每一次触发后应该被复位的值
itimer.it_interval.tv_sec = 2;
itimer.it_value.tv_usec = 0; // it_value字段指定了直到下一次触发的时间
itimer.it_value.tv_sec = 5;
setitimer(ITIMER_REAL,&itimer,NULL);
for(i=0;i<10;i++)
{
sleep(3);
}
void alarmhandler(int signum)
{
printf("alarmhandler./n");
}
- Linux下的signal信号机制
- Linux下的signal信号机制
- Linux下的signal信号机制
- Linux下的signal信号机制
- linux下的信号机制(signal)
- Linux下的signal信号机制
- Linux下的signal信号机制
- linux信号机制signal
- Linux Signal 信号机制
- Linux下Signal信号
- Linux下Signal信号
- Linux下Signal信号
- Linux下Signal信号
- Linux下Signal信号
- Linux下信号signal
- Linux下Signal信号
- Linux下Signal信号
- Linux下的信号(signal)
- 使用log4j按包名输出日志
- asp mvc3 发送email
- 用Redis实现分布式锁
- linux windows socket通信
- 2012科技业大公司与大事件:苹果不再创新垄断(转)(一)
- Linux下的signal信号机制
- IOS之输入法隐藏
- 宏中"#"和"##"的用法
- 设计模式之--迭代器与组合模式
- ubuntu建立samba服务器
- 2012科技业大公司与大事件:苹果不再创新垄断(转)(二)
- android APK反编译入门
- 用hibernate查询一个空表时,返回的List很奇怪
- 2012科技业大公司与大事件:苹果不再创新垄断(转)(三)