您的位置:首页 > 运维架构 > Linux

linux 信号简介二 信号处理函数安装

2011-01-19 10:41 495 查看
3. 内核对信号的基本处理方法

内核给一个进程发送软中断信号的方法,是在进程所在的进程表项的信号域设置对应于该信号的位。内核处理一个进程收到的信号的时机是在一个进程从内核态返回用户态时。所以,当一个进程在内核态下运行时,软中断信号并不立即起作用,要等到将返回用户态时才处理。

4. 用signal函数安装信号处理函数

函数原型:__sighandler_t signal(int sig, __sighandler_t handler);

sig: 输入参数,信号名称,指定要安装的信号

handler:输入参数,指向信号处理函数的指针。或者为SIG_DEN, 即采用默认信号处理方式,或者SIG_IGN,忽略该信号

返回值:SIG_ERR, 安装信号失败

其他值: 原来的信号处理函数指针

例子:

#include<stdio.h>
#include<signal.h>
void Handlesignal(int signo)
{
printf("receive signal %d./n",signo);
}
int main()
{
if(signal(SIGINT,Handlesignal)==SIG_ERR){//按ctrl+C产生SIGINT信号
perror("/ncan't install signal/n");
return -1;
}
pause();
return 0;
}


5. 用signal可以实现基本的信号安装功能,在某些情况下,需要对信号的安装进行更多的控制,这时候就需要用到sigaction函数

函数原型: int sigaction(int signum, __const struct sigaction *__restrict act, struct sigaction *__restrict oact)

1. signum:输入参数,信号名称,指定要安装的信号

2. act: 输入参数,制定安装信号的数据结构,该参数是个struct sigaction类型的结构指针。 其原型

struct sigaction

{

/* Signal handler. */

#ifdef __USE_POSIX199309

union

{

/* Used if SA_SIGINFO is not set. */

__sighandler_t sa_handler;

/* Used if SA_SIGINFO is set. */

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

}__sigaction_handler;

# define sa_handler __sigaction_handler.sa_handler

# define sa_sigaction __sigaction_handler.sa_sigaction

#else

__sighandler_t sa_handler;

#endif

/* Additional set of signals to be blocked. */

__sigset_t sa_mask;

/* Special flags. */

int sa_flags;

/* Restore handler. */

void (*sa_restorer) (void);

};

A:__sigaction_handler 用于定义信号处理函数,指向信号处理函数指针。void (*sa_sigaction) (int, siginfo_t *, void *); 中siginfo_t的结构

siginfo_t {

int si_signo; /* Signal number */

int si_errno; /* An errno value */

int si_code; /* Signal code */

pid_t si_pid; /* Sending process ID */

uid_t si_uid; /* Real user ID of sending process */

int si_status; /* Exit value or signal */

clock_t si_utime; /* User time consumed */

clock_t si_stime; /* System time consumed */

sigval_t si_value; /* Signal value */

int si_int; /* POSIX.1b signal */

void * si_ptr; /* POSIX.1b signal */

void * si_addr; /* Memory location which caused fault */

int si_band; /* Band event */

int si_fd; /* File descriptor */

}

B:sa_mask 信号掩码,在该掩码中定义的信号将被阻塞

C:sa_flags 标志位。主要有:

(1)SA_RESETHAND 处理完毕要捕捉的信号后,将自动撤消信号处理函数的注册,即必须再重新注册信号处理函数,

才能继续处理接下来产生的信号。

   (2)SA_NODEFER 在处理信号时,如果又发生了其它的信号,则立即进入其它信号的处理,等其它信号处理完毕后,

   再继续处理当前的信号,即递规地处理。如果sa_flags包含了该掩码,则结构体sigaction的sa_mask将无效;

   (3)SA_RESTART 如果在发生信号时,程序正阻塞在某个系统调用,例如调用read()函数,则在处理完毕信号后,

   接着从阻塞的系统返回。该掩码符合普通的程序处理流程,所以一般来说,应该设置该掩码,否则信号处理完后,

   阻塞的系统调用将会返回失败;SA_RESTART参数表明如果信号中断了进程某个系统调用,将由系统自动重启该系统调用。

   如果不指定该参数,则被中断系统调用将返回失败,错误码为EINTR

   (4)SA_SIGINFO 指示结构体的信号处理函数指针是哪个有效,如果sa_flags包含该掩码,

   则sa_sigactiion指针有效,否则是sa_handler指针有效。

3. oact:输出参数,指向struct sigaction结构指针。调用sigaction成功后,该参数将返回ixinhaode原来处理方式。该参数可为NULL。

返回值:0 调用成功,-1调用失败,可用errno获取错误信息。

例子:

#include<stdio.h>
#include<signal.h>
#include<string.h>
void HandleSigint(int signo, siginfo_t *info, void *none)
{
printf("receive signal %d, addtional data is: %d/n",signo,info->si_value.sival_int);
printf("the send process id is: %u/n",info->si_pid);
printf("the si_signo is: %d/n",info->si_signo);
printf("the si_int is: %d/n",info->si_int);
}
//如果用act.sa_handler=HandleSigint,则用该信号处理函数
/*void HandleSigint(int signo)
{
printf("receive signal %d/n",signo);
}
*/
int main()
{
struct sigaction act, oact;
memset(&act,0x00,sizeof(struct sigaction));
sigemptyset(&act.sa_mask);
act.sa_sigaction=HandleSigint;
//act.sa_handler=HandleSigint;
act.sa_flags=SA_SIGINFO;
if(sigaction(SIGINT,&act,&oact)==-1){//按ctrl+C产生SIGINT信号
perror("sigaction error/n");
return -1;
}
pause();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: