美文网首页
APUE信号

APUE信号

作者: m风满楼 | 来源:发表于2018-09-29 14:41 被阅读0次

    第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 大部分应用程序并不处理这些信号。

    相关文章

      网友评论

          本文标题:APUE信号

          本文链接:https://www.haomeiwen.com/subject/qezvoftx.html