进程间通信(四)—— 信号

参考:《UNIX环境高级编程》

1、信号的概念:
信号是软件中断。很多比较重要的应用程序都需处理信号。信号提供了一种处理异步事件的方法。
每个信号都有一个名字,这些名字都以三个字符SIG开头;
2、信号处理流程
1)选择信号;
2)发送信号;
3)处理信号:忽略信号;交给内核处理;用户自定义处理方法;


3、信号类型:
Linux系统支持的所有信号均定义在 /usr/include/asm/signal.h(展示),其中常见的信号有:

SIGINT:当用户按中断键(一般是DELETE或Ctrl+C)时,终端驱动程序产生此信号并送至前台进程组中的每一个进程。当一个进程在运行时失控,特别是它正在屏幕上产生大量不需要的输出时,常用此信号终止它;
SIGKILL:杀死进程;
SIGSTOP:暂停进程;
SIGHOLD:子进程停止或结束时用来通知父进程;

4、发送信号kill
函数原型:
int kill(pid_t pid, int sig);

函数功能:
该系统调用可以用来向任何进程或进程组发送任何信号。参数pid的值为信号的接收进程

头文件
#include <sys/types.h>
#include <signal.h>

返回值:
成功返回0,失败返回-1;
该调用执行成功时,返回值为0;错误时,返回-1,并设置相应的错误代码errno。下面是一些可能返回的错误代码:
EINVAL:指定的信号sig无效。
ESRCH:参数pid指定的进程或进程组不存在。注意,在进程表项中存在的进程,可能是一个还没有被wait收回,但已经终止执行的僵尸进程。
EPERM:进程没有权力将这个信号发送到指定接收信号的进程。因为,一个进程被允许将信号发送到进程pid时,必须拥有root权力,或者是发出调用的进程的UID 或EUID与指定接收的进程的UID或保存用户ID(savedset-user-ID)相同。如果参数pid小于-1,即该信号发送给一个组,则该错误表示组中有成员进程不能接收该信号。

参数说明:
1)pid
pid>0 进程ID为pid的进程
pid=0 同一个进程组的进程
pid<0 pid!=-1 进程组ID为 -pid的所有进程
pid=-1 除发送进程自身外,所有进程ID大于1的进程

2)sig:指明要发送的信号;
sig是信号值,当为0时(即空信号),实际不发送任何信号,但照常进行错误检查,因此,可用于检查目标进程是否存在,以及当前进程是否具有向目标发送信号的权限(root权限的进程可以向任何进程发送信号,非root权限的进程只能向属于同一个session或者同一个用户的进程发送信号)。

5、处理信号signal
函数原型:
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);

函数功能:
设置信号的处理方式;

头文件
#include <signal.h>

返回值:
成功返回处理函数的指针,失败返回SIG_ERR;

参数说明:
signum:指明要处理的信号;
handler:对应信号的处理方式,取值如下
SIG_IGN:忽略信号;
SIG_DFL:交给内核来处理,按照linux默认的方式进行处理;
用户自定义函数:用户自定义处理方式;

6、代码
/*
B进程
1)设置进程处理方式;
2)等待信号(pause()函数的功能是使调用进程挂起,直至捕捉到一个信号);
*/
#include <signal.h>
#include <unistd.h>
#include <stdio.h>

/* 自定义信号处理函数 */
void myfunc(int a)
{
    printf("Process B received SIGINT\n");
    
}

void main()
{
    signal(SIGINT, myfunc);
    
    pause();

}

/*
A进程:
发送信号给B进程;
*/
#include <sys/types.h>
#include <signal.h>
#include <stdio.h>

void main(int argc, char *argv[])
{
    pid_t pid;
    
    pid = atoi(argv[1]);
    kill(pid, SIGINT);

}

发送命令验证:
1)在终端1中,输入./bprocess命令运行bprocess进程;
2)新开一个终端2,输入ps -aux | grep bprocess命令找到bprocess进程的进程号9083;
3)终端2中输入kill -n SIGINT B进程号,如kill -n SIGINT 9083;
4)在终端1中查看bprocess进程打印信息;
test$ ./bprocess 
Process B received SIGINT
test$ 

运行aprocess进程验证:
1)在终端1中,输入./bprocess命令运行bprocess进程;
2)新开一个终端2,输入ps -aux | grep bprocess命令找到bprocess进程的进程号9127;
3)终端2中输入./aprocess 9127;
4)在终端1中查看bprocess进程打印信息;
test$ ./bprocess 
Process B received SIGINT
test$ 


 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
进程信号的处理过程:(1)在目的进程中安装该信号,即设置如果目标进程捕获该信号时执行的操作代码。Linux采用sigal和sgation系统调用来完成。因信号是异步事件的典型应用,产生信号进程而言是随机出现的,因此,进程不能预先知道信号会不会发送到当前进程,也不能预先知道信号什么时候发送到当前进程,因此只能在信号到来前告诉内核“在此信号发生时,请执行下列操作”,即所谓的安装信号。 (2)信号被某个进程产生,同时设置此信号的目标进程(一般为目标进程的pid),然后由操作系统管理。Linux采用kill()、arise()、alarm()等系统调用来实现。 (3)信号在目的进程被注册。操作系统将信号添加到目的进程的PCB相关的数据结构中。在每个进程的PCB (task_struct结构)中有一个未决信号的数据成员。 (3)信号进程中的注销。进程在执行信号相应处理函数之前,首先要把信号进程中注销。如果存在未决信号等待处理且该信号没有被进程屏蔽,则在运行相应的信号处理函数前,进程会把信号在未决信号链中占有的结构卸掉。 (5)信号生命终止。进程注销信号后,目的进程根据当前进程对此信号设置的处理方式,暂时终止当前代码的执行,保护上下文,转而执行信号处理函数,即捕获该信号,执行完成后再恢复到被中断的位置继续执行。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值