Linux signal is used to notify the process of the occurrence of a specific event or to let the process execute a specific processing function; signal is an ancient communication mechanism in the Unix family; the signal can come from the terminal keyboard Character input, such as SIGINIT triggered by control-C, can also come from exceptions related to hardware or software, such as SIGSEGV triggered by an application accessing an invalid address, SIGALARM triggered by timer expiration, etc.
#The operating environment of this tutorial: linux5.9.8 system, Dell G3 computer.
What is linux signal used for?
Signal processing mechanism in Linux
Signal is an ancient communication mechanism in the Unix family. It is mainly used to notify the process of the occurrence of a specific event, or to allow A process performs a specific processing function. It is said to be ancient because it has existed in the first generation of Unix systems.
The signal can come from the keyboard character input of the terminal, such as SIGINIT triggered by control-C; it can also come from hardware or software related Abnormalities, such as SIGSEGV (segmentation fault) triggered by an application accessing an invalid address, SIGALARM triggered by a timer expiration, etc. These signals are sent to the process by the kernel.
The signals received by the process can also come from other processes. But not all processes can send signals to any other process. Only super users with root permissions can do this. For ordinary user processes, they can only send signals to processes belonging to the same user.
Can the process send signals to the kernel? It is possible, but the kernel thread will not respond, and it will be useless unless... you modify the kernel code.
Usually signals are considered an asynchronous mechanism, but in Linux code, the following signals caused by exceptions are also called "synchronous":
#define SYNCHRONOUS_MASK \ (sigmask(SIGSEGV) | sigmask(SIGBUS) | sigmask(SIGILL) | \ sigmask(SIGTRAP) | sigmask(SIGFPE) | sigmask(SIGSYS))
Here we call the process that receives the signal the "target process". The traditional signal sending function is kill(). This name looks scary, and it feels like the target process is about to be "killed". In fact, although all signals are sent using kill(), only a small part of the processes actually need to be "killed". Of course, there is now sigqueue() with more powerful functions and a friendlier name.
Let’s take a look at the function prototypes of the two:
int kill(pid_t pid, int sig);int sigqueue(pid_t pid, int sig, const union sigval value);
pid represents the PID of the target process. The PIDs of processes in Linux are all positive numbers. If the value of the parameter pid is 0 or a negative number, is it illegal? No, in fact, 0 and negative numbers have other uses here. There is a concept of process group in Linux, which represents a collection of processes of a type. In kill(), if the parameter pid is "0", it means that the signal is sent to all processes in the process group where the current process is located. If it is less than "-1", the signal is sent to the process group numbered -pid.
__kill_pgrp_info(sig, info, pid ? find_vpid(-pid) : task_pgrp(current));
pid of "-1" means sending it to all processes except the Init process and itself, or all processes with a pid greater than 1 except itself.
for_each_process(p) { if (task_pid_vnr(p) > 1 && !same_thread_group(p, current)) ...
If the pid here is the process's own PID, then the process sends a signal to itself. For this purpose, Linux also provides a simpler interface: the raise() function.
kill(getpid(), sig) --> raise(sig)
It should be noted that in sigqueue(), you cannot send a signal to the entire process group by setting the value of the parameter pid to a negative number.
sig represents the number of the signal to be sent. The signal number in Linux starts from 1. What will happen if the value of the parameter sig is 0? The 0 here also has a magical effect. When sig is "0", it does not actually send a signal to the target process (or process group), but is used to detect whether the target process (or process group) exists.
As for the third parameter added by sigqueue, its definition is as follows:
union sigval { int sival_int; void __user *sival_ptr;};
传统的信号是没有传递消息的功能的,sigval算是稍微扩展了一下信号的通信能力。比如,通信双方可以事先约定某些事件为特定的int值,这个"sival_int"就可以用来保存具体的int值,目标进程可以据此来区分不同的事件,做出不同的响应。当然,这种方法传递的消息内容受限,且不易扩展,因而不适合用作常规的通信手段。
就算是进程之间发送信号,那也是要经过内核的,可以理解成是被内核“截获”了吧。
由于内核态和用户态的切换操作在不同的硬件体系架构上是不同的,而且有一些信号,比如SIGCHLD和SIGSTOP,其实现也是和架构相关的,所以Linux中signal机制的很多代码都是放在架构相关的目录下的,比如"/arch/arm/kernel/signal.c"。
一个信号的相关信息在内核中用siginfo_t结构体表示:
siginfo_t{ int si_signo; int si_sicode; union __sifields _sifields; ...}
内核在截获到一个进程发送的信号后,会首先做一系列的检查,比如该信号的值是否合法啦,进程有没有发送这个信号的权限啦。如果检查通过,就调用copy_from_user()将该信号的相关信息复制到siginfo_t结构体中。
相关推荐:《Linux视频教程》
The above is the detailed content of What is linux signal used for?. For more information, please follow other related articles on the PHP Chinese website!