进程与进程间通信(3)

时间:2022-10-12 19:02:37

信号

信号(signal),又称为软中断信号,用来通知进程发生了异步事件。进程之间可以互相发送软中断信号。内核也可以因为内部事件而给进程发送信号,通知进程发生了某个事件。注意,信号只是用来通知进程发生了什么事件,并不给该进程传递任何数据。处理方法分为三类:

1是类似中断的处理程序,对于需要处理的信号,进程可以指定处理函数,由该函数来处理;

2是忽略某个信号,对该信号不做任何处理,就像未发生过一样;

3是对该信号的处理保留系统的默认值,这种缺省操作,对大部分的信号的缺省操作是使得进程终止。

1. sigaction 函数

Linux 系统为大部分信号定义了缺省处理方法,当信号的缺省处理方法不满足需求时,可通过 sigaction()函数进行改变。 sigaction()函数的原型如下:

#include <signal.h>

int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact);

sigaction()函数成功返回 0,否则返回-1。

参数 signum 指出需要改变处理方法的信号,如 SIGINT 信号,但SIGKILL 和 SIGSTOP这两个信号是不可捕捉的。

参数 act 和 oldact 是一个 sigaction 结构体的指针,act 为要设置的对信号的新处理方式,而 oldact 为原来对信号的处理方式。

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 是一个函数指针, 用来指定信号发生时调用的信号处理函数;

 sa_sigaction 则是另一个信号处理函数,它有三个参数,可以获得关于信号的更详

细的信息,当 sa_flags成员的值包含了SA_SIGINFO标志时,系统将使用 sa_sigaction

函数作为信号处理函数,否则使用 sa_handler 作为信号处理函数;

 sa_mask 成员用来指定在信号处理函数执行期间需要被屏蔽的信号,特别是当某个信号被处理时,它自身会被自动放入进程的信号掩码,因此在信号处理函数执行期间这个信号不会再度发生。可以使用 sigemptyset()、 sigaddset()、 sigdelset()分别对这个信号集进行清空、增加屏蔽信号、删除屏蔽信号等操作;

 sa_flags 成员用于指定信号处理的行为,它可以是以下值的“按位或”组合:

 SA_RESTART:使被信号打断的系统调用自动重新发起;

 SA_NOCLDSTOP:使父进程在它的子进程暂停或继续运行时不会收到SIGCHLD 信号;

 SA_NOCLDWAIT:使父进程在它的子进程退出时不会收到 SIGCHLD 信号,这时子进程如果退出也不会成为僵尸进程;

 SA_NODEFER:使对信号的屏蔽无效,即在信号处理函数执行期间仍能发出这个信号;

 SA_RESETHAND:信号处理之后重新设置为默认的处理方式;

 SA_SIGINFO:使用 sa_sigaction 成员而不是 sa_handler 作为信号处理函数。

re_restorer 成员则是一个已经废弃的数据域,不要使用。

 

2. kill 函数

int kill(pid_t pid, int sig);

kill()函数成功返回 0,否则返回-1。参数 pid 为发送 sig 信号的进程 PID,参数 sig 为发送的信号。