1 信号传递过程

当引发信号的事件发生时(如软硬件异常、软件定时、终端产生信号或调用kill函数等等),会产生信号,内核会发送给目标进程。

在信号产生到信号传递给目标进程之间的时间间隔内,称该信号为未决的(pending)。

进程可以对信号进行阻塞操作。若进程选择了对一个信号进行阻塞,并且对该信号的动作为默认或捕捉该信号。此时进程仍然对信号保持未决状态,直到进程解除了阻塞或将信号动作改为忽略。

如果在进程解除对信号的阻塞之前,该信号发生了多次,那么内核一般会对这些信号进行排队。

每个进程都有一个信号屏蔽字(signal mask),它规定了当前要阻塞传递给该进程的信号集。对于每种可能的信号,信号屏蔽字中都有一位与之对应。

如下图所示过程:

  1. 如果目标进程设置了忽略该信号,则内核直接将该信号丢弃
  2. 如果目标进程没有阻塞该信号,则内核将该信号传递给目标进程进行相应操作。
  3. 如果目标进程设置阻塞该信号,则内核将该信号放到目标进程的阻塞信号列表中,等待它的下一步设置。若目标进程后续设置忽略该信号,则内核将该信号从目标进程的阻塞信号列表中移除并丢弃。若目标进程对该信号解除了阻塞,内核将该信号传递给目标进程进行相对应的操作。

2 基本信号操作

#include <signal.h>
int kill(pid_t pid, int signo);
int raise(int signo);
/*返回值:若成功返回0,出错返回-1*/

kill函数将信号发送给进程或进程组,raise函数则允许进程向自身发送信号。调用raise(signo)等价于kill(getpid(), signo);

#include <unistd.h>
unsigned int alarm(unsigned int seconds);
/*返回值:0或以前设置的闹钟剩余秒数*/
int pause(void);
/*返回值-1,并将errno设置为EINTR*/

使用alarm函数设置一个定时器,当定时器超时后会产生SIGALRM信号。如果进程不捕捉或不忽略该信号,默认动作是终止进程。

只能设置一个时钟,如果之前已经有了闹钟就会替代它,并且返回旧闹钟剩余的秒数。用alarm(0)可以清除闹钟。

pause函数使调用进程挂起,直到捕捉到一个信号。只有执行了一个信号处理程序并从其返回时,pause函数才返回。

3 信号集及其操作

信号集(signal set)是一种能表示多个信号的数据类型,POSIX.1 定义了一个数据类型sigset_t,用于表示信号集。另外,头文件 signal.h 提供了下列五个处理信号集的函数。

/*初始化由set指向的信号集,清除其中所有信号*/
int sigemptyset(sigset_t *set); /*初始化由set指向的信号集,使其包含所有信号*/
int sigfillset(sigset_t *set); /*将一个信号signo添加到现有信号集set中*/
int sigaddset(sigset_t *set, int signo); /*将一个信号signo从信号集set中删除*/
int sigdelset(sigset_t *set, int signo);
/*上述四个函数的返回值:若成功返回0,出错返回-1*/ //判断指定信号 signo 是否在信号集set中。
int sigismember(const sigset_t *set, int signo);
/*返回值:若真则返回1,若假则返回0,若出错则返回-1*/

4 sigprocmask函数

每个进程都有一个信号屏蔽字(signal mask),对于每一种可能的信号,屏蔽字中都有一位与之对应,它规定了当前要阻塞而不能递送到该进程的信号集。sigprocmask 函数可以检测或者设置进程的信号屏蔽字。

#include <signal.h>
int sigprocmask(int how, const sigset_t *restrict set, sigset_t *restrict oset);
/*返回值:若成功则返回0,若出错则返回-1*/

若 oset 参数是一个非空指针,则进程的当前信号屏蔽字将通过 oset 返回。

若 set 参数是一个非空指针,则参数 how 将指示如何修改当前信号屏蔽字。

若set是一个空指针,则不改变该进程的信号屏蔽字,how的值也无意义。

how 的可选值如下表所示:

how 说明
SIG_BLOCK 该进程新的信号屏蔽字是其当前信号屏蔽字和 set 指向信号集的并集,set 包含了我们希望阻塞的信号
SIG_UNBLOCK 该进程的信号屏蔽字是当前信号屏蔽字和 set 所指向信号集补给的交集,set包含了我们希望解除阻塞的信号
SIG_SETMASK 该进程新的信号屏蔽字被set所指向的信号集代替

