APUE信号

第10章 信号

  • 信号是软件中断
  • 信号提供了一种处理异步事件的方法

10.2 信号概念

  • 信号都以SIG开头
  • 信号名都被定义为正整数常量,不存在编号为0的信号,kill函数对信号编号0有特殊的应用,这种信号称为空信号
  • 很多条件可以产生信号
    • 当用户按某些终端键,引发终端产生的信号
    • 硬件产生的信号:除数为0,无效内存引用
    • 进程调用kill可将任意信号发送给另一个进程或进程组
    • 用户可调用kill将信号发送给其他进程
    • 当检测到某种软件条件已经发生,并将其通知有关的进程时也产生信号
  • 信号是异步事件的经典案例。产生信号的的事件对进程来说是随机出现的
  • 在某个信号出现时,可以告诉内核按照下列三种方式之一处理
    • 忽略
      • 大多数信号可以使用这种方式进行处理,但时SIGKILL和SIGSTOP不能被忽略,因为他们向内核和超级用户提供了使进程终止的可靠方法。
    • 捕捉
      • 做到这一点的前提是要通知内核在某种信号发生时,调用一个用户函数,在用户函数中对这种事件进行处理
    • 执行系统默认动作
      • 大多数信号的系统默认动作是终止进程
      • 在系统默认动作中,有的默认动作回在进程当前工作目录中生成core文件(中间复制了该进程的内存映像)
  • 下面几种条件不产生core文件
    • 进程是设置用户id的,而且当前用户并非程序文件的所有者
    • 进程是设置组id的
    • 用户没有写当前工作目录的权限的
    • 文件已经存在,而且用户对该文件有写权限
    • 文件太大
  • 常用信号
    • SIGABRT
      • 调用abort函数时产生此信号
    • SIGBUG
      • 硬件故障产生
    • SIGCHLD
      • 当一个进程终止或停止,SIGCHLD信号被送给父进程。父进程可以使用wait取得子进程id和终止状态
    • SIGHUP
      • 如果终端检测到一个连接断开,则将此信号送给与该终端相关的控制进程
    • SIGILL
    • SIGINFO
    • SIGINT
      • 终端键产生
    • SIGIO
      • 异步io事件
        — SIGKILL
      • 这是两个不能被捕捉或忽略信号中的一个,直接杀死进程
    • SIGPIPE
      • 如果管道的读进程已终止写管道,产生该信号
    • SIGQUIT
      • 退出键时触发
    • SITTERM
      • 这是kill命令发送的的系统默认终止信号。该信号由应用程序捕获,可以让程序有机会在退出前做好清理工作。

10.3 函数signal

  • 信号机制最简单的接口时signal函数
#include<signal.h>
void(*signal(int signo,void (*func)(int)))(int) ;
成功返回以前的信号处理配置,出错返回SIG_ERR
  • 该函数的signal参数是信号名,func值是接收到此信号后要调用的函数的地址。
  • 当指定函数地址时,则信号发生时,调用该函数。我们称这种函数为信号处理程序或信号捕捉函数
  • 程序启动
    • 当执行一个程序时,所有信号状态都是系统默认或忽略。
    • shell自动将后台进程对终端和退出信号的处理方式设置为忽略
  • 进程创建
    • 当一个进程调用fork时,其子进程继承父进程的信号处理方式

10.4 不可靠的信号

在早期的unix版本中,信号是不可靠的,不可靠指的是信号可能会丢失:一个信号发生了,但进程可能不知道这一点。同时,进程对信号的控制能力也很差,他能捕获信号或或忽略它。

10.5 中断的系统调用

  • 早期unix系统的特性是:如果进程在执行一个低速系统而阻塞期间捕捉到一个信号,则该系统调用就被中断不在继续执行。

  • 当捕捉到某个信号时,被中断的是内核中执行的系统调用

  • 为了支持该特性,系统调用分为两类

    • 低速系统调用(<span style="color:#a6684d"><span style="color:#e1441c">低速系统调用</span></span>是可能会使进程永远阻塞的的一类系统调用)

      • 某些类型文件不存在(读管道,终端和网络设备),则读操作坑会永远阻塞
      • 如果这些数据不能被相同类型文件立即接受,则可操作可能会使调用者永远阻塞
      • 在某种条件发生之前被相同类型文件立即接受,则可能会发生阻塞(例如打开一个终端设备,需要先等待与之连接的调制解调器应答)
      • pause函数(它使调用进程休眠直至捕捉到一个信号)和wait函数
      • 某些ioctl操作
      • 某些进程间通信函数
    • 其他系统调用

  • 中断系统调用表示某个系统调用被阻塞,需要被中断。

  • 与被中断的系统调用相关的问题是必须显示的处理出错返回

  • 某些操作系统为了使程序不必处理被中断的系统调用,引入了自动重启动的系统调用

