Linux下的signal信号机制

在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

进程TerminateStop的时候,SIGCHLD会发送给它的父进程。缺省情况下该Signal会被忽略

SIGCONT

当被stop的进程恢复运行的时候,自动发送

SIGEMT

和实现相关的硬件异常

SIGFPE

数学相关的异常,如被0除,浮点溢出,等等

SIGFREEZE

Solaris专用,Hiberate或者Suspended时候发送

SIGHUP

发送给具有TerminalControlling Process,当terminaldisconnect时候发送

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.mzph.cn/news/405806.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

React开发(200):三种截取字符串的方法

JS提供三个截取字符串的方法,分别是:slice(),substring()和substr(),它们都可以接受一个或两个参数: var stmp "rcinn.cn"; 使用一个参数 alert(stmp.slice(3));//从第4个字符开始,截取到最后个字符;返回"nn.cn" alert(stmp.substring(3));//从第4个字…

oracle scn与数据恢复,[Oracle] SCN与数据恢复的关系

Oracle内部主要存在以下四种SCN1.系统检查点(system checkpoint)SCN每当一个检查点完成时&#xff0c;Oracle就把该检查点对应的SCN记录到控制文件中&#xff0c;可以用以下语句查看当前数据库的检查点SCN&#xff1a;select CHECKPOINT_CHANGE# from v$database;CHECKPOINT_CH…

js Date 生成某年某月的天数

$(function () {//构造一个日期对象&#xff1a;var day new Date(2014, 2, 0);//获取天数&#xff1a;var daycount day.getDate();alert(daycount);}) 省去了判断 闰年平年 转载于:https://www.cnblogs.com/dragon-L/p/4522144.html

romfs, cramfs和ramdisk

From:http://blog.csdn.net/at91rm9200/article/details/550074 文章来源 &#xff08;http://publishblog.blogchina.com/blog/tb.b?diaryID3226065&#xff09; cramfs和romfs只是一个文件系统类型&#xff0c;ramdisk相当于一块硬盘空间&#xff0c;可以理解为在内存中虚拟…

Qt中利用QProcess调用外部cmd.exe执行程序

1、#include "mainwindow.h"中 添加头文件&#xff1a; #include <QProcess> 添加成员&#xff1a; QProcess *myprocess; 添加槽函数声明&#xff1a; void showCMDResult(); void showCMDState(QProcess::ProcessState state); void showCMDError(); vo…

html 后# 号的作用,及html 如何传参

2019独角兽企业重金招聘Python工程师标准>>> 经常在 网上看到一些静态网页后加着 #XXX 如http://www.family168.com/tutorial/springsecurity3/html/introduction.html#spring-security-core 这种形式。这个#spring-security-core 起的作用就是在 introduction 中定…

oracle10g生成awr报告,awr报告生成位置.docx

awr报告生成位置/u01/app/oracle/product//dbhome_1/rdbms/admin/脚本生成awr报告  在SQL环境执行&#xff1a;SQL>/u01/app/oracle/product//dbhome_1/rdbms/admin/  输入报告类型&#xff1a;html或text  输入要生成报告的天数&#xff0c;缺省是7天  列出最近7天…

Codeforces Round #304 (Div. 2)

这次打得较差&#xff0c;差点就绿了。。。 B题&#xff0c;这B题竟然WA了&#xff0c;再看看就发现一个很严重的错误。。--! #include <iostream> #include <cstdio> #include <algorithm> #include <cstring>using namespace std;int num[3050];int …

Qt 设置应用程序开机自启动

要实现开机自启动&#xff0c;主要是将应用程序添加到注册表中。 一、首先定义注册表 #define AUTO_RUN "HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Run" 二、编写开机自启动设置函数 //开机自启动&#xff0c;采用QSetting的方式将其写…

MySQL浅谈 LEFT JOIN

On条件&#xff08;在“A left join b on conditional_expr”&#xff09;决定如何从table B 中检索数据行&#xff08;Matching-State&#xff09;; 如果&#xff22;中没有行匹配On 条件&#xff0c;额外的B的所有数据列被设为null; 如果Matching-Stage阶段,where语句的任…

oracle cdc 关闭,Oracle CDC部署流程

一、ORACLE环境检查查oracle数据库版本(>9.2.0.4.0).select * from v$version;BANNEROracle Database 10g Enterprise Edition Release 10.2.0.1.0 - ProdPL/SQL Release 10.2.0.1.0 - ProductionCORE 10.2.0.1.0 ProductionTNS for 32-bit Windows: Version …

几个重要的RedHat Linux内核文件介绍 (1)

From:http://tech.sina.com.cn/s/s/2006-06-27/061923370.shtml Linux服务器内核编译基础 mynix编译自www.linux.org之Linux HowTo之Kernel HowTo 在网络中&#xff0c;不少服务器采用的是Linux系统。为了进一步提高服务器的性能&#xff0c;可能需要根据特定的硬件及需求重新…

Qt 两个Ui 界面传值

一、说明 A子界面 B主界面 &#xff0c; 实现A往B传值&#xff0c;B显示. 二、利用emit和slot实现 2.1 对A.h 添加声明 signals: void sendData(QString); //用来传递数据的信号 2.2在A.cpp中适当位置将数据进行发射 emit sendData(ui->lineEdit->text());…

有哪些是你成为一名开发之后才知道的事情

目录 前言 疑问1成为一名开发真的很难嘛&#xff1f; 疑问2作为一名开发的工资一定很高吗 疑问3开发一定加班会很厉害嘛 疑问4一定要去大厂嘛 疑问5程序员是个很好的职业选择吗 疑问6毕业前参加培训好吗 疑问7入行之后要不断提升自己的能力吗 疑问8大学四年该如何度过 疑问…

她们分别买了什么?

using System; using System.Collections.Generic; using System.Text; class Program { static void Main(string[] args) { /* * 测试 9&#xff0e;她们分别买了什么? */ WhatWasBought(); …

[发布] 矩阵乘法及其对于编程求斐波那契数列的某一项的应用

需要PDF的读者可以向我索要。 如果发现有翻印与用于商业用途&#xff0c;将予追究。 编者注&#xff1a;本文中如果没有特殊说明&#xff0c;除法均只取整数部分&#xff0c;忽略小数部分。 感谢大家对我的支持&#xff01;同时感谢ysy大聚聚。转载于:https://www.cnblogs.com…

oracle新建用户sql局域,oracle 新建数据库,及创建用户,表空间,sqlplus导入导出数据库...

oracle11G新建数据库&#xff1a;默认下一步&#xff1a;默认下一步&#xff1a;默认下一步&#xff1a;填写数据库名下一步&#xff1a;默认下一步&#xff1a;完成&#xff0c;再按指示确定&#xff0c;就完成了数据库的创建。数据库创建完后&#xff0c;在oracle11G Net Man…

QIcon 给按钮和动作添加图片

对Qt中资源文件的引用时&#xff0c;QAction/QPushbutton添加图标时&#xff0c;需要用到图片的路径。 1、先添加资源文件&#xff0c;项目->添加新的文件->Qt resource files->添加前缀->添加文件。 2、复制需要文件的路径&#xff1b;&#xff08;工程树对应图…