Linux signal Programming Practice (2) signal sending function and reentrant function

Source: Internet
Author: User
Tags sleep function

Linux signal Programming Practice (2) signal sending function and reentrant function

 

In the early UNIX era, the signal was unreliable. It cannot be said that the signal may be lost, but a signal may occur, but the process may never know this.

Currently, Linux calls unreliable signals before the SIGRTMIN real-time signal. The unreliable signal here is mainly because the signal queue is not supported, that is, when multiple signals occur in the process (when the speed of receiving signals exceeds the processing speed of the process), these unused and processed signals will be lost, only one signal is left.

When multiple signals are sent to the process (when the signal receiving speed exceeds the processing speed), these unused and processed signals will be sent to the process queue. When the process has the opportunity to process it, it will process it in sequence, so that the signal will not be lost.

At the same time, a new version of signal sending and installation has also emerged: the signal sending function sigqueue () and the signal installation function sigaction ().

Both sigaction and signal functions call the kernel service do_signal function. [kernel service function, which cannot be called by applications.

Non-real-time signals do not support queuing and are all unreliable signals. Real-time signals support queuing and are all reliable signals.

APIS for sending signals:

1. kill

 

int kill(pid_t pid, int signo); 

 

Parameters:
Pid: the following four options may be selected:

1. If the pid is greater than zero, the pid indicates the process to be sent.
2. If the pid is equal to zero, the signal is sent to all processes that belong to the same group as the process that calls kill.
3. When the pid is equal to-1, the signal will be sent to all processes whose calling process has the right to send signals to them, except process 1 (init ).
4. When the pid is less than-1, the signal is sent to the process marked by-pid.

Sig: the signal code to be sent. If the value is zero, no signal is sent, but the system will perform an error check. Generally, the sig value is zero to check whether a process is still running.

Return Value Description: 0 is returned when execution is successful. If-1 is returned for failure, errno is set to one of the following values EINVAL: the specified signal code is invalid (the sig parameter is invalid) EPERM; if the permission is insufficient, the signal cannot be sent to the specified process ESRCH: the process or process group specified by the pid parameter does not exist.

 

Void handler (int sig) {printf ("recvv a sig = % d \ n", sig);} int main () {if (signal (SIGUSR1, handler) = SIG_ERR) ERR_EXIT ("signal error! "); Pid_t pid = fork (); if (pid =-1) ERR_EXIT (" fork error! "); Else if (pid = 0) {// equals to killpg (getpgrp (), SIGUSR1); pid = getpgrp (); kill (-pid, SIGUSR1 ); /* kill (getppid (), SIGUSR1); * // The preceding exit (EXIT_SUCCESS) ;}int n = 5; do {n = sleep (n );} while (n> 0); // return 0 ;}

 

Note:

(1) The sleep function will be interrupted by a signal. After the signal processing function is completed, it will not sleep, but will continue the operation after the sleep function is executed. What if we want the program to sleep for a while? The man manual shows that the return value of the sleep function is the remaining number of seconds. Therefore, you can use a loop:

 

while(n=sleep(n));
(2) If the target of sending a signal is a process group, the subprocess fork inherits the signal, and two signal processing occurs.

 

2. raise

 

Raise () sends signals to itself, equivalent to raise (getpid (), sig)

3. killpg

 

Killpg () sends a signal to the process group. killpg (pgrp, sig) equals kill (pgrp, sig)

4. sigqueue

 

int sigqueue(pid_t pid, int sig, const union sigval value); 
Sends signals to processes. It supports queuing and can contain additional information.
5. alarm

 

The alarm function is used to set an alarm time to send the SIGALRM signal (telling the Linux kernel to send the SIGALRM signal after n seconds );
However, the alarm function can send only one signal at a time. Therefore, it must be called recursively to implement the function of sending signals intermittently.

 

Void handler (int sig) {printf ("recvv a sig = % d \ n", sig); alarm (1); // indirect recursion, continuous sending signal} int main () {if (SIGALRM, handler) = SIG_ERR) ERR_EXIT ("signal error! "); Alarm (1); while (1) pause (); return 0 ;}
Reentrant/non-reentrant Functions

It is mainly used in multi-task environments. A reentrant function is simply a function that can be interrupted. That is to say, it can be interrupted at any time during function execution, when the system is transferred to the OS for scheduling and another piece of code is executed, no error will occur when the returned control is returned. The non-reentrant function uses some system resources, such as the global variable area, interrupt vector table, etc. Therefore, if it is interrupted, problems may occur. Such functions cannot run in multi-task environments.

It can also be understood that re-entry means repeated entry. First, it means that this function can be interrupted, second, it means that it does not depend on any environment (including static) except the variables on its own stack. Such a function is a purecode (pure code) reentrant, multiple copies of the function can be allowed to run. Since they use a separate stack, they do not interfere with each other. If you really need to access global variables (including static), be sure to implement mutex. Reentrant functions are very important in parallel runtime environments, but they generally cost some performance for accessing global variables.

When writing reentrant functions, if global variables are used, they should be protected by means of clearance interruption and semaphores (namely, P and V Operations.

Note: If the global variables used are not protected, this function is not reentrant. That is, when multiple processes call this function, it is very likely that the related global variables are changed to an unknown state.

To enhance the stability of the program, the reentrant function should be used in the signal processing function.

The following shows an error that may occur in the signal processing program of the non-reentrant function:

 

ypedef struct{        int a;        int b;        int c;        int d;}TEST;TEST g_data;void handler(int sig){       // printf("recvv a sig =%d\n",sig);        printf("%d %d %d %d\n",g_data.a,g_data.b,g_data.c,g_data.d);        alarm(1);}int main(){        TEST zeros={0,0,0,0};        TEST ones={1,1,1,1};        if(signal(SIGALRM,handler)==SIG_ERR)        ERR_EXIT("signal error!");         g_data=zeros;        alarm(1);        while(1)        {                g_data=zeros;                g_data=ones;        }         return 0;}

, There will be a cross result similar to 0011, because the signal may be interrupted when g_data = ones internally assigns values to a, B, c, and d respectively, some old values have not yet been replaced and an error has occurred. This indicates that the operation is not an atomic operation, but a non-reentrant function. Do not use it in signal processing programs.

 

We can use man 7 signal to view common reentrant functions:



 

Non-reentrant function

Most functions that meet the following conditions cannot be reentrant:

(1) use static data structures, such as getlogin (), gmtime (), getgrgid (), getgrnam (), getpwuid (), and getpwnam;

(2) the malloc () or free () function is called during function implementation;

(3) standard I/O functions are used for implementation.

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.