进程间通信-信号

进程间通信有很多种方式,常见的有管道,消息队列,信号量,共享内存,还有信号,这篇文章主要结合实列简单介绍信号函数的使用,以及有哪些常用的信号类型

常用的信号类型有以下几种:

SIGTERM:可以捕捉,默认执行操作是终止程序,终端执行kill 或者 kill -15发送该信号

SIGKILL:不可以捕捉,默认执行操作是终止程序,终端执行kill -9 发送该信号

SIGALRM:定时器超时信号

SIGUSR1,SIGUSR2:用户定义信号

SIGCHLD:子进程退出时发送给发进程的信号

当某个信号出现时,可以告诉内核按下面的3种方式之一进行处理

1. 忽略该信号,大多数信号都可以使用这种方式进行处理,但是SIGKILL和SIGSTOP这两种信号不可以忽略

2. 捕捉信号,这个是通知内核在某种信号产生时,调用一个用户函数,在用户函数中,可执行用户希望对这种事件进行处理

3. 执行系统默认动作,系统对每种信号都有一个默认动作,需要注意的是对大多数信号,系统的默认动作是终止该进程

下面介绍下一个UNIX系统信号机制最简单的接口signal 函数

原型如下

#include <signal.h>

typedef void (*sighandler_t)(int);

sighandler_t signal(int signum, sighandler_t handler);

下面简单演示下该接口的使用,让signal捕捉两个用户定义的信号并打印信号编号

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>

static void sig_usr(int signo)
{
	if (SIGUSR1 == signo)
	{
		printf("received SIGUSR1\n");
		exit(0);
	}
	else if (SIGUSR2 == signo)
	{
		printf("received SIGUSR2\n");
		exit(0);
	}
	else
	{
		printf("received signal %d\n", signo);
	}
}
int main(void)
{
	if (signal(SIGUSR1, sig_usr) == SIG_ERR)
	{
		printf("can't catch SIGUSR1\n");
	}
	if (signal(SIGUSR2, sig_usr) == SIG_ERR)
	{
		printf("can't catch SIGUSR2\n");
	}
	
	for(; ;)
	{
		sleep(2);
	}
	return 0;
}

结果如下:

mcchen-virtual-machine:/home/mywork/test/signal$ ./signal  & //在后台启动进程
[1] 5472                   //作业控制shell打印作业编号和进程ID
mcchen-virtual-machine:/home/mywork/test/signal$ kill -USR1 5472 //向该进程发送SIGUSR1
received SIGUSR1
mcchen-virtual-machine:/home/mywork/test/signal$ kill -USR2 5472 //向该进程发送SIGUSR2
received SIGUSR2
mcchen-virtual-machine:/home/mywork/test/signal$ kill 5472  //向该进程发送SIGTERM
[1]+  Terminated              ./signal

/*由于程序并没有捕捉SIGTERM信号,而对该信号的系统默认动作是终止,所以当向该进程发送SIGTERM信号后,该进程就终止*/

SIGKILL和SIGSTOP两个信号捕捉不了,下面通过实例演示下

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>

static void sig_usr(int signo)
{
	if (SIGUSR1 == signo)
	{
		printf("received SIGUSR1\n");
	
	}
	else if (SIGUSR2 == signo)
	{
		printf("received SIGUSR2\n");
	}
	else
	{
		printf("received signal %d\n", signo);
	}
}

int main(void)
{
	if (signal(SIGKILL, sig_usr) == SIG_ERR)
	{
		printf("can't catch SIGKILL\n");
	}
	if (signal(SIGSTOP, sig_usr) == SIG_ERR)
	{
		printf("can't catch SIGSTOP\n");
	}

	for(; ;)
	{
		sleep(2);
	}

	return 0;
}

结果如下

mcchen@mcchen-virtual-machine:/home/mywork/test/signal$ 
can't catch SIGKILL  //捕捉不了SIGKILL
can't catch SIGSTOP  //捕捉不了SIGSTOP

总结下,这篇文章简单介绍了signal的使用,以及信号的种类,以及SIGKILL和SIGSTOP两个信号不可以忽略或捕捉,其它信号可以忽略捕捉,默认是终止进程,后面有时间会详细介绍signal衍生的其它接口,谢谢。

发布了33 篇原创文章 · 获赞 7 · 访问量 8342

猜你喜欢

转载自blog.csdn.net/muchong123/article/details/103330406