Linux信号_总结

对信号本质的理解:

类似于中断,区别在于中断是由硬件产生的,而信号是由软件实现的。

信号的来源:

触发硬件(触发键盘,或是硬件故障);软件信号函数kill 、alarm、setitimer、sigqueue 等函数。

信号的分类:

可靠信号与不可靠信号,实时信号与非实时信号;

不可靠信号:

SIGRTMIN前的信号称为不可靠信号,在早期这段信号可能做出错误的反应,或是丢失。因此对此段信号成为不可靠信号。

可靠信号:

在SIGRTMIN与SIGRTMAX之间的信号称做可靠信号,可靠信号是为了防止信号丢失的。这些信号可以排队处理。

实时信号与非实时信号:

非实时信号都不支持排队,都是不可靠信号;实时信号都是支持排队的,都是可靠信号;

对信号的响应:

响应的三种方式

(1)忽略信号

有两个特殊的信号SIGKILL 和SIGSTOP信号不能被忽略。

(2)捕捉信号

给对应的信号绑定响应的处理函数,带到信号产生时,执行对应的函数。

(3)执行缺省信号

进程对实时信号的缺省反应时进程的终止。

信号的发送:

发送信号的函数有,kill(), alarm(),raise(),setitimer();

(1)kill(int pid, int signal);

PID参数 信号的就收进程
pid>0 进程的ID为pid的进程
pid=0 同一个进程组
pid<0 && pid!=-1 进程组ID为pid绝对值的所有进程
pid=-1 发送至所有ID大于1的进程

参数介绍:

pid为进程号,singnal为信号值。

kill常用于pid>0的信号处理,调用成功返回0,否则返回-1。

(2)alarm(unsigned int seconds)

专门为SIGALRM信号而设函数,seconds表示时间,此函数意味着在seconds秒后向SIGALRM信号发送消息。

进程调用alarm后,以前的alarm()调用都将无效。若调用alarm()前,进程中已经设置了闹钟,则返回上一个闹钟生于的时间,否则返回0;

eg:

#include<signal.h>
#include<stdio.h>
int main(void)
{
printf("first time return:%d\n",alarm(4));
sleep(1);
printf("after sleep(1),remain:%d\n",alarm(2));
printf("renew alarm,remain:%d\n",alarm(1));
}

//运行结果为
first time return:0
after sleep(1),remain:3
renew alarm,remain:2

(3)raise(int signal);

此函数时向本进程发送signal信号的,signal为即将发送的信号值。调用成功返回0;否则返回 -1。

(4)setitimer()函数

int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue));

结构体介绍:

struct itimerval 
{
 struct timeval it_interval;//间隔时间
 struct timeval it_value; //初始时间
 };  

struct timeval
{
   long tv_sec; //秒
   long tv_usec; //微妙
};            

参数描述:

which:表示定时器类型,setitimer有三种定时器类型。

ITIMER_REAL : 以系统真实的时间来计算,它送出SIGALRM信号。  

ITIMER_VIRTUAL : 设定程序执行时间;经过指定的时间后,内核将发送SIGVTALRM信号给本进程;

ITIMER_PROF : 设定进程执行以及内核因本进程而消耗的时间和,经过指定的时间后,内核将发送ITIMER_VIRTUAL信号给本进程;

it_interval指定间隔时间,it_value指定初始定时时间。如果只指定it_value,就是实现一次定时;如果同时指定 it_interval,则超时后,系统会重新初始化it_value为it_interval,实现重复定时;

eg:

#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/time.h>

void sigroutine(int signo) {
       switch (signo) {
               case SIGALRM:
                       printf("Catch a signal -- SIGALRM\n");
                       break;
               case SIGVTALRM:
                       printf("Catch a signal -- SIGVTALRM\n");
                       break;
      }
}

int main(int argc, char ** argv) {
       struct itimerval value,ovalue,value2;

       printf("process id is %d\n",getpid());
       signal(SIGALRM, sigroutine); //为SIGALRM信号绑定sigroutine函数
       signal(SIGVTALRM, sigroutine); //为SIGVTALRM信号绑定sigroutine函数

       value.it_value.tv_sec = 1;//设定起始时间
       value.it_value.tv_usec = 0;
       value.it_interval.tv_sec = 1;//设定终止时间
       value.it_interval.tv_usec = 0;
       setitimer(ITIMER_REAL, &value, &ovalue);

       value2.it_value.tv_sec = 0;
       value2.it_value.tv_usec = 500000;
       value2.it_interval.tv_sec = 0;
       value2.it_interval.tv_usec = 500000;
       setitimer(ITIMER_VIRTUAL, &value2, &ovalue);

       for (;;) ;
}

