linux进程号函数,Linux进程间通信——信号集函数

我们已经知道,我们可以通过信号来终止进程,也可以通过信号来在进程间进行通信,程序也可以通过指定信号的关联处理函数来改变信号的默认处理方式,那么我们应该如何设定我们需要处理的信号,我们不需要处理哪些信号呢?信号集函数就是帮助我们解决这些问题的。

有关Linux进程间使用信号通信的更多内容,可以参阅我的另一篇文章——Linux进程间通信——使用信号

例如,Linux有一个健壮的信号编程接口,用于关联指定信号和处理函数,它就是sigaction函数,它的定义为:

#include

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

该函数用于设置与信号sig关联的动作,而oact如果不是空指针的话,就用它来保存原先对该信号的动作的位置,act则用于设置指定信号的动作。

sigaction结构体定义在signal.h中,但是它至少包括以下成员:

void (*) (int) sa_handler;处理函数指针,相当于signal函数的func参数。

sigset_t sa_mask; 信号屏蔽字,指当前被阻塞的一组信号,它们不能被当前进程接收到

int sa_flags;信号处理修改器;

有关sigaction函数的更详细介绍请查阅本人的上一篇文章——

而信号集函数就可以对sigaction结构中的成员sa_mask参数进行设置,下面的例子中,都会用到这个函数,所以在这里先作一点介绍。

1、int sigemptyset(sigset_t *set);

该函数的作用是将信号集初始化为空。

2、int sigfillset(sigset_t *set);

该函数的作用是把信号集初始化包含所有已定义的信号。

3、int sigaddset(sigset_t *set, int signo);

该函数的作用是把信号signo添加到信号集set中,成功时返回0,失败时返回-1。

4、int sigdelset(sigset_t *set, int signo);

该函数的作用是把信号signo从信号集set中删除,成功时返回0,失败时返回-1.

*例子

说明这里先给出一个例子,用来消化一下上面的内容,下面就用这些函数来写一个例子,文件名为signal5.c,代码如下:

#include

#include

#include

#include

#include

static int type = 0;

void handler(int sig)

{

type = sig;

}

int main()

{

struct sigaction act;

//设置sigaction结构

act.sa_handler = handler;

//构建一个空的屏蔽信号集

sigemptyset(&act.sa_mask);

act.sa_flags = 0;

sigaction(SIGINT, &act, 0);

printf("Wait the signal SIGINT...\n");

//挂起进程

pause();

printf("\nReceive the signal SIGINT...\n");

//使act变为默认行为

act.sa_handler = SIG_DFL;

sigemptyset(&act.sa_mask);

//屏蔽信号SIGINT

sigaddset(&act.sa_mask, SIGINT);

act.sa_flags = 0;

sigaction(SIGQUIT, &act, 0);

printf("Wait the signal SIGINT...\n");

sleep(10);

printf("\nIgnore the signal SIGINT!\n");

//解除信号SIGINT的屏蔽

sigdelset(&act.sa_mask, SIGINT);

sigaction(SIGQUIT, &act, 0);

printf("Wait the signal SiGINT...\n");

//挂起进程

pause();

exit(0);

}

运行结果如下:

A031649712-29245.png

第一个ctrl+c(产生SIGINT信号,正常情况下,会使进程结束)没有使进程,是因为为sigaction函数改变了这一信号的默认处理方式,使之关联到函数handler的处理上。第二个ctrl+c(要快一点,在10秒内按下)没有使进程终止是因为函数sigaddset把信号SIGINT加到sigaction结构的sa_mask中去,使进程屏蔽了SIGINT信号,所以进程还是没有被终止。然后函数sigdelset把sa_mask信号集中的SIGINT信号去除,进程就不再屏蔽SIGINT信号,所以进程被终止了。

注意在sigaction中指定的处理的信号不能包括在sa_mask(即信号屏蔽集)中。此外,本人试过,不能屏蔽SIGQUIT,如大家有成功的,还望赐教。

5、int sigismember(sigset_t *set, int signo);

该函数的作用是判断给定的信号signo是否是信号集中的一个成员,如果是返回1,如果不是,返回0,如果给定的信号无效,返回-1;

6、int sigpromask(int how, const sigset_t *set, sigset_t *oset);

该函数可以根据参数指定的方法修改进程的信号屏蔽字。新的信号屏蔽字由参数set(非空)指定,而原先的信号屏蔽字将保存在oset(非空)中。如果set为空,则how没有意义,但此时调用该函数,如果oset不为空,则把当前信号屏蔽字保存到oset中。

how的不同取值及操作如下所示:

A031651962-29246.png_small.png

如果sigpromask成功完成返回0,如果how取值无效返回-1,并设置errno为EINVAL。

7、int sigpending(sigset_t *set);

该函数的作用是将被阻塞的信号中停留在待处理状态的一组信号写到参数set指向的信号集中,成功调用返回0,否则返回-1,并设置errno表明错误原因。

8、int sigsuspend(const sigset_t *sigmask);

该函数通过将进程的屏蔽字替换为由参数sigmask给出的信号集,然后挂起进程的执行。程序将在信号处理函数执行完毕后继续执行。如果接收到信号终止了程序,sigsuspend就不会返回,如果接收到的信号没有终止程序,sigsuspend就返回-1,并将errno设置为EINTR。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值