Linux下的signal信号机制

分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!http://www.captainbed.net

在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"); 
}

再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!http://www.captainbed.net

原文地址:https://www.cnblogs.com/siwnckhhw/p/10525086.html

时间: 2024-10-30 06:03:42

Linux下的signal信号机制的相关文章

Linux下利用signal函数处理ctrl+c等信号

前言 linux下可以通过信号机制来实现程序的软中断,是一个非常有用的编程方法.我们平时在程序运行的时候按下ctrl-c.ctrl-z或者kill一个进程的时候其实都等效于向这个进程发送了一个特定信号,当进程捕获到信号后,进程会被中断并立即跳转到信号处理函数.默认情况下一个程序对ctrl-c发出的信号(SIGINT)的处理方式是退出进程,所以当我们按下ctrl-c的时候就可以终止一个进程的运行. signal函数 但是有时候我们希望我们的程序在被信号终止之前执行一些特定的收尾流程,或者我们希望我

Linux内核中的信号机制--一个简单的例子【转】

本文转载自:http://blog.csdn.net/ce123_zhouwei/article/details/8562958 Linux内核中的信号机制--一个简单的例子 Author:ce123(http://blog.csdn.NET/ce123) 信号机制是类UNIX系统中的一种重要的进程间通信手段之一.我们经常使用信号来向一个进程发送一个简短的消息.例如:假设我们启动一个进程通过socket读取远程主机发送过来的网络数据包,此时由于网络因素当前主机还没有收到相应的数据,当前进程被设置

linux下的常见信号总结

在linux下有很多信号,按可靠性分为可靠信号和非可靠信号,按时间分为实时信号和非实时信号,linux进程也有三种方式来处理收到的信号: (1)忽略信号,即对信号不做任何处理,其中,有两个信号不能忽略:SIGKILL及SIGSTOP: (2)捕捉信号.定义信号处理函数,当信号发生时,执行相应的处理函数: (3)执行缺省操作,Linux对每种信号都规定了默认操作. Linux进程对实时信号的缺省反应是进程终止.但是对于高性能服务器编程来说,这是致命的缺陷,对于这类服务器需要保证在收到各种信号后仍然

[转]Linux下的常见信号总结

转自 https://www.cnblogs.com/gaorong/p/6430905.html 在linux下有很多信号,按可靠性分为可靠信号和非可靠信号,按时间分为实时信号和非实时信号,linux进程也有三种方式来处理收到的信号: (1)忽略信号,即对信号不做任何处理,其中,有两个信号不能忽略:SIGKILL及SIGSTOP: (2)捕捉信号.定义信号处理函数,当信号发生时,执行相应的处理函数: (3)执行缺省操作,Linux对每种信号都规定了默认操作. Linux进程对实时信号的缺省反应

linux下 signal信号机制的透彻分析与各种实例讲解

转自:http://blog.sina.com.cn/s/blog_636a55070101vs2d.html 转自:http://blog.csdn.net/tiany524/article/details/17048069 首先感谢上述两位博主的详细讲解. 虽然内容有点长,但是分析的很全面,各种实例应用基本都考虑到了. 本文将从以下几个方面来阐述信号: (1)信号的基本知识 (2)信号生命周期与处理过程分析 (3) 基本的信号处理函数 (4) 保护临界区不被中断 (5) 信号的继承与执行 (

linux下select/poll/epoll机制的比较

select.poll.epoll简介 epoll跟select都能提供多路I/O复用的解决方案.在现在的Linux内核里有都能够支持,其中epoll是Linux所特有,而select则应该是POSIX所规定,一般操作系统均有实现 select: select本质上是通过设置或者检查存放fd标志位的数据结构来进行下一步处理.这样所带来的缺点是: 1. 单个进程可监视的fd数量被限制,即能监听端口的大小有限. 一般来说这个数目和系统内存关系很大,具体数目可以cat /proc/sys/fs/fil

Django signal 信号机制的使用

Django中提供了"信号调度",用于在框架执行操作时解耦. 一些动作发生的时候,系统会根据信号定义的函数执行相应的操作 一.Django中内置的 signal 类型主要包含以下几种 1.Model_signals pre_init # Django中的model对象执行其构造方法前,自动触发 post_init # Django中的model对象执行其构造方法后,自动触发 pre_save # Django中的model对象保存前,自动触发 post_save # Django中的m

linux下时钟及时间同步机制

linux有两个时钟:系统时钟和硬件时钟 硬件时钟:hwclock    显示硬件时钟 系统时钟:data只修改系统时间 hwclock --help -s    硬件设为系统 -w    系统设为硬件 ntp:Network Time Protocol ntpdate --help ntpdate 127.0.0.1

Linux信号机制

信号分类 不可靠信号 VS. 可靠信号 Linux信号机制基本上是从UNIX系统中继承过来的.早期UNIX系统中的信号机制比较简单和原始,后来在实践中暴露出一些问题,它的主要问题是: 1.进程每次处理信号后,就将对信号的响应设置为默认动作.在某些情况下,将导致对信号的错误处理:因此,用户如果不希望这样的操作,那么就要在信号处理函数结尾再一次调用signal(),重新安装该信号. 2.早期UNIX下的不可靠信号主要指的是进程可能对信号做出错误的反应以及信号可能丢失. Linux支持不可靠信号,但是