//运行结果为
process id is 3136
Catch a signal -- SIGVTALRM
Catch a signal -- SIGALRM
Catch a signal -- SIGVTALRM
Catch a signal -- SIGVTALRM
Catch a signal -- SIGALRM
Catch a signal -- SIGVTALRM
Catch a signal -- SIGVTALRM
Catch a signal -- SIGALRM
Catch a signal -- SIGVTALRM
Catch a signal -- SIGVTALRM
Catch a signal -- SIGALRM
Catch a signal -- SIGVTALRM
Catch a signal -- SIGVTALRM
Catch a signal -- SIGALRM
Catch a signal -- SIGVTALRM
Catch a signal -- SIGVTALRM
Catch a signal -- SIGALRM
Catch a signal -- SIGVTALRM
Catch a signal -- SIGVTALRM

安装信号:

由signal()、sigaction()处理:

(1)signal(int signum, sighandler_t handler);

此函数的作用是,为handler函数,或处理过程绑定一个信号,每当出现信号后,进行handler处理。

signum:所指信号;

handler:处理过程,可以时函数的指针。这个也可设置为"SIG_IGN",表示忽略此信号,"SIG_DFL"表示以系统默认方式处理此信号。(注意:SIGKILL SIGSTOP不可被安装)

此函数的例子可参考上一个例子。

(2)sigaction();

int sigaction(int signum,const struct sigaction *act,struct sigaction *oldact));

signum:指定的信号(除SIGKILL,SIGSTOP外)

sigaction:指向结构指针,指定对特定信号的处理

oldact:指向的对象用来保存原来对相应信号的处理

sigaction()函数中第二个参数最为关键。

sigaction结构体如下:

struct sigaction 
{
      void     (*sa_handler)(int);
      void     (*sa_sigaction)(int, siginfo_t *, void *);
      sigset_t   sa_mask;
      int        sa_flags;  //会影响信号接受特殊标志
      void     (*sa_restorer)(void);
  };

(1)结构体中的sa_restorer已经不使用可以忽略。

(2)sa_handler指定的处理函数只有一个参数类似于使用signal()函数

(3)sa_sigaction也是指定信号的处理函数,不过可以带三个参数:

第一个参数为信号值;

第二个参数是指向siginfo_t结构的指针;

第三个参数没有使用;

siginfo_t结构体如下:

siginfo_t 
{
  int      si_signo;    /* Signal number */
  int      si_errno;    /* An errno value */
  int      si_code;     /* Signal code */
  int      si_trapno;   /* Trap number that caused
                           hardware-generated signal
                           (unused on most architectures) */
  pid_t    si_pid;      /* Sending process ID */
  uid_t    si_uid;      /* Real user ID of sending process */
  int      si_status;   /* Exit value or signal */
  clock_t  si_utime;    /* User time consumed */
  clock_t  si_stime;    /* System time consumed */
  sigval_t si_value;    /* Signal value */
  int      si_int;      /* POSIX.1b signal */
  void    *si_ptr;      /* POSIX.1b signal */
  int      si_overrun;  /* Timer overrun count; POSIX.1b timers */
  int      si_timerid;  /* Timer ID; POSIX.1b timers */
  void    *si_addr;     /* Memory location which caused fault */
  long     si_band;     /* Band event (was int in
                           glibc 2.3.2 and earlier) */
  int      si_fd;       /* File descriptor */
  short    si_addr_lsb; /* Least significant bit of address
                           (since Linux 2.6.32) */
};

(4)sa_mask指定在信号处理程序执行过程中,哪些信号应当被阻塞。缺省情况下当前信号本身被阻塞,防止信号的嵌套发送,除非指定SA_NODEFER或者SA_NOMASK标志位。

注:请注意sa_mask指定的信号阻塞的前提条件,是在由sigaction()安装信号的处理函数执行过程中由sa_mask指定的信号才被阻塞。

(5)sa_flags标志位:

当sa_flags设置为SA_SIGINFO时,示信号附带的参数可以传递到信号处理函数中。即使sa_sigaction指定信号处理函数,如果不设置SA_SIGINFO,信号处理函数同样不能得到信号传递过来的数据,在信号处理函数中对这些信息的访问都将导致段错误。

信号,介绍先到此,如若觉得又不对的地方,请指出,共同进步谢谢!

参考博客有:

https://www.ibm.com/developerworks/cn/linux/l-ipc/part2/index1.html

http://www.cnblogs.com/dandingyy/articles/2653218.html

