Linux Operating System - Chapter 5 Process Signals

 

 

 

Table of contents

signal concept

Use the kill -l command to view the list of signals defined by the system

An overview of common approaches to signal processing

generate signal

1. Generate a signal through the terminal key

2. Call the system function to signal the process

3. Signals generated by software conditions

4. A hardware exception generates a signal

blocking signal

1. Other common concepts related to signals

2. Representation in the kernel

3. sigset_t

4. Signal set operation function

sigprocmask

sigpending

capture signal

1. How does the kernel implement signal capture

2. sigaction

reentrant function


 



signal concept



Signal is a way of asynchronous notification of events between processes, which belongs to soft interrupt


Use the kill -l command to view the list of signals defined by the system

  • Each signal has a number and a macro definition name, these macro definitions can be found in signal.h, for example, there is a definition #define SIGINT 2
  • Signals numbered above 34 are real-time signals, and this chapter only discusses signals below number 34, not real-time signals. The conditions under which these signals are generated and the default processing actions are detailed in signal(7): man 7 signal 

 



An overview of common approaches to signal processing



There are three optional processing actions:
1. Ignore this signal.
2. Execute the default processing action for the signal.
3. Provide a signal processing function that requires the kernel to switch to user mode to execute the processing function when processing the signal . This method is called catching a signal. 



generate signal




1. Generate a signal through the terminal key



The default processing action of SIGINT is to terminate the process , and the default processing action of SIGQUIT is to terminate the process and Core Dump

When a process is going to terminate abnormally, you can choose to save all the user space memory data of the process to the disk. The file name is usually core, which is called Core Dump. The abnormal termination of the process is usually due to a bug, such as illegal memory access causing a segment fault. You
can use a debugger to check the core file to find out the cause of the error afterwards. This is called Post-mortem Debug (post-mortem debugging). How many core files a process is allowed to generate depends on the Resource Limit of the process (this information is stored in the PCB). By default, the core file is not allowed to be generated,
because the core file may contain sensitive information such as user passwords, which is not safe. You can use the ulimit command to change this limit during the development and debugging phase, allowing core files to be generated. First use the ulimit command to change the Resource Limit of the Shell process, allowing the core file to be up to 1024K: $ ulimit -c 1024


2. Call the system function to signal the process


The kill command is implemented by calling the kill function. The kill function can send a specified signal to a specified process. The raise function can send a specified signal to the current process (send a signal to yourself)

#include <signal.h>
int kill(pid_t pid, int signo);
int raise(int signo);
Both functions return 0 for success and -1 for error.

The abort function causes the current process to receive a signal and terminate abnormally.

#include <stdlib.h>
void abort(void);
Just like the exit function, the abort function will always succeed, so there is no return value. 

3. Signals generated by software conditions



SIGPIPE is a signal generated by a software condition.

#include <unistd.h>
unsigned int alarm(unsigned int seconds);
call the alarm function to set an alarm clock, that is to tell the kernel to send a SIGALRM signal to the current process after seconds seconds, the default processing action of this signal is to terminate the current process

The return value of this function is 0 or the number of seconds remaining from the previously set alarm time. For example, someone wants to take a nap, set the alarm clock to ring after 30 minutes, and is woken up after 20 minutes, and wants to sleep a little longer, so reset the alarm clock to ring after 15 minutes, "previously set The remaining time of the alarm clock time" is 10 minutes. If the value of seconds is 0, it means that the previously set alarm clock is canceled, and the return value of the function is still the remaining seconds of the previously set alarm clock time.


4. A hardware exception generates a signal



A hardware exception is somehow detected by the hardware and notified to the kernel, which then sends the appropriate signal to the current process.

For example, if the current process executes the instruction of dividing by 0, the operation unit of the CPU will generate an exception, and the kernel will interpret this exception as a SIGFPE signal and send it to the process.

Another example is that the current process accesses an illegal memory address, the MMU will generate an exception, and the kernel will interpret this exception as a SIGSEGV signal and send it to the process.




blocking signal




1. Other common concepts related to signals



The actual execution of the signal processing action is called the signal delivery (Delivery) and
the state between the signal generation and the delivery is called the signal pending (Pending).
A process can choose to block (Block) a signal.
When a blocked signal is generated, it will remain in a pending state until the process unblocks the signal before performing the delivery action. Note that
blocking and ignoring are different, as long as the signal is blocked, it will not be delivered, while ignoring Is an optional processing action after delivery.



2. Representation in the kernel



Schematic representation of signals in the kernel

  • Each signal has two flags indicating blocking (block) and pending (pending) , and a function pointer indicating processing actions. When a signal is generated, the kernel sets the pending flag of the signal in the process control block, and the flag is not cleared until the signal is delivered. In the example above, the SIGHUP signal is neither blocked nor generated, and the default processing action is executed when it is delivered.
  • The SIGINT signal has been generated, but is being blocked, so it cannot be delivered temporarily . Although its processing action is to ignore, this signal cannot be ignored before unblocking , because the process still has the opportunity to change the processing action before unblocking.
  • The SIGQUIT signal has never been generated. Once the SIGQUIT signal is generated, it will be blocked, and its processing action is the user-defined function sighandler.
  • What happens if a signal is generated multiple times before the process unblocks it?       
    •  POSIX.1 allows the system to deliver this signal one or more times. Linux is implemented in this way: regular signals are generated multiple times before delivery and only counted once, while real-time signals are generated multiple times before delivery and can be placed in a queue in turn. This chapter does not discuss real-time signals 

