Linux programming signal (4): signal capturing and sigaction Functions

Source: Internet
Author: User

I. How to capture signals in the kernel

If the signal processing is a user-defined function, this function is called when the signal is delivered. This function is called capture signal. Because the code of the signal processing function is in the user space, the processing process is complicated, for example:
1. the user program registers the sigquit signal processing function sighandler.
2. The main function is being executed. If the main function is interrupted or an exception occurs, it is switched to the kernel state.
3. After the interrupt processing is completed, the signal sigquit delivery is checked before the main function of the user State is returned.
4. after the kernel decides to return the user State, it does not resume the context of the main function, but executes the sighandler function. The sighandler and main functions use different stack spaces. There is no call or call relationship between them, is two independent control processes.
5. After the sighandler function returns, it will automatically execute a special system call sigreturn to enter the kernel state again.
6. If there is no new signal to be delivered, the next return to the user State will restore the context of the main function and continue the execution.

From ulk.


Ii. sigaction Functions

# Include <signal. h>

Int sigaction (INT signo, const struct sigaction * Act, struct sigaction * oact );


The sigaction function can read and modify the processing actions associated with the specified signal. If the call is successful, 0 is returned, and-1 is returned if an error occurs. Signo is the ID of the specified signal. If the act pointer is not empty, modify the processing action of the signal according to act. If the oact pointer is not empty, the original processing action of the signal is sent out through oact. Act and oact point to the sigaction struct: struct sigaction {
Void (* sa_handler) (INT );
Void (* sa_sigaction) (INT, siginfo_t *, void *);
Sigset_t sa_mask;
Int sa_flags;
Void (* sa_restorer) (void );
};


Assign the value of sa_handler to the constant sig_ign and pass it to sigaction to ignore the signal. Assign the value to the constant sig_dfl to execute the default system action. Assign the value to a function pointer to capture the signal using a custom function, or register a signal processing function with the kernel. the return value of this function is void. You can include an int parameter to know the number of the current signal, in this way, you can use the same function to process multiple types of signals. Obviously, this is also a callback function, not called by the main function, but called by the system.
When a signal processing function is called, the kernel automatically adds the current signal to the process's signal shielding word. When the signal processing function returns, the original signal shielding word is automatically restored, this ensures that when processing a signal, if the signal is generated again, it will be blocked until the current processing ends. If you want to automatically shield other signals in addition to the current signal when calling the signal processing function, use the sa_mask field to describe the signals to be blocked, when the signal processing function returns, the original signal shielding characters are automatically restored.


It should be noted that the sa_restorer parameter is no longer needed. sa_handler is mainly used for unreliable signals (Real-time signals are also acceptable, but not information), and sa_sigaction is used for real-time signals with information (siginfo_t ), the two cannot appear at the same time. Sa_flags has several options, including sa_nodefer and sa_siginfo. When sa_nodefer is set, the current signal is not blocked during the execution of the signal processing function; When sa_siginfo is set, it corresponds to sa_sigaction.
In combination, the first parameter of the sa_sigaction function, like sa_handler, represents the number of the current signal. The second parameter is a siginfo_t struct, and the third parameter is generally not used. When sa_handler is used, set sa_flags to 0.


Siginfo_t {
Int si_signo;/* Signal Number */
Int si_errno;/* an errno value */
Int si_code;/* signal code */
Int si_trapno;/* trap number that caused
Hardware-generated signal
(Unused on most ubuntures )*/
Pid_t si_pid;/* Sending process ID */
Uid_t si_uid;/* real User ID of sending process */
Int si_status;/* exit value or signal */
Clock_t si_utime;/* User time consumed */
Clock_t si_stime;/* system time consumed */
Sigval_t si_value;/* signal value */
Int si_int;/* posix.1b signal */
Void * si_ptr;/* posix.1b signal */
Int si_overrun;/* timer overrun count; posix.1b timers */
Int si_timerid;/* timer ID; posix.1b timers */
Void * si_addr;/* memory location which caused fault */
Long si_band;/* band event (was int in
Glibc 2.3.2 and earlier )*/
Int si_fd;/* file descriptor */
Short si_addr_lsb;/* least significant bit of address
(Since kernel 2.6.32 )*/
}


It should be noted that not all Members have definitions in all signals. Some members share the same body. When reading data, you must read the well-defined part of a specific signal.


The following example uses the sigaction function:

C ++ code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
/*************************************** **********************************
> File name: Process _. c
> Author: Simba
> Mail: dameng34@163.com
> Created time: sat 23 Feb 2013 02:34:02 pm CST
**************************************** ********************************/
# Include <sys/types. h>
# Include <sys/STAT. h>
# Include <unistd. h>
# Include <fcntl. h>
# Include <stdio. h>
# Include <stdlib. h>
# Include <errno. h>
# Include <string. h>
# Include <signal. h>

# Define err_exit (m )\
Do {\
Perror (m );\
Exit (exit_failure );\
} While (0)

Void handler (INT sig );

Int main (INT argc, char * argv [])
{
Struct sigaction Act;
Act. sa_handler = handler;
Sigemptyset (& act. sa_mask );
Act. sa_flags = 0;

If (sigaction (SIGINT, & act, null) <0)
Err_exit ("sigaction error ");

For (;;)
Pause ();

Return 0;

}

Void handler (INT sig)
{
Printf ("Rev Sig = % d \ n", sig );
}

Simba @ Ubuntu :~ /Documents/code/linux_programming/apue/signal $./sigaction
^ Crev Sig = 2
^ Crev Sig = 2
^ Crev Sig = 2

...........................

That is to say, pressing CTRL + C will always generate a signal and be processed to print the Recv statement.


In fact, the signal function we mentioned earlier is implemented by calling sigaction, while the bottom layer of the sigaction function is implemented by calling the do_sigaction () function. You can implement a my_signal function by yourself, as shown below:

C ++ code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
/*************************************** **********************************
> File name: Process _. c
> Author: Simba
> Mail: dameng34@163.com
> Created time: sat 23 Feb 2013 02:34:02 pm CST
**************************************** ********************************/
# Include <sys/types. h>
# Include <sys/STAT. h>
# Include <unistd. h>
# Include <fcntl. h>
# Include <stdio. h>
# Include <stdlib. h>
# Include <errno. h>
# Include <string. h>
# Include <signal. h>

# Define err_exit (m )\
Do {\
Perror (m );\
Exit (exit_failure );\
} While (0)

Void handler (INT sig );
/* The system calls signal () and actually calls sigaction ()*/
_ Sighandler_t my_signal (INT Sig, _ sighandler_t handler );

Int main (INT argc, char * argv [])
{
My_signal (SIGINT, Handler );

For (;;)
Pause ();

Return 0;

}

_ Sighandler_t my_signal (INT Sig, _ sighandler_t handler)
{
Struct sigaction Act;
Struct sigaction oldact;
Act. sa_handler = handler;
Sigemptyset (& act. sa_mask );
Act. sa_flags = 0;

If (sigaction (SIG, & act, & oldact) <0)
Return sig_err;

Return oldact. sa_handler; // returns the previous handler pointer.
}

Void handler (INT sig)
{
Printf ("Rev Sig = % d \ n", sig );
}

The output test is the same. Note that the signal function returns the previous handler successfully and the sig_err is returned if the function fails. While sigaction returns the previous Handler through the oact parameter, returns 0 if the handler succeeds, and-1 if the handler fails.


The following is a small example to illustrate the role of sa_mask:

C ++ code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
/*************************************** **********************************
> File name: Process _. c
> Author: Simba
> Mail: dameng34@163.com
> Created time: sat 23 Feb 2013 02:34:02 pm CST
**************************************** ********************************/
# Include <sys/types. h>
# Include <sys/STAT. h>
# Include <unistd. h>
# Include <fcntl. h>
# Include <stdio. h>
# Include <stdlib. h>
# Include <errno. h>
# Include <string. h>
# Include <signal. h>

# Define err_exit (m )\
Do {\
Perror (m );\
Exit (exit_failure );\
} While (0)

Void handler (INT sig );

Int main (INT argc, char * argv [])
{
Struct sigaction Act;
Act. sa_handler = handler;
Sigemptyset (& act. sa_mask );
Sigaddset (& act. sa_mask, sigquit); // The sigquit signal is blocked during signal processing function execution and will arrive
/* Note that the blocked signals in sigprocmask cannot be reached until blocking is removed */
Act. sa_flags = 0;

If (sigaction (SIGINT, & act, null) <0)
Err_exit ("sigaction error ");

For (;;)
Pause ();

Return 0;

}

Void handler (INT sig)
{
Printf ("Rev Sig = % d \ n", sig );
Sleep (5 );
}

Press Ctrl + C and then Ctrl + \ immediately. The program will not be terminated immediately, that is, it will not arrive until the handler completes processing the sigquit signal.

Simba @ Ubuntu :~ /Documents/code/linux_programming/apue/signal $./sa_mask
^ Crev Sig = 2
^ \

After 5s, The quit (core dumped) is output, that is, the signal in the sa_mask set is blocked during the execution of the signal processing function until the operation is completed.


Here is an example of the parameters sa_flags and sa_sigaction.

Reference: apue and Linux C Programming one-stop learning

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.