5 sigpending函数

函数 sigpending 获取当前进程所有未决的信号。通过其 set 参数返回未决的信号集。

#include <signal.h>
int sigpending(sigset_t *set);
/*返回值:若成功则返回0,若出错则返回-1*/

6 sigaction函数

函数sigaction的功能是检查或修改与指定信号相关的处理动作(或同时执行这两种操作)

#include <signal.h>
int sigaction(int signo, const struct sigaction *restrict act, struct sigaction *restrict oact);
/*返回值:成功返回0,出错返回-1*/

其中,参数signo是要检测或修改的信号编号。

若act指针非空,则修改其动作。

若oact指针非空,则系统经由oact指针返回该信号的上一个动作。

结构体sigaction定义如下:

struct sigaction{
void (*sa_handler)(int);//信号处理函数的地址
//或SIG_IGN,或SIG_DFL
sigset_t sa_mask;//信号屏蔽字
int sa_flags;//信号选项
/*替代的信号处理程序*/
void (*sa_sigaction)(int, siginfo_t *, void *);
};

sa_handler为一个信号处理函数,在电泳该函数之前,sigaction函数会将sa_mask信号集的内容加入到进程的信号屏蔽字之中。只有当信号处理函数返回后再将进程屏蔽字恢复成原先值。这样,在调用信号处理函数的过程中就能够阻塞某些信号,保证进程处理一个信号时不会被打断。

sa_flag字段指定对信号处理的选项,几个重要的见下表:

选项 说明
SA_INTERRUPT 由此信号中断的系统调用不会自启动
SA_RESTART 由此信号中断的系统调用会自动重启动
SA_SIGINFO 此选项对信号处理程序提供了附加信息:一个指向siginfo结构指针和一个指向进程上下文标识符的指针
SA_NOCLDSTOP 这个flag只对SIGCHLD信号有效,当这个flag设置的时候,系统会给终止的子进程发送一个信号,但是不会给已经停止的子进程发送信号。默认情况下,系统会向终止的子进程和停止的子进程都发送SIGCHLD信号

sa_sigaction字段是一个替代的信号处理程序。但sigaction结构体中使用了SA_SIGINFO标识时,使用该信号处理函数。他与sa_handler使用同一存储区,因此只能使用两者其中一个。

7 sigsetjmp和siglongjmp函数

#include <setjmp.h>
int sigsetjmp(sigjmp_buf env, int savemask);
/*返回值:若直接调用则返回0,若从siglongjmp调用则返回非0值*/
void siglongjmp(sigjmp_buf env, int val);

sigsetjmp和siglongjmp与setjmp和longjmp之间的区别在于:增加了一个savemask参数。如果savemask非0,则sigsetjmp保存当前进程的信号屏蔽字到env中,调用siglongjmp时则会从中恢复保存的信号屏蔽字。

8 sigsuspend函数

更改信号屏蔽字可以阻塞或者解除阻塞所选择的信号,用这种技术可以保护不希望由信号中断的代码临界区。如果希望一个信号解除阻塞,然后等待以前被阻塞的信号发生,需要用sigsuspend函数。

#include <signal.h>
int sigsuspend(const sigset_t *sigmask);
/*返回值:-1,并将errno设置为EINTR*/

调用该函数进程将会一直挂起,直到捕捉到sigmask里的信号并且从它的信号处理函数返回,则sigsuspend函数返回。

