signal 函数的使用方法简单,但并不属于 POSIX 标准,在各类 UNIX 平台上的实现不尽相同,因此其用途受到了一定的限制。而 POSIX 标准定义的信号处理接口是 sigaction 函数,其接口头文件及原型如下:
 #include <signal.h>
 int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);

◆ signum:要操作的信号。
 ◆ act:要设置的对信号的新处理方式。
 ◆ oldact:原来对信号的处理方式。
 ◆ 返回值:0 表示成功,-1 表示有错误发生。

struct 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);
 };

sa_handler:是一个函数指针,其含义与 signal 函数中的信号处理函数类似

sa_sigaction:另一个信号处理函数,它有三个参数,可以获得关于信号的更详细的信息。当 sa_flags 成员的值包含了 SA_SIGINFO 标志时,系统将使用 sa_sigaction 函数作为信号处理函数,否则使用 sa_handler 作为信号处理函数。

sa_flags 成员用于指定信号处理的行为,它可以是一下值的“按位或”组合。
 ◆ SA_RESTART:使被信号打断的系统调用自动重新发起。
 ◆ SA_NOCLDSTOP:使父进程在它的子进程暂停或继续运行时不会收到 SIGCHLD 信号。
 ◆ SA_NOCLDWAIT:使父进程在它的子进程退出时不会收到 SIGCHLD 信号,这时子进程如果退出也不会成为僵尸进程。
 ◆ SA_NODEFER:使对信号的屏蔽无效,即在信号处理函数执行期间仍能发出这个信号。
 ◆ SA_RESETHAND:信号处理之后重新设置为默认的处理方式。
 ◆ SA_SIGINFO:使用 sa_sigaction 成员而不是 sa_handler 作为信号处理函数

sa_mask: 这个参数指明了在信号处理函数执行过程中应该被阻止的信号的mask值。此外,触发这个handler的信号应该被阻止。

首先来看下sigaction的用法:

void ouch(int signum){

printf("received sig=%d\n",signum);

}

void signal_action_fun(){

struct sigaction act;

act.sa_handler=ouch;

sigemptyset(&act.sa_mask);

act.sa_flags=0;

sigaction(SIGINT,&act,NULL);

while(1){

printf("hello world!\n");

sleep(1);

}

}

当接受到终端发送的CTRL_C信号的时候,将会打印出该信号的值

继续来看下使用sa_sigaction的用法。

sa_sigaction函数中的siginfo_t 参数是一个如下定义的结构体:从中可以获取信号编号,进程ID等等信息

siginfo_t  {

int si_signo; /*信号编号*/

int si_errno; /*错误号*/

int si_code; /*信号码*/

int si_trapno;/*导致硬件产生信号的trap号*/

pid_t si_pid; /*发送进程ID*/

uid_t si_uid; /*发送进程真实的用户ID*/

int si_status; /*退出值*/

clock_t si_utime; /*花费的用户时间*/

clock_t si_stime; /*花费的系统时间*/

sigval_t si_value; /*信号值*/

int si_int ; /*POSIX.1b 信号*/

void *si_ptr; /*POSIX.1b 信号*/

int  si_overrun

int si_timerid

void *si_addr

long si_band

int si_fd;

short si_addr_lsb;

}

代码修改如下:

void ouch(int signum,siginfo_t *info,void *para){

printf("received sig=%d,the process id is %d\n",signum,info->si_pid);

printf("the uid is %d\n",info->si_uid);

}

void signal_action_fun(){

struct sigaction act;

sigemptyset(&act.sa_mask);

act.sa_flags=0;

act.sa_flags|=SA_SIGINFO;  /*设置SA_SIGINFO表示使用sa_sigaction*/

act.sa_sigaction=ouch;

sigaction(SIGINT,&act,NULL);

while(1){

printf("hello world!\n");

sleep(1);

}

}

运行结果如下:在收到CTRL_C信号后,会打印出信号ID,进程ID以及用户ID。

