您的位置:首页 > 编程语言

《unix环境高级编程》信号——sigaction 函数

2014-11-25 16:27 309 查看

sigaction 函数

sigaction 函数的功能与 signal 类似,用于检查或修改与指定信号相关联的处理动作,一般在应用中使用 sigaction 函数。

[cpp] view
plaincopy





/* sigaction函数 */

/*

* 函数功能: 检查或修改与指定信号相关联的处理动作;此函数取代之前的signal函数;

* 返回值:若成功则返回0,若出错则返回-1;

* 函数原型:

*/

#include <signal.h>

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

/*

* 说明:

* signo是要检查或修改其具体动作的信号编号;

* 若act非空,则要修改其动作;

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

*

* struct sigaction 结构如下:

*/

struct sigaction

{

void (* sa_handler)(int); /* addr of signal handler, or SIG_IGN, or SIG_DFL */

sigset_t sa_mask; /* additional signals to block */

int sa_flags; /* signal options */

/* alternate handler */

void (*sa_sigaction)(int, siginfo_t *, void *);

};

/*

* 说明:

* 当更改动作时,若sa_handler 字段包含一个信号捕捉函数的地址,则sa_mask字段说明了一个信号集,在调用该信号捕捉函数之前,

* 这一信号集要加到进程的信号屏蔽字中。仅当从信号捕获函数返回时再将进程的信号屏蔽字复位为原先值;

* 其中sa_flags标志如下:

* (1)SA_INTERRUPT 由此信号中断的系统调用不会自动重启;

* (2)SA_NOCLDSTOP 若signo是SIGCHLD,当子进程停止时,不产生此信号,当子进程终止时,仍然产生此信号;若已设置此标志,则当停止的进程继续运行时,不发送SIGCHLD信号;

* (3)SA_NOCLDWAIT 若signo是SIGCHLD,当子进程停止时,不创建僵死进程;若调用进程后面调用wait,则调用进程阻塞,直到其所有子进程都终止,此时返回-1,并将errno设置为ECHILD;

* (4)SA_NOEFER 当捕捉到此信号时,在执行其信号捕捉函数时,系统不自动阻塞此信号;

* (5)SA_NOSTACK 若用signaltstack(2)声明了一替换栈,则将此信号传递给替换栈上的进程;

* (6)SA_RESETHAND 在此信号捕捉函数入口处,将此信号的处理方式复位为SIG_DEL,并清除SA_SIGINFO标志;

* (7)SA_RESTART 由此信号中断的系统调用会自动重启动;

* (8)SA_SIGINFO 此选项对信号处理程序提供附加信息:一个指向siginfo结构的指针以及一个指向进程上下文标识符的指针;

*/

sa_sigaction 字段是一个替代的信号处理程序,当在 sigaction 结构中使用了 SA_SIGINFO 标志时,使用该信号处理程序。通常,按下列方式调用信号处理程序:

[cpp] view
plaincopy





void handler(int signo);

如果设置了 SA_SIGINFO 标志,那么按照下列方式调用信号处理程序:

[cpp] view
plaincopy





void handler(int signo, siginfo_t *info, void *context);

//siginfo 的结构如下:

struct siginfo{

int sig_signo; //信号编号

int sig_errno; //如果不是0,就是errno.h中的errno值

int sig_code; //附加信息(取决于信号)

pid_t si_pid; //发送信号的进程ID

uid_t sig_uid; //发送信号的进程实际用户ID

void *si_addr; //产生错误的地址

int si_status; //退出值或者信号值

long si_band; //SIGPOLL的band号

//可能还会有其他的值。

}

下面可以 sigaction 函数实现 signal 函数的功能:

[cpp] view
plaincopy





#include "apue.h"

Sigfunc *signal(int signo, Sigfunc *func)

{

struct sigaction act, oact;

/* 设置信号处理函数 */

act.sa_handler = func;

/* 初始化信号集 */

sigemptyset(&act.sa_mask);

act.sa_flags = 0;

if(signo == SIGALRM)

{/* 若是SIGALRM信号,则系统不会自动重启 */

#ifdef SA_INTERRUPT

act.sa_flags |= SA_INTERRUPT;

#endif

}

else

{/* 其余信号设置为系统会自动重启 */

#ifdef SA_RESTART

act.sa_flags |= SA_RESTART;

#endif

}

/* 调用 sigaction 函数 */

if(sigaction(signo, &act, &oact) < 0)

return(SIG_ERR);

return(oact.sa_handler);

}

测试程序:

[cpp] view
plaincopy





#include <sys/types.h>

#include "apue.h"

#include <signal.h>

static Sigfunc *Msignal(int signo, Sigfunc *func);

static void sig_func(int signo);

int main(void)

{

if(Msignal(SIGALRM,sig_func) == SIG_ERR)

err_sys("SIGALRM error");

if(Msignal(SIGHUP,sig_func) == SIG_ERR)

err_sys("SIGHUP error");

printf("kill...\n");

kill(getpid(),SIGHUP);

printf("alarm...\n");

alarm(5);

pause();

printf("exit.\n");

exit(0);

}

static void sig_func(int signo)

{

if(SIGHUP == signo)

printf("Recevied kill.\n");

else if(SIGALRM == signo)

printf("Recevied alarm.\n");

else

printf("Recevied others.\n");

}

static Sigfunc *Msignal(int signo, Sigfunc *func)

{

struct sigaction act, oact;

/* 设置信号处理函数 */

act.sa_handler = func;

/* 初始化信号集 */

sigemptyset(&act.sa_mask);

act.sa_flags = 0;

if(signo == SIGALRM)

{/* 若是SIGALRM信号,则系统不会自动重启 */

#ifdef SA_INTERRUPT

act.sa_flags |= SA_INTERRUPT;

#endif

}

else

{/* 其余信号设置为系统会自动重启 */

#ifdef SA_RESTART

act.sa_flags |= SA_RESTART;

#endif

}

/* 调用 sigaction 函数 */

if(sigaction(signo, &act, &oact) < 0)

return(SIG_ERR);

return(oact.sa_handler);

}

输出结果:

[cpp] view
plaincopy





kill...

Recevied kill.

alarm...

Recevied alarm.

exit.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