zoukankan      html  css  js  c++  java
  • linux编程之信号

    信号(signal)机制是UNIX系统中最为古老的进程之间的通信机制,它用在一个或多个进程之间传递异步信号,信号可以由各种异步事件产生,如:

    键盘中断等等,在Linux 的shell 中,也可以使用信号将作业控制命令传递给它的子进程。在linux系统中,定义了一系列的信号,这些信号可以由

    内核产生,也可以有系统中的其他进程产生,只要这些进程的权限足够大。进程可以屏蔽掉大多数的信号,除了SIGSTOP和SIGKILL,前者使一个

    正在运行的进程暂停,后者则使一个正在运行的进程退出。应用程序收到信号后,有三种处理方式:忽略,默认,或捕捉。进程收到一个信号后,

    会检查对该信号的处理机制。如果是SIG_IGN,就忽略该信号;如果是SIG_DFT,则会采用系统默认的处理动作,通常是终止进程或忽略该信号;

    如果给该信号指定了一个处理函数(捕捉),则会中断当前进程正在执行的任务,转而去执行该信号的处理函数,返回后再继续执行被中断的任务。

    1.信号截取函数 signal()

    #include<signal.h>
    typedef void (*sighandler_t) (int);
    sighandler_t signal(int signum, sighandler_t handler);
    signal()是最简单的给进程安装信号处理器的函数,第一个参数指定信号,第二个参数为该信号指定一个处理函数。它的返回值为原信号处理函数,
    或SIG_ERR
     
    2.发送信号的kill和raise函数
     
    #include<sys/types.h>
    #include<signal.h> 
    int kill(pid_t pid, int sig);
    int raise(int sig);
    kill()发送信号给指定进程,raise()发送信号给进程本身。对kill()的pid,有如下描述:
     
    pid > 0 将信号发送给ID为pid的进程
    pid == 0 将信号发送给与发送进程属于同意个进程组的所有进程
    pid < 0 将信号发送给进程组ID等于pid绝对值的所有进程
    pid == -1 将信号发送给该进程有权限发送的系统里的所有进程
     
    3.等待信号的pause函数
    int pause(void);
     
    pause()会使当前进程挂起,直到捕捉到一个信号,对指定为忽略的信号,pause()不会返回。只有执行了一个信号处理函数,并从其返回,
    puase()才返回-1,并将errno设为EINTR。
     
    4.信号集函数
     
    int sigemptyset(sigset_t * set);
    int sigfillset(sigset_t * set);
    int sigaddset(sigset_t * set, int signum);
    int sigdelset(sigset_t * set, int signum);
    int sigismember(sigset_t * set, int signum);
     
    信号集是Linux中的一种特殊的数据类型,由于无法确定信号的多少,所以不能用简单数据类型来包含所有可能的信号,所以系统就定义了一个sigset_t
    的数据类型专门用于信号集。同时还定义了一族用于处理信号集的函数。这样用户可以不必关心信号集的实现,只要使用以上这组函数来处理信号集就可以了。
     sigemptyset()和sigfillset()都用于初始化一个信号集,前者用于清空信号集中所有的信号,后者则用于设置信号集中所有的信号;信号集在使用前必须要经
    过初始化,初始化后,就可以用sigaddset()和sigdelset()往信号集里添加删除信号了。sigismember()用于判断指定信号是否在信号集中。
     
    5.修改信号屏蔽字的sigprocmask函数
     
    int sigprocmask(int how, const sigset_t * set, sigset_t * oldset);
     
    每个进程都会有一个信号屏蔽字,它规定了当前进程要阻塞的信号集。对于每种可能的信号,信号屏蔽字中都会有一位与之对应,如果该位被设置,该信号当前
    就是阻塞的。进程可以通过sigprocmask()来获得和修改当前进程的信号屏蔽字。sigpromask()根据how指定的方式,设置进程的当前信号屏蔽字为set,并将
    旧的信号屏蔽字保存在oldset中返回。如果set为NULL,则不修改当前信号屏蔽字,而将其通过oldset返回;如果oldset为NULL,则不会返回旧的信号屏蔽字。
    how支持以下三种方式,见下表。
     
     how  说明

    SIG_BLOCK

     

    SIG_UNBLOCK

     

    SIG_SETMASK

    设置阻塞set指定的信号集

     

    设置解除阻塞set指定的信号集

     

    设置当前信号屏蔽字为set,在set中的信号都会被阻塞,不在set中的信号会被递送

    6.获得未决的信号sigpending

    int sigpending(sigset_t * set);
     
    信号是由某些事件产生的,这些事件可能是硬件异常(如被零除),软件条件(如计时器超时),终端信号或调用kill()/raise()函数。信号产生时,内核通常会在进程表中
    设置某种标志,表示当前信号的状态。当内核对信号采取某种动作时,我们说向进程递送(deliver)了一个信号,而在信号产生和递送之间的间隔内,该信号的状态是
    未决的(pending)。 而sigpending函数在set中返回进程中当前尚未递送的信号集。
     
    7.查询或设置信号处理方式的sigaction()函数

    int sigaction(int signo,const struct sigaction *restrict act,struct sigaction *restrict oact);

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

    结构sigaction定义如下:

    struct sigaction{
      void (*sa_handler)(int);
      sigset_t sa_mask;
      int sa_flag;
      void (*sa_sigaction)(int,siginfo_t *,void *);
    };

    sa_handler字段包含一个信号捕捉函数的地址

    sa_mask字段说明了一个信号集,在调用该信号捕捉函数之前,这一信号集要加进进程的信号屏蔽字中。仅当从信号捕捉函数返回时再将进程的信号屏蔽字复位为原先值。

    sa_flag是一个选项,主要理解两个

    SA_INTERRUPT 由此信号中断的系统调用不会自动重启
    SA_RESTART 由此信号中断的系统调用会自动重启

    SA_SIGINFO 提供附加信息,一个指向siginfo结构的指针以及一个指向进程上下文标识符的指针

    SA_INTERRUPT 由此信号中断的系统调用不会自动重启
    SA_RESTART 由此信号中断的系统调用会自动重启

    SA_SIGINFO 提供附加信息,一个指向siginfo结构的指针以及一个指向进程上下文标识符的指针

    最后一个参数是一个替代的信号处理程序

  • 相关阅读:
    窗体控件JFrame的使用
    WindowBuilder的安装与简介
    Swing事件机制
    Swing的MVC结构
    Swing框架的继承关系
    SWT简介
    Swing简介
    AWT简介
    Java界面设计
    使用Java建立聊天客户端
  • 原文地址:https://www.cnblogs.com/kunhu/p/3618237.html
Copyright © 2011-2022 走看看