10.6 可重入函数

  • 进程捕捉到信号并对其进行处理时,进程正在执行的正常指令序列就被信号处理程序临时中断,它首先执行该信号处理程序中的指令。
  • 如果在信号处理的过程中,由于出现克了新的信号,则会导致信息的丢失或被覆盖,因而引入了可重入的函数
    • 可重入是一种异步信号安全的函数。在信号处理操作期间,它会阻塞任何会引起信号不一致的信号发送。
    • 没有列入表中的大部分是不可重入的函数,不可重入的函数大多将变量存储在全局数据结构中
  • 每个线程只有一个errno变量,所以信号处理程序可能会更改其原先值。所以当在信号处理程序中调用read这类函数,在调用前应该保存errno,调用后恢复errno。

10.7 sigcld语义

10.8 可靠的信号术语和语义

  • 当造成信号的事件发生时,为进程产生一个信号
  • 事件可以是硬件异常,软件条件,终端产生的信号或调用kill函数
  • 当一个信号产生的时候,内核通常在进程表中以某种形式设置一个标志
  • 当对信号才去了这种的动作的时候,我们说向进程<span style="color:#f00808">递送</span>了一个信号
  • 在信号产生和递送之间的事件间隔,信号是<span style="color:#f00808">未决的</span>
  • 进程可以选用'阻塞信号递送',如果为进程产生了一个阻塞的信号,而且对该信号的动作时系统默认动作或捕捉该信号,则为该进程将此信号保持为未决状态,直到该进程为对此信号接触了阻塞,或者将该信号的动作改为忽略。
  • 内核在递送一个原来被阻塞的信号给进程时(而不是产生该信号时),才决定对他的处理方式
  • 进程调用sigpending函数来判定哪些信号是设置为阻塞并处于未决状态的。
  • 每个进程都有一个信号屏蔽字(signal mask),它规定了当前号阻塞递送到该进程的信号集。

10.8 kill和raise

  • kill函数将信号发送给进程或进程组,raise函数允许进程向自身发送信号
#include <signal.h>

int kill(pid_t pid, int signo) ;
int raise(int signo) ;
    //成功返回0,出错返回-1
// raise 调用等价于 kill(getpid(), signo) ;
  • kill的pid参数有以下4种情况
    • pid>0 将该信号发送给进程id为pid的进程
    • pid
  • 进程将信号发送给其他进程需要权限
  • 对于非超级用户,基本规则是发送者的实际用户id或有效用户id必须等于接受着的实际用户id或有效用户id

10.10 函数alermh和函数pause

  • 使用alerm设置一个定时器,在将来的某时刻该定时器超时,产生SIGALRM信号,如果忽略或不捕捉此信号,则其默认动作是终止调用该函数的进程
#include<unistd.h>
unsigned int alarm(unsigned int seconds) 
    //0 或设置的闹钟时间剩余的秒数
  • 每个进程只能有一个闹钟时间
  • pause函数使调用进程挂起直至捕捉一个信号
#include<unistd.h>
int pause(void) ;
    //-1 ,errno设置为ENTER

10.14 sigaction函数

  • sigaction函数的功能是检查或修改与指定信号关联的处理动作
#include <signal.h>
int sigaction(int signo, const struct siaction *restrict act,
    struct sigaction *restrict oact) ;
        //成功返回0,出错返回-1
        //signo是要检测或修改其具体动作的信号编号,若act制作非空,则修改其动作。如果oact指针非空,则系统经由oact指针返回上一个信号的动作。
        struct sigaction{
            void (*sa_handler)(int) ;
            sigset_t sa_mask ;
            int sa_flags ;
            void (*sa_sigaction)(int, siginfo_t *, void *) ;
        }

10.17 函数abort

  • 使程序异常终止
#include<stdlib.h>
void abort(void) ;
  • 此函数发送SIGABRT信号给调用进程

10.18 函数system

10.19 函数system

10.21 作业控制信号

  • 以下几个信号和作业控制有关
    • SIGCHLD子进程已停止或者终止
    • SIGCONT 如果进程已经停止,则使其继续运行
    • SIGSTOP 停止信号
    • SIGTSTP 交互式停止信号
    • SIGTTIN 后台进程组成员读控制终端
    • SIGTTOU 后台进程组成员写控制终端
  • 除了SIGCHLD 大部分应用程序并不处理这些信号。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,923评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,154评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,775评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,960评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,976评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,972评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,893评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,709评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,159评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,400评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,552评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,265评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,876评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,528评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,701评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,552评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,451评论 2 352

推荐阅读更多精彩内容

  • 信号的基本概念 信号被认为是一种软件中断(区别于硬件中断),信号机制提供了一种在单进程/线程下处理异步事件的方法。...
    小叶大孟阅读 1,907评论 0 1
  • 对于 Linux来说,实际信号是软中断,许多重要的程序都需要处理信号。信号,为 Linux 提供了一种处理异步事件...
    故事狗阅读 84,889评论 2 62
  • 1.内存的页面置换算法 (1)最佳置换算法(OPT)(理想置换算法):从主存中移出永远不再需要的页面;如无这样的...
    杰伦哎呦哎呦阅读 3,247评论 1 9
  • 计算机系统漫游 代码从文本到可执行文件的过程(c语言示例):预处理阶段,处理 #inlcude , #defin...
    willdimagine阅读 3,579评论 0 5
  • 清明时节天阴沉, 跪拜墓地祭亲人。 一壶老酒坟头奠, 不忘祖辈养育恩。
    普通人_8909阅读 131评论 0 0