进程间通信IPC-信号

信号

信号是进程间通信的一种方式 这种方式并没有传输数据 只是在内核中传了一个信号(整数)
信号的表示是一个整数
不同的信号值 代表不同的含义 当然用户可以自定义信号

信号的本质其实是软中断
信号会中断正在进行的程序 转而去处理中断(处理函数)
处理完中断后 再回来继续执行原有的程序
注意:如果用户没有显式地处理信号 系统收到信号默认地处理方式大多是终止进程

查看信号可以在终端上输入

man 7 signal 

几个常用的信号:


	
		Signal     Value     Action   Comment
       ──────────────────────────────────────────────────────────────────────
       
       SIGINT        2       Term    Interrupt from keyboard 
									 从键盘上收到了中断信号 按下ctrl+c就会产生这个信号 
									 
       SIGQUIT       3       Core    Quit from keyboard
								     默认的处理是输出信息然后终止进程 按下ctrl+\就会产生这个信号
									 
     
       SIGFPE        8       Core    Floating-point exception
									 浮点数运算异常的时候 产生SIGFPE信号 
									 
       SIGKILL       9       Term    Kill signal  
									 杀死进程 不可被捕获和忽略
	   SIGSTOP   17,19,23    Stop    Stop process	
									 停止进程 不可被捕获和忽略 
									 
       SIGSEGV      11       Core    Invalid memory reference
									 非法内存引用时 就会收到SIGSEGV信号 
									 比如段错误 一旦产生段错误 进程收到SIGSEGV信号 此时输出信号 
									 然后终止进程
	   
       SIGPIPE      13       Term    Broken pipe: write to pipe with no
                                     readers; see pipe(7)
									 当你往一个管道写数据时 没有读端进程就会产生SIGPIPE信号
									 
       SIGALRM      14       Term    Timer signal from alarm(2)
									 定时信号 在进程调用alarm时 会在超时的时候 就会产生SIGALRM信号
	         
       SIGUSR1   30,10,16    Term    User-defined signal 1
       SIGUSR2   31,12,17    Term    User-defined signal 2
	   
       SIGCHLD   20,17,18    Ign     Child stopped or terminated
									 当子进程停止或终止的时候 父进程就会收到该信号 
									 父进程收到这个信号并不会怎么样 因此信号的默认行为是忽略
      

linux下信号相关的API函数
1.发送信号kill

NAME
			   kill - send signal to a process

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

			   int kill(pid_t pid, int sig);

			函数功能: kill用来把一个信号发送到一个指定的进程或多个进程 
					   kill不仅仅是一个函数 也是一条指令
					   
			头文件:如上 
			
			参数列表: 
					pid : 指定信号的接收者(可能是多个进程 )
						
						pid > 0  pid表示指定的那一个要发送的进程
						
						pid = 0  发送信号给 与调用进程同组的所有进程 
						
						pid = -1 发送信号给系统所有进程(有权限发送的所有进程)
						
						pid < -1 发送信号给组id等于pid绝对值的所有进程 
						
					sig: 你要发送的信号  参考上面的宏
						
			返回值: 
					成功(至少有一个进程成功接收到信号)返回0 
					失败返回-1 并且errno被设置
  1. raise
NAME
				   raise - send a signal to the caller

			SYNOPSIS
				   #include <signal.h>

				   int raise(int sig);

			
			函数功能: 发送一个信号给自己 
			
					
				raise(sig)==kill( getpid(), sig)
  1. alarm
NAME
				   alarm - set an alarm clock for delivery of a signal
													
			SYNOPSIS
				   #include <unistd.h>

				   unsigned int alarm(unsigned int seconds);

				函数功能: alarm定时发送一个闹钟(SIGALRM)信号给本进程
						
						"闹钟":每个进程都有属于自己的一个“闹钟” “闹钟”时间到了 进程就会收到 
								一个SIGALRM信号 但是同一时刻只有一个“闹钟”生效 
								
				头文件:如上 
				
				参数列表: 
						
						seconds: 多少秒后 发送一个“闹钟信号”
								  如果为0 代表取消上一个“闹钟”
								  
				返回值: 
						返回上一个闹钟的剩余秒数 

4.捕捉信号 改变信号地处理方式

NAME
				   signal - ANSI C signal handling

			SYNOPSIS
				   #include <signal.h>

				   typedef void (*sighandler_t)(int);
				   
					sighandler_t是一个函数指针类型 它可以用来定义函数指针变量 
					这个变量指向一个无返回值 并带有一个int类型参数地函数

				   sighandler_t signal(int signum, sighandler_t handler);

			函数功能: 捕捉对应地信号 使其按照指定地方式去处理 
			参数列表:
						signum: 你要捕捉哪个信号  要捕捉地那个信号地信号值 
						
						handler: 信号的处理方式  一般有如下三种: 
								  a.自定义的函数
									这个函数为无返回值 但是带一个int的参数(用来保存收到的那个信号的信号值)的函数
									
									大概格式: 
									void my_signal_handle(int sig)
									{
    
    
										//用户自定义处理
									}
										
								  b.SIG_IGN    忽略该信号
								  
								  c.SIG_DFL    default 采用操作系统默认的处理方式 
			
						返回值: 
					成功返回信号的上一次的处理方式 
					失败 返回SIG_ERR 同时errno被设置

5.pause

NAME
				   pause - wait for signal

			SYNOPSIS
				   #include <unistd.h>

				   int pause(void);
				   
				   
				让进程停在那里 等待某个信号的到来。直到收到信号
				
				返回值: 
						当一个信号被捕捉 且信号处理函数返回后返回 这种情况下返回-1

实现pause

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

void mysign(int sign)
{
    
    
	if(sign==SIGCHLD)
	{
    
    
		printf("child is die!\n");

	}


}

int main()
{
    
    

	signal(SIGCHLD,mysign);
	pid_t pid=fork();
	if(pid ==-1)
	{
    
    
		perror("fork error\n");
		exit(1);
	}
	else if(pid ==0)
	{
    
    
		sleep(2);
		printf("I am child!\n");
		return 0;
	}
	else if(pid >0)
	{
    
    
		int ret=pause();
		printf("ret==%d\n",ret);
		wait(NULL); //回收子进程
		printf("my name is father process!\n");
	}

	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_46836491/article/details/126813909
今日推荐