Linux基础----信号

信号

信号是软件对中断的一个模拟,进程根据接收的信号进行相应的响应。

1. 信号的产生

信号可能由硬件产生,也可能由软件产生,由硬件产生一般包含以下几种情况:

  • 执行了非法的指令
  • 访问了非法的内存
  • 驱动程序报错

由软件产生一般可以以下几种情况来产生:

  • 终端当中:
    • CTRL C 中断信号
    • CTRL | 退出信号
    • CTRL z 停止信号
  • kill 命令:使用kill命令能够使用发送对应的信号给某个进程
  • 在程序中带哦用kill()函数的方式来完成信号的处理
    在这里插入图片描述

2. 常用的信号

信号名信号编号产生原因默认处理方式
SIGHUP1关闭终端终止
SIGINT2ctrl+c终止
SIGQUIT3ctrl+\终止+转储
SIGABRT6abort()终止+转储
SIGPE8算术错误终止
SIGKILL9kill -9 pid终止,不可捕获/忽略
SIGUSR110自定义忽略
SIGSEGV11段错误终止+转储
SIGUSR212自定义忽略
SIGALRM14alarm()终止
SIGTERM15kill pid终止
SIGCHLD17(子)状态变化忽略
SIGTOP19ctrl+z暂停,不可捕获/忽略

3. 信号的处理函数

当需要向外发送信号或者进程接收到信号的时候,需要对这个信号进行正确地响应才可以,在这里需要了解几个常用的函数,来设置信号及其响应。

3.1 signal 函数

signal()函数主要用于捕获信号,并且可以更改进程中对信号的默认行为。
比如,当进程接收到CTRL+C这个信号之后,默认的处理方式是终止程序的运行。但是,如果我们使用了signal函数来捕获这个信号,并且对这个信号的响应进行修改的话,那么可也完成非默认的操作。

signal函数的使用:
typedef void (*sighandler_t)(int);

sighandler_t signal(int signum, sighandler_t handler);

signum:是准备捕获或者忽略的信号
handler:是处理函数或者系统支持的两个宏:

  • SIG_IGN:忽略该信号
  • SIG_DFL:采用系统默认的方式来处理信号
  • 使用自定义的处理函数

使用一个简单的例子,来说明signal函数的作用

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <wait.h>
#include <sys/wait.h>
#include <string.h>
#include <errno.h>

void signal_handler(int sig)
{
	printf("The signal number is %d\r\n", sig);

	if(sig == SIGINT)
	{
		printf("The handler has received the SIGINT signal!!!\r\n");
		printf("The handler will be set to the default\r\n");
		signal(SIGINT, SIG_DFL);
	}
}


int main(void)
{
	printf("This is the signal test demo\r\n");

	/*Set the signal handler response to SIGNINT*/
	signal(SIGINT, signal_handler);

	while (1)
	{
		printf("Waiting for CTRL+C......\r\n");
		sleep(3);
	}	
}

该代码完成的就是更改signal函数对SIGINT这个信号的处理函数,第一次接收到这个信号的时候,会去打印一个信息,然后会在回调函数里面将处理函数更改为默认的处理函数。
当第二次接收到SIGINT函数的时候,就会退出这个程序。
在这里插入图片描述

3.2 kill函数

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

int kill(pid_t pid, int sig);

kill函数的参数有两个,

  • pid指的是信号的接收进程的ID号。
  • sig指的是向进程发送的信号
    返回值:
  • 0:发送成功
  • -1:发送失败
    kill函数的使用方法和在shell里面直接使用kill命令是类似的,比如我们在shell里面执行一个sleep命令,然后使用kill能够将这个进程发送命令使其停止。
    在这里插入图片描述

3.3 raise函数

raise函数和kill函数类似,不过raise函数只能由进程自生发送信号给自己。其函数原型如下:

int raise(int sig);
kill和rasie函数举例
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <wait.h>
#include <sys/wait.h>
#include <string.h>
#include <errno.h>

int main(void)
{
	/*Create a new process*/
	pid_t pid = fork();

	if (pid == 0)
	{
		/*show child process*/
		printf("This is clid process pid is %d\r\n",getpid());

		/*Raise signal, Interrupt child process*/
		raise(SIGSTOP);

		/*This will never print*/
		printf("exit child process\r\n");
		
		exit(0);
	}

	else if (pid > 0)
	{
		sleep(3);

		/* kill child process*/
		if (kill(pid, SIGKILL) == 0)
		{
			printf("parent process kill pid %d\r\n", pid);
		}

		/*wait for child process wxit*/
		wait(NULL);

		exit(0);
	}
}

在上面的例子当中,子进程当中在raise函数之后的内容不会被打印。因为子进程在raise函数中,中断了自己。子进程的退出,是依靠父进程中使用kill命令来杀死这个子进程的。

参考

i.MX6ULL开发板资料

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值