APUE学习笔记5——信号、信号集和进程信号屏蔽字的更多相关文章

  1. apue学习笔记(第七章 进程环境)

    本章将了解进程的环境. main函数 C程序总是从main函数开始执行,main函数的原型是: int main(int argc,char *argv[]); 其中,argc是命令行参数的数目,ar ...

  2. APUE学习笔记——10.9 信号发送函数kill、 raise、alarm、pause

    转载注明出处:Windeal学习笔记 kil和raise kill()用来向进程或进程组发送信号 raise()用来向自身进程发送信号. #include <signal.h> int k ...

  3. apue学习笔记(第十章 信号)

    本章先对信号机制进行综述,并说明每种信号的一般用法. 信号概念 每个信号都有一个名字,这些名字都以3个字符SIG开头.在头文件<signal.h>中,信号名都被定义为正整形常量. 在某个信 ...

  4. APUE学习笔记3_文件IO

    APUE学习笔记3_文件IO Unix中的文件IO函数主要包括以下几个:open().read().write().lseek().close()等.这类I/O函数也被称为不带缓冲的I/O,标准I/O ...

  5. UNIX环境编程学习笔记(24)——信号处理进阶学习之信号集和进程信号屏蔽字

    lienhua342014-11-03 1 信号传递过程 信号源为目标进程产生了一个信号,然后由内核来决定是否要将该信号传递给目标进程.从信号产生到传递给目标进程的流程图如图 1 所示, 图 1: 信 ...

  6. APUE学习笔记——10.11~10.13 信号集、信号屏蔽字、未决信号

    如有转载,请注明出处:Windeal专栏 首先简述下几个概念的关系: 我们通过信号集建立信号屏蔽字,使得信号发生阻塞,被阻塞的信号即未决信号. 信号集: 信号集:其实就是一系列的信号.用sigset_ ...

  7. APUE学习笔记——10信号——信号接口函数 signal 和 sigaction

    signal函数     signal函数是早起Unix系统的信号接口,早期系统中提供不可靠的信号机制.在后来的分支中,部分系统使用原来的不可靠机制定义signal函数,如 Solaris 10 .而 ...

  8. APUE学习笔记——10 信号

    信号的基本概念     信号是软件中断,信号提供了解决异步时间的方法.     每一中信号都有一个名字,信号名以SIG开头. 产生信号的几种方式     很多条件可以产生信号:     终端交互:用户 ...

  9. APUE学习笔记——10.可靠信号与不可靠信号

    首先说明:现在大部分Unix系系统如Linux都已经实现可靠信号. 1~31信号与SIGRTMIN-SIGRTMAX之间并不是可靠信号与不可靠信号的区别,在大多数系统下他们都是可靠信号. 只不过: 1 ...

随机推荐

  1. vc++如何创建程序-构造函数02

    1.若忘记了赋值,出现运行结果是很大的负值(因为我们定义的x与y这两个成员变量存储在内存中是一个随机的值) 当我们调用时,随机输出. //包含输入输出的头文件#include<iostream. ...

  2. 洛谷P1297 [国家集训队]单选错位_数学期望

    考虑第 iii 位, 那么当前共有 a[i]a[i]a[i] 种选项,那么当前选项正确的情况就是下一个被误填的答案与当前答案相同.换句话说,当前答案一共有 a[i]a[i]a[i] 种可能,而下一个答 ...

  3. Centos7下 yum安装php扩展

    linux下, 使用thinkphp的模板标签,如 eq, gt, volist defined, present , empty等 标签时, 报错: used undefined function ...

  4. linu问题集锦

    问题1 系统卡 慢 执行命令延迟/var/spool/mail下root文件过大导致/var磁盘空间92% cd / && du | sort -n | tail -n 10 查看排名 ...

  5. jemeter安装步骤

    1.jmeter下载地址:http://jmeter.apache.org/download_jmeter.cgi 2.在安装jmeter之前首先要安装jdk1.8以上版本,朋友们,千万不要忘了 jd ...

  6. Django 连接MySQL 通过pymysql 库

    ython3 如何安装pymysql 库,在此不再做多的讲解,如果有想知道如何安装的朋友,请求参考下面的连接地址: 第一步:应用setting.py 文件设置mysql 数据库连接相关属性.   DA ...

  7. HDU 1021 Fibonacci Again( 同余水 )

    链接:传送门 题意:现在给出 Fibonacci numbers: F(0) = 7, F(1) = 11, F(n) = F(n-1) + F(n-2) (n>=2).问第 n 项能不能整除 ...

  8. nyoj181-小明的难题

    小明的难题时间限制:3000 ms  |  内存限制:65535 KB难度:2描述课堂上小明学会了用计算机求出N的阶乘,回到家后就对妹妹炫耀起来.为了不让哥哥太自满,妹妹给小明出了个问题"既 ...

  9. java实现根据起点终点和日期查询去哪儿网的火车车次和火车站点信息

    本文章为原创文章,转载请注明,欢迎评论和改正. 一,分析 之前所用的直接通过HTML中的元素值来爬取一些网页上的数据,但是一些比较敏感的数据,很多正规网站都是通过json数据存储,这些数据通过HTML ...

  10. 《黑白团团队》第七次作业:团队项目设计完善&编码

    项目 内容 作业课程地址 任课教师首页链接 作业要求 团队项目 填写团队名称 黑白团团队 填写具体目标 认真负责,完成项目 任务1:团队软件项目设计完善 Github仓库上传<软件设计方案说明书 ...