3. sigset_t



From the above figure, each signal has only one bit pending flag, which is either 0 or 1, and the number of times the signal has been generated is not recorded, and the blocking flag is also indicated in this way.
Therefore, pending and blocked flags can be stored with the same data type sigset_t, which is called a signal set , and this type can represent the "valid" or "invalid" status of each signal,

The meaning of "valid" and "invalid" in the blocking signal set is whether the signal is blocked,

The meaning of "valid" and "invalid" in the pending signal set is whether the signal is pending.

The blocking signal set is also called the signal mask of the current process (Signal Mask), and the "shielding" here should be understood as blocking rather than ignoring.



4. Signal set operation function



The sigset_t type uses a bit for each signal to represent the "valid" or "invalid" state. As for how to store these bits inside this type, it depends on the system implementation. From the user's point of view, it is not necessary to care. The user can only call the following functions To operate the sigset_t variable, and should not make any interpretation of its internal data, such as printing the sigset_t variable directly with printf is meaningless 

#include <signal.h>
int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigaddset (sigset_t *set, int signo);
int sigdelset(sigset_t *set, int signo);
int sigismember(const sigset_t *set, int signo)

The function sigemptyset initializes the signal set pointed to by set, and clears the corresponding bits of all signals in it, indicating that the signal set does not contain any valid signals.
The function sigfillset initializes the signal set pointed to by set, so that the corresponding bits of all signals in it are set to 1, indicating that the effective signals of this signal set include all signals supported by the system.
Note that before using the variable of type sigset_t, be sure to call sigemptyset or sigfillset for initialization, so that the signal set is in a definite state . After initializing the sigset_t variable, you can call sigaddset and sigdelset to add or delete a valid signal in the signal set

These four functions all return 0 on success and -1 on error. sigismember is a Boolean function used to judge whether a certain signal is included in the effective signals of a signal set
, and return 1 if included, 0 if not included, and -1 if an error occurs.


sigprocmask



Calling the function sigprocmask can read or change the signal mask word of the process (blocking signal set)

#include <signal.h>
int sigprocmask(int how, const sigset_t *set, sigset_t *oset);
return value: 0 if successful, -1 if error

If oset is a non-null pointer, the current signal mask of the read process is passed through the oset parameter.

If set is a non-null pointer, the signal mask word of the process is changed, and the parameter how indicates how to change it.

If both oset and set are non-null pointers, first backup the original signal mask word to oset, and then change the signal mask word according to the set and how parameters. Assuming that the current signal mask word is mask, the following table shows the optional value of the how parameter 

 

 If calling sigprocmask unblocks several currently pending signals, at least one of the signals will be delivered before sigprocmask returns.


sigpending


#include <signal.h>
sigpending (sigset_t *set) The output parameter  
reads the pending signal set of the current process and sends it out through the set parameter. Returns 0 if the call is successful, and -1 if an error occurs. 

 

 



capture signal



1. How does the kernel implement signal capture



If the signal processing action is a user-defined function, this function is called when the signal is delivered, which is called capturing the signal. Since the code of the signal processing function is in the user space, the processing process is more complicated, as follows:

The user program registers the processing function sighandler of the SIGQUIT signal.

The main function is currently being executed, and an interrupt or exception occurs to switch to the kernel mode. After the interrupt processing is completed, the signal SIGQUIT is detected before returning to the main function of the user state.

After the kernel decides to return to the user mode, it does not restore the context of the main function to continue execution, but executes the sighandler function. The sighandler
and main functions use different stack spaces. There is no relationship between calling and being called, and they are two independent control processes. .

After the sighandler function returns, it automatically executes a special system call sigreturn to enter the kernel mode again. If there is no new signal to be delivered, returning to the user mode this time is to restore the context of the main function and continue to execute


2. sigaction


 #include <signal.h>
int sigaction(int signo, const struct sigaction *act, struct sigaction *oact);

 

 Assigning sa_handler to the constant SIG_IGN and passing it to sigaction means ignoring the signal, assigning it to the constant SIG_DFL means executing the default action of the system, assigning it to a function pointer means capturing the signal with a custom function, or registering a signal processing function with the kernel, which returns The value is void, and can take an int parameter, through which the number of the current signal can be known, so that multiple signals can be processed with the same function. Obviously, this is also a callback function, not called by the main function, but by the system.


When a signal processing function is called, the kernel automatically adds the current signal to the signal mask word of the process, and automatically restores the original signal mask word when the signal processing function returns, thus ensuring that when a signal is processed, if this If this signal is generated again, it will be blocked until the current processing ends.

If you want to automatically mask some other signals besides the current signal when calling the signal processing function, use the sa_mask field to indicate these signals that need to be additionally masked , and automatically restore the original signal mask word when the signal processing function returns . The sa_flags field contains some options. The codes in this chapter set sa_flags to 0, and sa_sigaction is the processing function of real-time signals.

 



reentrant function



  • A function is non-reentrant if it meets one of the following conditions:
    • Called malloc or free, because malloc also uses a global linked list to manage the heap.
    • A standard I/O library function was called. Many implementations of the standard I/O library use global data structures in a non-reentrant manner 

The signal is only processed when the receiving process returns from kernel mode to user mode.

 

 

Guess you like

Origin blog.csdn.net/MuqiuWhite/article/details/131235051