您的位置:首页 > 运维架构 > Linux

Linux进程通信之信号

2015-06-17 12:11 411 查看
Linux应用程序学习之进程通信之信号
前面我们学习了Linux进程间管道的通信方式,主要是把管道看做文件来进行相应操作,这一章就来了解一些进程间的信号通信方式。

在Linux系统中,信号是一种最为古老的进程间通信机制,在进行进程间通信编程之前,我们首选需要了解一下任意两个进程间是如何进行信号交流的.



由上图可以很清晰的看到两个进程之间信号的交互,无非是一个进程等待另一进程来发送信号,以完成后续的操作。关于信号的选择,我们可以在Linux系统中的/usr/include/asm/signal.h文件中查看,这个文件中定义了Linux系统支持的所有信号,常见的信号有 :

SIGKILL:杀死进程

SIGSTOP:暂停进程

SIGCHLD:子进程停止或者结束时用来通知父进程

下面我们就来看看Linux中信号编程的相关函数,首先是signal函数,其原型如下:

sighandler_t signal(int signum ,sighandler_t handler);
初看到这个函数,我们可能觉得很复杂,主要是其返回值是一个从没见过的类型,其实sighandler_t是一个typedef定义的类型,其定义如下:

typedef void (*sighandler_t)(int);

可见其是一个函数指针,指向一个返回值为void且其只有一个int型参数的函数(有关typedef的用法可到网上查询下)。

这个函数的第一个参数为指定传达的信号,第二个参数也是一个函数指针,这第二个参数总共有三种取法:

(1)SIG_IGN:此时表示忽略掉接收的信号。

(2)SIG_DFL:此时表示接收信号后交给内核来处理。

(3)自定义函数来进行处理。

下面我就通过一个内核向进程发送信号的例子来向大家解释signal函数的用法,在此我用第二个参数的第三种用法,程序代码如下:

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
void func()
{
printf("receive the signal\n");
}

void main(int argc , char*argv[])
{
signal(SIGINT,func);
pause();
}


这个程序的意思是signal函数等待一个SIGINT信号,如果该信号到来,就调用func函数,然后打印出receive the signal,等待函数用的是pause,有关其详细信息可通过man命令来查看。

我们在linux终端中用kill命令来向这个进程发送命令,表示内核与进程的通信,kill命令的用法也可以通过man命令进行查看,下图就是我们先运行这个进程后等待信号的界面。



接下来我们再打开一个linux终端,按下图输入命令之后我们可以看到上面等待进程打印出了消息。



上面的kill命令后面跟的选项可以自己man来进行查询,后面的数字是我们运行程序的进程号,前面我们讲过如何查阅一个进程的进程号,用ps aux命令可以查看linux下所有进程的进程号,一般我们自建的进程都在最后面。

下面我们就来学习任意两个进程之间的信号通信,在此之前我们首先来看看linux中提供的发送信号的函数:kill和raise。kill函数(注意是函数,而不是前面的命令)将信号发送给进程或进程组,而raise函数则允许进程向自身发送信号,其函数原型如下:

int kill(pid_t pid , int signal);
int raise(int signal);
其实调用raise(signal)就等价于调用kill(getpid() , signal);因此在此我们主要介绍一下kill函数的用法,kill的pid参数有4中不同的取值情况:

pid>0 , 将该信号发送给进程ID为pid的进程。

Pid == 0 ,将该信号发送给与发送进程属于同一进程组的所有进程(即这些进程的进程组ID等于发送进程的进程组ID)。

pid < 0 ,将该信号发送给其进程组ID等于pid的绝对值。

Pid == -1 ,将该信号发送给发送进程有权限向它门发送信号的系统上的所有进程。

下面就用一个程序实例来展示kill函数的用法,这里总共有两个程序,前面一个程序我们已经在上面给出,下面我再写一个发送信号的进程,程序代码如下:

#include <stdio.h>
#include <sys/types.h>
#include <signal.h>
#include <stdlib.h>

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


这个程序需要从命令行传入一个参数,为接收信号进程的进程号,程序中的atoi函数为linux提供的将char*转换为int型的函数,下图为程序运行结果。



以上就是本次linux进程间信号通信的一些知识,不全面希望得到大家的指正。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: