Linux process signal

Table of contents

1. Process signal

1. The concept of signal

2. Signal generation

2.1 Hardware generation (press the key on the keyboard):

2.2 Software generated:

1. kill function

2. raise function:     

 3. kill- [num] [pid] can send a signal to the process

 3. Types of signals

kill -l can list signals

4. Signal processing method

 5. Registration of signals

5.1 Understanding of basic concepts:

5.2 Registration of Signals:

5.3 The difference between real-time signal and non-real-time signal when registering:

6. Unify the understanding of signals

7. Cancellation of signal:

7.1 Deregistration of unreliable signals

7.2 Deregistration of reliable signals

8. Custom processing of signals

8.1 Concept:

8.2 Functions

8.3 The principle of the two functions in the kernel:

Interlude the processing of the process kernel code 

9. Signal capture process

10. Signal blocking

10.1 Characteristics of signal blocking:

10.2 Interface:

11. Cooperate with the signal to solve the zombie process:

 12. volatile keyword:


1. Process signal

1. The concept of signal

signal is a software interrupt

"Example of daughter-in-law crossing the road" in daily life

Daughter-in-law's call to eat is just a signal to tell you to eat, but it is not mandatory

1.1 just tells that there is such a signal, but how to deal with this signal and when to deal with it is determined by the process, so it is a soft interrupt

2. Signal generation

2.1 Hardware generation (press the key on the keyboard):

  • ctrl+c : No. 2 signal SIGINT, pressing ctrl+c actually means that the process has received the No. 2 signal, and the No. 2 signal causes the process to exit.

  • ctrl+z : No. 20 signal SIGTSTP,

    ctrl+|: No. 3 signal SIGQUIT

The kill -l command can view the signal values ​​​​defined by the operating system and the names corresponding to the signals

 So what are these signals for?

We can see that the default action of SIGINT is term termination

 

 Signals can also be sent through the kill command

 

2.2 Software generated:

1. kill function

int kill(pid_t pid,int sig);

  • parameter:
    • pid_t: To send to that process, fill in the pid of that process
    • sig: the signal to send to the process

Use: We can send a No. 2 signal to the current process, and then run it to see the result

                            

Run it:

                         

 found that the process terminated

2. raise function:     

  • Role: Who calls and who sends the signal
  • Parameters: The signal value to send the signal to the calling process
  • Use: Send yourself a No. 2 signal to terminate the process

Our code executes raise(2) in this process

 One run: We found that the process also terminated after the raise call

                  

 3. kill- [num] [pid] can send a signal to the process

              

 We can see that the process is suspended

 3. Types of signals

kill -l can list signals

  • Non-real-time signal (non-reliable signal):
    • Feature: signal may be lost (1-31)
  • Live signal (reliable signal):
    • Features: Signal will not be lost (33-64)

4. Signal processing method

