linux用信号写代码,linux中l通过自定义信号完成进程间的通信的代码

信号同样是用于进程通信的,他是一种异步通信方式。我们之前的管道不是,明显,读进程要等管道里面有数据才能运行,否则他要等待。信号处理则不同,进程不知道什么时候信号会到来,先看一小段代码,看看信号的程序:

[root@liumengli signal]# cat ./signal_recive1.c

#include "stdio.h"

#include "signal.h"

#include "sys/types.h"

#include "unistd.h"

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

int main(int argc, char**argv) {

struct sigaction act; //创建新的信号

struct sigaction old_act; //用与记录旧的信号,当然你也可以不用记录

int sig; //信号量,将来我们发送的信号要以这个信号量发送

sig = atoi(argv[1]);

sigemptyset(&act.sa_mask);

act.sa_flags = SA_SIGINFO;

act.sa_sigaction = new_op; //设置信号的响应操作

if(sigaction(sig, &act, &old_act) < 0) { //开始创建信号

printf("install sigal error\n");

return 1;

}

while(1) { //为了测试写的一个死循环

sleep(2);

printf("Now we wait for signal\n");

}

}

void new_op(int signum, siginfo_t * info, void * myact) { //信号的响应操作

printf("recive signal %d\n", signum);

exit(1);

}

[root@liumengli signal]# ./signal_recive1 15

(我们以15号信号作为新的信号的信号量,我们即将发送就发送15好给目标进程,注意我们这里是用掉了系统的15号信号,这个信号是可以被从写的,但有2个信号KILL和STOP信号,KILL的信号是9,而STOP是根据硬件结构体系而不同,他们是不能被从写的,原因是,内核代码中在安装信号上有这么一句(act && (sig == SIGKILL || sig == SIGSTOP)))

return -EINVAL;同时他们不能被屏蔽也就是不能被不响应,其它信号是可以屏蔽的。这么做的原因是内核设计者为了给进程控制留下的最后底限,绝大部分信号的默认操作是终止进程,这个2个从名字上也看出一个是终止,另一个是暂停。这样我们对一个进程至少有最后的杀死手段就是向进程发送这2种信号,如何法后面会看到)

Now we wait for signal

Now we wait for signal

Now we wait for signal

Now we wait for signal

.......

另开一个终端

[root@liumengli signal]# ps -le

......

0 S     0 30681 28333  0  75   0 -   352 hrtime pts/2    00:00:00 signal_recive1

0 R     0 30828 28245  0  78   0 -  1368 -      pts/1    00:00:00 ps

[root@liumengli signal]# kill -15 30681

再返回看看被这个进程掌控的终端的反应

Now we wait for signal

recive signal 15

[root@liumengli signal]#

按照我们预期的结束了。

先解释下kill指令,这是发送信号的一个指令,当然我们可以用函数(linux提供了),我们发送了15号信号,按照我们预期的结束了。通常人们认为 kill是杀死一个进程,其实不是,它是发送一个信号给你指定的进程,觉大部分进程不会去改系统的信号量,如果真的改了,他们改不了STOP和KILL这2个信号量,我改过,运行时候报了信号安装失败。如果你杀不死一个流氓进程的时候,不妨试试 kill -KILL目标进程的PID,kill -STOP是个蛮好玩的信号,可以试试,想恢复就发送kill -CONT.另一个,写过linux/unix环境编程的人会清楚知道,就算进程不是就绪状态,发送信号是会将它改成就绪态,这个看下发送信号的源代码就知道了,他会把目标进程挂到就绪队列中。所以睡眠进程也会响应信号。

从我的程序中看出我没有哪儿有代码去检测一个信号是否到来,既用户并不关心信号什么时候会到来,用户关心的是信号来了我该做些什么。那么谁去检测信号是否到来的,换句话说就是:信号检测的代码写在哪里。它写在

217 ret_with_reschedule:

218 cmpl $0,need_resched(%ebx)

219 jne reschedule

220 cmpl $0,sigpending(%ebx)

221 jne signal_return

这段代码的第220行就是检测信号,以前我们看过进程调度,进程调度代码写在218行。这段代码会在任何返回用户空间时候会被执行,包括系统调用返回,中断返回,异常处理返回从睡眠唤醒的时候返回。

如果你的程序一直在用户空间,而且不会受到任何中断(不太可能实现,至少定时的时钟中断会来骚扰下,而且没有系统调用的支持,直接自己去操作一些硬件也不太可能),那么信号是不会被响应的。

从响应的角度来说,不是我发信号,对方就会立即反应,这中间会有延时,这个不难理解了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值