linux多进程通讯---signal 信号机制

基本概念

•又叫:软中断信号,是一种异步通信的IPC
•类似于硬件中断,可以将一个事件以信号形式通知给进程
•给一个指定进程发送一个信号
–信号只是告诉进程发生了什么事,并不传递数据
–进程表的表项中有一个软中断信号域,有信号发给该进程,对应位置位
–进程根据接收信号类型作相应的处理

信号的来源

•来自shell终端用户输入的各种信号:ctrl + C/D
•来自其它进程或者进程本身发送的信号
•来自系统内部的信号
–硬件异常:如SIGBUS表示总线错误、SIGSEGV表示段错误
–终端相关的信号
–软件事件相关的信号

进程对信号的处理方式

–缺省行为
•忽略信号:如SIGIGN、SIGCHLD
–SIGKILL/SIGSTOP比较特殊,不能忽略,所有进程都要在OS管控之下
•终止进程:SIGTERM、SIGINT、SIGHUP
•终止进程并内核转储:SIGBUS、SIGABRT、SIGQUIT
–捕获信号并执行信号注册的handler
•通过signal系统调用可以改变信号的处理行为,即注册新的handler
•当有信号到来时,信号的处理类似于中断程序
•暂停当前进程正在执行的代码、跳到注册的回调函数handler执行
•函数返回,回到当前进程捕获信号的地方继续执行
•若该信号没有注册回调函数,采用默认操作:忽略或终止进程

信号相关API

•typedef void (*sighandler_t)(int);
•sighandler_t signal (int signum, sighandler_t handler);
•int kill (pid_t pid, int sig);
–通过signal注册信号处理函数
–进程之间通过kill发送软中断信号
–内核也可以因内部异常等事件给进程发信号

系统调用signal

•函数原型:sighandler_t signal (int signum, sighandler_t handler);
•函数功能:注册一个信号处理函数
•函数参数
–signum:信号值,定义在:asm/signal.h 头文件中,很多信号跟体系相关
–handler:信号对应的处理函数
–Linux支持的信号列表

系统调用:kill

•函数原型:int kill (pid_t pid, int sig);
•函数功能:给指定进程发送一个信号

系统调用:pause

•函数原型:int pause (void);
•函数功能:将当前进程挂起睡眠,等待某一个信号,直到信号到来,恢复运行
•返回值:该函数总是返回-1

系统调用:alarm

•函数原型:unsigned int alarm(unsigned int seconds);
•函数功能:给当前进程在指定的seconds秒后发送一次SIGALRM信号

系统调用:setitimer

•int getitimer (int which, struct itimerval *curr_value);
•int setitimer (int which, const struct itimerval *new_value,
struct itimerval *old_value);
•函数功能:获取定时器状态、设置定时器,周期发送信号
•函数参数:which,指定三个内部定时器中的一个
–ITIMER_REAL:按实际时间计时,计时到达给进程发送SIGALRM信号
–ITIMER_VIRTUAL:当进程执行时才计时,到期后发送SIGVTALRM信号
–ITIMER_PROF:当进程执行或系统为该进程执行动作时都计时,如统计进程在用户态和内核态所花的时间,到期后发送SIGPROF信号给进程

函数示例

pause

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

void signal_handler (int unused)
{
	printf ("catch a signal SIGINT\n");
}

int main (void)
{
	signal (SIGINT, signal_handler);
	pause();
	printf ("main exit...\n");
	return 0;
}

setitimer

#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/time.h>


void signal_handler (int signum)
{
	switch (signum)
	{
		case SIGALRM:
			printf ("catch a signal: SIGALRM\n");
			break;
		case SIGVTALRM:
			printf ("catch a signal: SIGVTALRM\n");
			break;
	}
	return;
}

int main (void)
{
	struct itimerval value,old_value, value2;
	printf ("process id: %d\n", getpid());
	signal (SIGALRM, signal_handler);
	signal (SIGVTALRM, signal_handler);

	value.it_value.tv_sec = 5;
	value.it_value.tv_usec = 0;
	value.it_interval.tv_sec = 1;
	value.it_interval.tv_usec = 0;
	setitimer (ITIMER_REAL, &value, &old_value);

	value2.it_value.tv_sec = 10;
	value2.it_value.tv_usec = 0;
	value2.it_interval.tv_sec = 1;
	value2.it_interval.tv_usec = 0;
	setitimer (ITIMER_VIRTUAL, &value2, &old_value);
	while (1)
    {
       // for(;;);
       sleep (5);
    }
	return 0;
}

signal

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


void handler (int signo)
{
	switch (signo)
	{
		case 1:
			printf ("get a SIGUP signal: %d\n", signo);
			break;
		case 2:
			printf ("get a SIGINT signal: %d\n", signo);
			break;
		case 3:
			printf ("get a SIGQUIT signal: %d\n", signo);
			break;
	}
}


int main (void)
{
	signal (SIGHUP, handler);
	signal (SIGINT, handler);
	signal (SIGQUIT, handler);

	pause ();
	//while (1);

	return 0;
}

alarm

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

void signal_handler (int unused)
{
	printf ("catch a signal SIGALRM\n");
}

int main (void)
{
	signal (SIGALRM, signal_handler);
	alarm (5);
	pause ();
	//sleep (3);
	//alarm (3);
	printf ("main exit\n");
	return 0;
}

kill

#include <signal.h>
#include <unistd.h>
#include <stdio.h>
int main (void)
{
	while (1)
	{
		kill (7118, SIGHUP);
		sleep (2);
	}
	return 0;
}


#include <stdio.h>
int main (void)
{
    while (1);
    return 0;
}
发布了349 篇原创文章 · 获赞 6 · 访问量 9742

猜你喜欢

转载自blog.csdn.net/qq_23929673/article/details/100174077