进程间通信方式--信号

信号(sginal)


信号的定义


信号是linux系统响应某些条件而产生的一个事件,接收到信号的进程会采取相应的措施。通常喜好是因为一个错误产生的。也可以作为进程间通信的一种方式,由一个进程发送给另一个进程。信号的产生叫做生成,接收叫做捕获。
信号的本质


信号是在软件层次上对中断机制的一种模拟,一个进程接收到信号和处理器收到一个中断请求是一样的。
信号是进程间通信机制中唯一的异步通信,进程不需要等待信号的到达,进程也不知道信号到达的时间。
信号的来源
信号的来源主要有两种:
1.硬件来源(按下键盘按键);
2.软件来源,包括kill,raise,alarm等函数;

信号可以直接进行用户空间进程和内核空间进程之间的交互,内核空间的进程可以通过信号来通知用户空间一些系统事件。
如果一个进程没有处在执行态,信号就存放在内核空间中,直到该进程恢复执行。
信号的产生


1.按下终端键
2.硬件异常
3.软件异常
4.调用kill()函数
5.运行kill命令

Linux所支持的信号


信号名含义默认操作
SIGHUP终端挂起或者控制进程终止终止进程
SIGINT键盘中断(如break键被按下)终止进程
SIGQUIT键盘的退出键被按下终止进程并进行内核映像转储(dump core)
SIGILL非法指令终止进程并进行内核映像转储(dump core)
SIGABRT由abort(3)发出的退出指令终止进程并进行内核映像转储(dump core)
SIGFPE浮点异常终止进程并进行内核映像转储(dump core)
SIGKILLKill信号终止进程,信号不能被捕获,不能被忽略
SIGSEGV无效的内存引用终止进程并进行内核映像转储(dump core)
SIGPIPE管道破裂: 写一个没有读端口的管道终止进程
SIGALRM由alarm(2)发出的信号终止进程
SIGTERM终止信号终止进程
SIGUSR1用户自定义信号1终止进程
SIGUSR2用户自定义信号2终止进程
SIGCHLD子进程结束信号忽略信号
SIGCONT进程继续(曾被停止的进程)
SIGSTOP终止进程停止进程,信号不能被捕获,不能被忽略
SIGTSTP控制终端(tty)上按下停止键停止进程
SIGTTIN后台进程企图从控制终端读停止进程
SIGTTOU后台进程企图从控制终端写停止进程

信号的发送


发送信号的函数有:kill()、raise()、sigqueue()、alarm()、setitimer()、abort()。

kill-发送信号给指定进程


函数原型

#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int signo);

参数

  • pid:指定发送信号的接收线程,getpid(),表示向自身发信号,等价于raise
  • signo:信号的大小signum

参数pid

参数pid的值接收信号的进程
pid>0进程ID为pid的进程
pid=0同一个进程组中的进程
pid<0 pid!=-1进程组ID为-pid的所有进程
pid=-1除发送进程外,所有进程ID大于1的进程

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

Kill()最常用于pid>0时的信号发送,调用成功返回 0; 否则,返回 -1。


下面程序,完成了父进程和子进程交替输出5次,然后父进程发送信号终止子进程,父进程继续循环输出。

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

int main(int argc, char *argv[])
{
	pid_t pid;
	
	int i = 0;
	
	//创建进程
	pid = fork();
	
	//出错
	if(pid < 0){
		printf("fork process failed!\n");
		exit(1);
	}else if(pid == 0){
		//子进程
		while(1){
			printf("I am child process ,my pid is: %d\n", getpid());
			sleep(3);
		}
	}else{
		//父进程
		while(1){
			printf("I am parent process ,my pid is: %d\n", getpid());
			sleep(3);
			i++;
			if(i == 2){
				kill(pid, SIGINT);
			}
		}
	}
	return 0;
}

在这里插入图片描述
raise-向自己发送信号


向进程本身发送信号,参数为即将发送的信号值。
调用成功返回0;否则,返回-1.
函数原型

#include <signal.h>
int raise(int signo);

下面的程序,进程通过raise向自身发送了一个SIGINT信号。


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

int main(int argc, char *argv[])
{
	int i = 0;
	
	while(1){
		i++;
		if(i ==3){
			printf("I will raise a SIGINT to myself!\n");
			//发送SIGINT给进程自身
			raise(SIGINT);
		}
		//进程正常运行
		printf("I am running!\n");
		sleep(1);
	}
	return 0;
}

在这里插入图片描述
alarm-设置信号传送闹铃

#include <unistd.h>
unsigned int alarm(unsigned int seconds);

专门为SIGALRM信号而设,在指定的时间seconds秒后,将向进程本身发送SIGALRM信号,又称为闹钟时间。

进程调用alarm后,任何以前的alarm()调用都将无效。如果参数seconds为零,那么进程内将不再包含任何闹钟时间。

返回值,如果调用alarm()前,进程中已经设置了闹钟时间,则返回上一个闹钟时间的剩余时间,否则返回0。

abort–终止进程


#include <stdlib.h> 
void abort(void);

向进程发送SIGABORT信号,默认情况下进程会异常退出,当然可定义自己的信号处理函数。即使SIGABORT被进程设置为阻塞信号,调用abort()后,SIGABORT仍然能被进程接收。该函数无返回值。

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


int main(void)
{
    printf("Calling abort()\n");
    abort();

    /* The next code will never reach... */
    printf("after abort...\n");

    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值