Linux 对信号的总结的更多相关文章

  1. linux kill信号列表

    linux kill信号列表 $ kill -l1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL5) SIGTRAP      6) ...

  2. Linux进程间通信——信号集函数

    一.什么是信号 用过Windows的我们都知道,当我们无法正常结束一个程序时,可以用任务管理器强制结束这个进程,但这其实是怎么实现的呢?同样的功能在Linux上是通过生成信号和捕获信号来实现的,运行中 ...

  3. linux 自定义信号

    从来没试过linux自定义信号,查了下,说是系统只提供了SIGUSR1和SIGUSR2两个,就两个够吗?更要命的是如果要自定义信号如#define SIG_MYSIG   ....的话要改内核才行,哥 ...

  4. Linux 的信号和线程

    什么是线程 线程,有时被称为轻量级进程(Lightweight Process,LWP),是程序执行流的最小单元.一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成,每一个程序都至少 ...

  5. Linux之信号

    产生信号五种方法: 按键产生:ctrl+c.ctrl+z.ctrl+\ 系统调用产生:如kill.raise.baort 软件条件产生:如定时器alarm 硬件异常产生:非法访问内存(段错误).除0( ...

  6. Linux&C ——信号以及信号处理

    linux信号的简单介绍 信号的捕捉和处理 信号处理函数的返回 信号的发送 信号的屏蔽 一:linux信号的简单介绍. 信号提供给我们一种异步处理事件的方法,由于进程之间彼此的地址空间是独立的,所以进 ...

  7. Linux&C ——信号以及信号处理

    linux信号的简单介绍 信号的捕捉和处理 信号处理函数的返回 信号的发送 信号的屏蔽 一:linux信号的简单介绍. 信号提供给我们一种异步处理事件的方法,由于进程之间彼此的地址空间是独立的,所以进 ...

  8. linux有关信号的FAQ

    1.为什么会出现系统调用被中断的情况? 进程在执行一个低速系统调用而阻塞期间捕捉到一个信号时,该系统调用就被中断不再继续执行.该系统调用返回出错,其errno被设置为EINTR.这样处理的理由是:因为 ...

  9. Linux 发送信号

    使用kill命令 --在命令行执行kill命令.向指定进程发送信号. 使用kill函数 int kill(pid_t pid,int sig); --参数pid指定一个要杀死的进程,而sig是要发送的 ...

  10. Linux进程间通信-信号

    1.什么是信号信号是Linux系统响应某些条件而产生的一个事件,接收到该信号的进程会执行相应的操作. 2.信号的产生1)由硬件产生,如从键盘输入Ctrl+C可以终止当前进程2)由其他进程发送,如可在s ...

随机推荐

  1. Java tomcat Several ports (8005, 8080, 8009) required by Tomcat v9.0 Server at localhost

    关于 下面问题是因为(8005, 8080, 8009) 被原tomcat占用了. Several ports (8005, 8080, 8009) required by Tomcat v9.0 S ...

  2. 《深度探索C++对象模型》读书笔记(二)

    第三章:Data语意学 这一章主要讲了类中的数据在内存中是如何分配的,包括(多重)继承和多态. 让我们首先从一段代码开始: class X{}; class Y :virtual public X{} ...

  3. RIDE创建工程和测试套件和用例--书本介绍的入门方法,自己整理实践下

    1.选择File->New Project 2.弹出的New Project对话框,在Name文本框输入一个名词,如“TestProject-0805”,右侧选中“Directory”,选中建立 ...

  4. sqlserver查找使用了某个字段的所有存储过程

    当一个系统中使用了很多的表,并且存在大量的存储过程,当数据库中的某个表删除了某个字段,那么相应的存储过程也需要改动,但是我们不知道哪些存储过程使用了该字段,那我们该怎么办?我们可以从之前的文档一个一个 ...

  5. windows 服务的安装与卸载之bat脚本命令

    在windows 平台下,服务的安装与卸载可通过bat 脚本命令来完成,同时可编辑服务的描述,具体代码如下: 1.服务的安装DynamicPlanService_installer.bat: @ech ...

  6. 解决TensorFlow程序无限制占用GPU

    今天遇到一个奇怪的现象,使用tensorflow-gpu的时候,出现内存超额~~如果我训练什么大型数据也就算了,关键我就写了一个y=W*x.......显示如下图所示: 程序如下: import te ...

  7. 四、Python-元组

    列表非常适合用于存储在程序运行期间可能变化的数据集.列表是可以修改的,这对处理网 站的用户列表或游戏中的角色列表至关重要. Python将不能修改的值称为不可变的,而不可变的列表被称为元组 一.元组( ...

  8. 解决uni-app props 传递数组修改后不能使用问题

    1.子组件页面结构 //NoticesMarquee 组件 <view v-for="(item, index) in tempList" :key="index& ...

  9. Java Design Patterr

    Factory: ●简介: 工厂模式同单例模式一样,也是Java中最常用的设计模式之一,属于创建型模式,它提供了一种创建对象的最佳方式.能够根据要求调用者提供的信息为接口指定不同的实现类,降低耦合. ...

  10. nodeJs 控制台打印中文显示为Unicode解决方案

    在使用 NodeJs 采集其他网站网页时遇到的,在获取源代码后发现里面原来的中文被转成了 Unicode(UTF8) 编码的中文(如:&# [xxx]),这当然不是真正想要的中文实体 解决方案 ...