赞
踩
如果进程要处理某一信号,那么就要在进程中安装该信号。安装信号作用是确定进程针对该信号值的动作之间的映射关系,即进程将要处理哪个信号;该信号被传递给进程时,将执行何种操作。
函数原型 | #include <signal.h> sighandler_t signal(int signum, sighandler_t handler); typedef void (*sighandler_t)(int); |
---|---|
参数 | signum:要捕捉的信号 handler:信号处理函数 信号处理函数中的int参数为传递的信号 |
案列1:
进程在运行过程中如果没有信号产生,会执行默认的程序,如果产生信号,会跳转到signal 信号处理函数当中执行信号的动作 ,执行完毕,返回主程序继续执行 。 信号默认动作是终止进程比如ctrl c 如果 捕捉信号成功,则 不会执行默认的动作 。
案列2:
在前面的《信号基础介绍》第七小节介绍了,信号的处理有三种方式:①、执行默认动作 ;②、忽略该信号;③、执行用户期望的动作(上诉案列1就是)。这个案列我们做个信号产生时忽略该信号的实验。
案列3:
①、一个进程中接受多个相同类型的信号
当同一个进程当中有多个相同信号,信号发生时会执行完第一个信号之后,再执行第二个信号。但不可靠信号不支持排队 ,不会将所有的信号全部捕捉 。(例如:你在主函数中只写了两个捕捉信号函数,捕捉的是同一个信号,那么当连续发生该信号二次以上时,只会执行两次信号的处理函数)
②、一个进程中接受多个不同类型的信号
同一个进程当中产生多个不同类型的信号,当第一个信号在执行信号处理函数,第二个不同类型的信号发生,会优先执行第二个信号,执行完毕,再接着继续未执行完毕的第一个信号。类似与中断嵌套。
案列3:信号和文件的结合
如果当调用文件IO 来读取一个文件的内容,在读取过程中如果发生一个信号,执行完毕信号处理函数,在unix 当中是继续之前没有读完的读操作,在LinuxPOSIX 是重新开始读操作
函数原型 | int kill(pid_t pid, int sig); |
---|---|
功能 | 向进程号为pid中发生信号值为sig的信号 |
参数 | pid : 指定的进程号 pid > 0 sig发送给ID为pid的进程 pid== 0 sig发送给与发送进程同组的所有进程 pid<0 sig发送给组ID为|-pid|的进程,并且发送进程具有向其发送信号的权限 pid== -1 sig发送给发送进程有权限向他们发送信号的系统上的所有进程 sig : 要发送的信号 |
返回值 | 成功: 0 失败:-1 |
与 kill 函数一样,raise 函数也是用来发送信号给进程的,但是它只能发送信号给当前进程,自己给自己发送信号。不能发送给其他进程。
函数原型 | int raise(int sig); |
---|---|
功能 | 给当前进程发送信号 |
参数 | sig :要发送的信号 |
#include <unistd.h>
int pause(void);
功能: 挂起进程
经常 alarm连用定时器会定时时间到之后会结束挂起状态 。
#include <unistd.h>
unsigned int alarm(unsigned int seconds);
功能; 调用此函数会触发 ALARM 信号 定时器
参数:
seconds : 定时时间 单位秒
Sigaction 是新版本内核中出现的函数,在Linux系统中,signal就是使用这个函数实现的。它有三个参数,支持信号传递信息,主要用来与sigqueue()系统调用配合使用,当然,sigaction()同样支持非实时信号的安装。Sigaction()优于signal 主要体现在支持信号带有参数。这两个函数的最大区别在于经过sigaction安装的信号都能传递信息给信号处理函数,而经过signal安装的信号不能向信号处理函数传递信息。.
函数原型 | int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact); |
---|---|
函数功能 | 注册信号处理函数 信号的安装 |
参数 | signum :需要捕捉的信号 Act: 里面包含信号处理函数地址,处理方式等信息。 Oldact: 输出参数,函数调用成功后oldact里面保存以前对signum的处理方式的信息,通常为NULL |
返回值 | 成功:0 失败:-1 |
参数2结构体
struct sigaction
{
void (*sa_handler)(int ); //旧类型的信号处理函数指针
void (*sa_sigaction)(int , siginfo_t * , void * ); //新类型的信号处理函数指针
sigset_t sa_mask; //信号被阻塞的信号集合
int sa_flags; //信号处理方式掩码(SA_SIGINFO)
void (*sa_restorer)(void); //保留,不要使用
};
成员说明:
①、sa_handler 是一个函数指针,旧类型信号处理函数,用于指向原型为void handler(int)的信号处理函数地址,如果用这个成员,则将sa_flags= 0,就等同于signal()函数。
②、sa_sigaction 也是一个函数指针,新类型的信号处理函数用于指向原型为:
void handler(int iSignNum,siginfo_t * pSignInfo,void * pReserved) ;的信号处理函数
函数原型 | void handler(int iSignNum,siginfo_t * pSignInfo,void * pReserved) |
---|---|
函数功能 | 信号处理函数,接受到该信号你做什么 |
参数 | iSignNum:传入的信号 pSignInfo:与该信号相关的一些信息,它是个结构体,定义如下 pReserved:保留,现在没用,通常为NULL |
typedef struct siginfo_t { int si_signo; //信号编号 int si_errno; //如果为非零值则错误代码与之关联 int si_code; //说明进程如何接收信号以及何处收到 pid_t si_pid; //适用于SIGCHLD ,代表被终止进程的PID pid_t si_uid; //适用于SIGCHLD,代表被终止进程所拥有的进程的UID int si_status; //适用于SIGHLD,代表被终止进程的状态 clock_t si_utime; //适用于SIGHLD,代表被终止进程所消耗的用户时间 clock_t si_stime //适用于SIGHLD,代表被终止进程所消耗系统的时间 sigval_t si_value; //存放sigqueue函数传递的额外信息给处理函数 int si_int; //存放sigqueue函数传递的额外信息给处理函数 void *si_ptr; //存放sigqueue 函数传递的额外信息给处理函数 void *si_addr; int si_band; int si_fd; };
③、 sa_handler和sa_sigaction 只应该有一个生效。
如果想采用老的信号处理机制,让sa_handeler指向正确的信号处理函数,并且让字段sa_flags为0;
如果想采用新的信号处理机制,让sa_sigaction 指向正确的信号处理函数,并且让字段sa_flags包含SA_SIGINFO选项。
④、 sa_mask是一个包含信号集合的结构体,该结构体内的信号表示在进行信号处理时,将要被阻塞的信号。需要注意的是,当在执行当前的信号处理程序时,后面再来的信号如果和当前信号相同,同样会被阻塞。
针对sigset_t结构体,有一组专门的函数对它进行处理,它们是:
int sigemptyset(sigset_t * set) | 清空信号集合 set |
---|---|
int sigfillset(sigset_t * set) | 将所有信号填充进 set中 |
int sigaddset(sigset_t * set, int signum) | 往 set 中添加信号 signum |
int sigdelset(sigset_t * set, int signum) | 从 set中移除信号 signum |
int sigismember(const sigset_t * set, int signum) | 判断 signnum 是不是包含在 set 中 |
int sigpending(sigset_t * set) | 将被阻塞的信号集合由参数 set指针返回 |
⑤、 sa_flags字段是一组掩码的合成值,指示信号处理时所应该采取的一些行为
各掩码的含义如表5.1所示:
掩码 | 描述 |
SA_RESETHAND | 处理完毕要捕捉的信号后,将自动撤消信号处理函数的注册,即必须再重新注册信号处理函数,才能继续处理接下来产生的信号。该选项不符合一般的信号处理流程,现已经被废弃。 |
SA_NODEFER | 在处理信号时,如果又发生了其它的信号,则立即进入其它信号的处理,等其它信号处理完毕后,再继续处理当前的信号,即递规地处理。 |
SA_RESTART | 如果在发生信号时,程序正阻塞在某个系统调用,例如调用 read()函数,则在处理完毕信号后,接着从阻塞的系统返回。如果不指定该参数,中断处理完毕之后, read 函数读取失败。 |
SA_SIGINFO | 指示结构体的信号处理函数指针是哪个有效,如果 sa_flags 包含该掩码,则 sa_sigaction 指针有效,否则是 sa_handler 指针有效。(常用) |
旧版信号处理实例:
新版信号处理实例:
函数原型 | int sigqueue(pid_t pid, int sig, const union sigval value); |
---|---|
功能 | 发送信号,并且可以在信号上面附加信息 |
参数 | pid:向哪个进程发送 sig:发送的信号 |
union sigval value | union sigval{ int sival_int; //可以传递int 类型的数据 void *sival_ptr; // 其他类型的数据 }; |
实例:
利用两个陌生进程传递信号,实现通信。(接收到信号以外的数据就算通信成功
实验现象:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。