How the operating system handles signals (man 7 signal

    term   core  cont   ign   stop

  • Default processing method:
    • SIG_DFL, the processing method of the number signal has been defined in the operating system
    • For example signal number 2 -> terminate the process
    • 11->Terminate the process and generate a core dump file

Ignore the processing method:

  • SIG_ IGN, the signal is ignored ( zombie process )
  • After the process receives the signal of ignoring the processing method, it does not process it, such as the generation of the zombie process learned before:
    •  The child process exits before the parent process, and the child process will send a SIGCHLD signal to the parent process when it exits, but the parent process ignores the processing of this signal, resulting in the parent process not recycling the exit status information of the child process, Thus the child process becomes a zombie process

  • Custom processing:
    • The programmer can change the signal processing method, define a function, and when the process receives the signal, call the function written by the programmer himself. (The 7th dot involves)

 5. Registration of signals

5.1 Understanding of basic concepts:

  • A process receives a signal, this process is called registration
  • The registration and deregistration of signals are not a process, but two independent processes

 Understanding of the signal registration bitmap in the kernel and the sigqueue queue

  • They are all inside the task_struct structure
  • Each process has its own unique registration bitmap and sigqueue queue

5.2 Registration of Signals:

  • Change the bitmap to 1, add the Sigqueue node to the sigqueue queue
  • When the signal is registered, the bit corresponding to the signal will be changed from 0 to 1, indicating that the current process has received the signal.
  • You also need to add a sigqueue node to the sigqueue queue. The queue is essentially a doubly linked list in the operating system kernel (the first-in-first-out feature

The registration process is roughly as follows:

  • 5.3 The difference between real-time signal and non-real-time signal when registering:

  • Registration of non-real-time signals (non-reliable signals)
    • The first registration: modify the sig bitmap (0-1), modify the sigqueue queue.
    • The second registration: the signal of the same signal value, on the premise that the previous signal has not been processed: modify the sig bitmap (1->1), and will not add the sigqueue node.
    • Summary: Add again, no sigqueue node will be added
  • Registration of Live Signals (Reliable Signals)
    • The first registration: modify the sig bitmap (0-1), modify the sigqueue queue.
    • The second registration: the signal of the same signal value: modify the sig bitmap (1->1), add the sigqueue node to the sigqueue queue.
    • Add it again, the siquque node will be added again

The reason why non-real-time signals are prone to signal loss is that the sigqueue node will not be added when registering again

6. Unify the understanding of signals

It is divided into three parts: before receiving the signal, receiving the signal, and processing the signal

7. Cancellation of signal:

  • 7.1 Deregistration of unreliable signals

    • 1. Set the bit position in the s ig bitmap corresponding to the signal to 0 (1-0)
    • 2. Dequeue the sigqueue node of the corresponding signal
  • 7.2 Deregistration of reliable signals

    • 1. Dequeue the sigqueue node of the corresponding signal
    • 2. Determine whether there are S igqueue nodes with the same signal in the s igqueue queue
      • If there is: the bit remains unchanged
      • If not: then bit change bit 0

8. Custom processing of signals

  • 8.1 Concept:

  • The custom processing method is to let the programmer define the processing method of a certain signal. For example, our No. 2 signal is a termination command. We can define it by ourselves to let him do other things, such as printing a sentence.

8.2 Functions

  • 1.sighandler_t signal (int signum, sighandler_t handler);

  • Function :
  • When calling the signal function, we pass the address of a callback function to the second parameter of the function. When we receive the signal value defined by the first parameter, the callback function will be called to execute the function of the callback function.
  • Parameters :
  • signum: signal value
  • handler: Change which function to handle, accept a function address, function pointer (callback function).
  • typedef void (*sighandler_ t)(int);
  • Code verification :
  • Let's write a code to test what happens when the process receives signal No. 2 to see if the process is terminated

 After knowing the custom processing method of the signal, we have a bold idea:

Consider the following piece of code:

 

 So, isn't my process "invulnerable"?

Let's see what happens next

 When other signals are killed, it doesn't work. Only signal No. 9 works. Why?

Because the No. 9 signal is a strong killing signal, it cannot be customized , (otherwise it would be the same as a cancer cell ...)

 3.int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact)

 For this function, we can also write code to verify:

 We can find that this function can have the same effect as the signal function

 We can also use this function to perform coquettish operations

Let's look at the following code:

 

 In this code, we actually made two changes to signal No. 2, let's execute this code:

8.3 The principle of the two functions in the kernel:

structure in the kernel

Interlude the processing of the process kernel code 

First we need to know the location of the process kernel code

 Once we know the location, we can find

 After vim sched.h, we entered the interface

 So how to better find the definition of each structure and where it is used?

We can create an index relationship for the source code through ctags

9. Signal capture process

  • When our process switches from kernel mode to user mode, do_signal is called to check whether the process has received a signal.

A process is registered with a signal by the operating system, and the process processes this signal only when it switches from user space to kernel space.

Call the dosignal function to judge whether the process has received a signal, and process it if there is one. When the processing is completed, the signal must be canceled from the process.

After logging out, return to the user state to continue executing his code. It is also possible that the process will be terminated directly when the signal is processed.

10. Signal blocking

  • 10.1 Characteristics of signal blocking:

  • The registration of a signal is a signal registration, and the signal blocking is a signal blocking. The blocking of the signal does not interfere with the registration of the signal, but means that after the process receives the signal, it does not process the signal temporarily due to blocking.

  • 10.2 Interface:

  • int sigprocmask (int how, const sigset_ t *Set, sigset_ t *oldset); (cannot block signals 9 and 19)

parameter:

  • how: what do you want sigp rocmask to do
    • SIG_ BLOCK: Set a signal to block
    • SIG_ UNBL.OCK : Set a signal as non-blocking state
    • SIG_SETMASK : Use the second parameter "set" to replace the original barrier bitmap. (meaning to replace)
  • set : newly set blocking bitmap
  • Compute a new blocking bitmap based on the function variables passed in:
    • 1. Block a single signal, block multiple signals (just set the corresponding signal bitmap to 1)
    • 2. Touch to block a single signal/unblock multiple signals.
  • oldset : the original old blocking bitmap

Principle analysis:

  • When how is SIG_ _BLOCK, the function will calculate a new blocking bitmap according to the set, the way is:
  • block(new) = block(old) | set; The new block bitmap and the old block bitmap are bitwise ORed.

  • When how is SIG_ _UNBLOCK, the function will calculate a new blocking bitmap according to the set, the way is:
  • block(new) = block(old) & (^ 'set); first invert the incoming new bitmap, and then perform a bitwise AND operation with the old bitmap

  • When how is SIG_SETMASK, the function will calculate a new blocking bitmap according to set in the following way:
  • block (new) = set;

Test code:

We call the sigprocmask function and want to set the bit position corresponding to signal No. 2 in the set bitmap to 1

In order to implement the code, we must first know some functions of set

 

 At this time, the blocking setting is indeed verified, but it is not verified that the blocking does not affect the registration of the signal, so the code needs to be modified again

Now let's verify that blocking does not affect the registration of signals, and reliable signals will not lose signals, and unreliable signals will lose signals

Ideas:

 code:

 Let's run it and observe the result:

 It can be seen that reliable signals will not be lost, but unreliable signals can be lost

11. Cooperate with the signal to solve the zombie process:

Before we solve the zombie process, we can only call the wait function or the waitpid function, but there is a problem when calling these two functions, that is, when calling,

Either the parent process is always blocked waiting for the child process to exit, or it has to be used in conjunction with the non-blocking state of loop and waitpid.

Our parent process can't do anything. Here we can use signals to recycle the child process.

Let's look at this code

 Let's run the code:

 We can see that the signal can be received and the parent process is released from wait

 12. volatile keyword:

  • effect:
  • Guaranteed memory visibility
  • The data to be calculated by the CPU is obtained from the memory every time, and the program optimized at compile time (obtained from the registers) is rejected. The compilation options of gcc/gt+ "-00, 01, -02, -03, the optimization level is getting more and more High. (Understanding the higher the optimization level, the faster the program may execute) The higher the optimization level, the greater the possibility of taking values ​​​​from registers

Let's write a code to experiment

 

We run and find that press ctrl+c to input signal No. 2 to the process, and the process ends directly. This is because we did not optimize the program when compiling , and it is taken from the memory at this time.

 

 We optimize to O3 level

 At this time, we press Ctrl again, and we can find that there is no exit, indicating that the value is not taken from the memory, but directly from the register.

But when we give another volatile keyword, even if we optimize it, we still get the value from the memory

 

Guess you like

Origin blog.csdn.net/flyingcloud6/article/details/127585663