linux c编程:信号(四) sigaction的更多相关文章

  1. Linux系统编程——信号

    目录 信号的介绍 信号的机制 信号的编号 Linux常规信号一览表 信号的产生 终端按键产生信号 硬件异常产生信号 kill函数/命令产生信号 信号的操作函数 信号集设定 sigprocmask函数 ...

  2. linux系统编程--信号

    信号的概念 man 7 siganl  查看man手册 信号在我们的生活中随处可见, 如:古代战争中摔杯为号:现代战争中的信号弹:体育比赛中使用的信号枪......他们都有共性:1. 简单 2. 不能 ...

  3. Linux系统编程—信号捕捉

    前面我们学习了信号产生的几种方式,而对于信号的处理有如下几种方式: 默认处理方式: 忽略: 捕捉. 信号的捕捉,说白了就是抓到一个信号后,执行我们指定的函数,或者执行我们指定的动作.下面详细介绍两个信 ...

  4. Linux系统编程—信号集操作函数

    先来回顾一下未决信号集是怎么回事. 信号从产生到抵达目的地,叫作信号递达.而信号从产生到递达的中间状态,叫作信号的未决状态.产生未决状态的原因有可能是信号受到阻塞了,也就是信号屏蔽字(或称阻塞信号集, ...

  5. Linux网络编程学习(四) -----守护进程的建立(第三章)

    本文介绍一个例程daemon_init() #include <sys/types.h> #include <signal.h> #include <unistd.h&g ...

  6. Linux系统编程(24)——信号的生命周期

    信号生命周期为从信号发送到信号处理函数的执行完毕. 对于一个完整的信号生命周期(从信号发送到相应的处理函数执行完毕)来说,可以分为三个重要的阶段,这三个阶段由四个重要事件来刻画:信号诞生:信号在进程中 ...

  7. Linux网络编程(四)

    在linux网络编程[1-3]中,我们编写的网络程序仅仅是为了了解网络编程的基本步骤,实际应用当中的网络程序并不会用那样的.首先,如果服务器需要处理高并发访问,通常不会使用linux网络编程(三)中那 ...

  8. Linux高性能server编程——信号及应用

     信号 信号是由用户.系统或者进程发送给目标进程的信息.以通知目标进程某个状态的改变或系统异常. Linux信号可由例如以下条件产生: 对于前台进程.用户能够通过输入特殊的终端字符来给它发送信号. ...

  9. linux系统编程之信号(三):信号安装、signal、kill,arise讲解

    一,信号安装 如果进程要处理某一信号,那么就要在进程中安装该信号.安装信号主要用来确定信号值及进程针对该信号值的动作之间的映射关系,即进程将要处理哪个信号:该信号被传递给进程时,将执行何种操作. li ...

随机推荐

  1. [React] Use react-rewards to add microinteractions to React app to reward users for some actions

    It's important that our users enjoy using our application or website. One way we can make it happen ...

  2. [Functional Programming] Define Discrete State Transitions using the State ADT

    We build our first state transactions as two discrete transactions, each working on a specific porti ...

  3. native method与so中function的关联

    在Android中,可以通过JNI的方式来调用和访问用C/C++实现的代码,这些代码以SharedLibrary的方式存在于so中.从Java Code到Native Code的一般使用过程为: 在J ...

  4. iOS 通用button 上图下字

    UIButton *first = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, kHeight(80), kHeight(80))]; [firs ...

  5. Transform.eulerAngles 欧拉角

    var eulerAngles : Vector3 Description描述 The rotation as Euler angles in degrees. 旋转作为欧拉角度. The x, y, ...

  6. Git简明操作

    我每天使用 Git ,但是很多命令记不住. 一般来说,日常使用只要记住下图6个命令,就可以了.但是熟练使用,恐怕要记住60-100个命令. 下面是我整理的常用 Git 命令清单.几个专用名词的译名如下 ...

  7. 【C/C++学院】0828-数组与指针/内存分配/数据结构数组接口与封装

    [送给在路上的程序猿] 对于一个开发人员而言,可以胜任系统中随意一个模块的开发是其核心价值的体现. 对于一个架构师而言,掌握各种语言的优势并能够运用到系统中.由此简化系统的开发,是其架构生涯的第一步. ...

  8. 会话管理之session技术

    上一节我们总结了cookie技术,这节主要总结一下session技术. 1. session对象 在web开发中,服务器可以为每个用户浏览器创建一个会话对象(session对象),注意:一个浏览器独占 ...

  9. $on、$emit和$broadcast的使用

    $emit只能向parent controller传递event与data( $emit(name, args) ) $broadcast只能向child controller传递event与data ...

  10. Lua基本函数库 【转】

    转自:http://www.cnblogs.com/whiteyun/archive/2009/08/12/1543184.html 基本函数库为Lua内置的函数库,不需要额外装载 assert (v ...