Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to use pause function in Linux

2025-03-31 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Servers >

Share

Shulou(Shulou.com)06/01 Report--

This article mainly shows you "how to use the pause function in Linux", the content is easy to understand, clear, hope to help you solve your doubts, the following let the editor lead you to study and learn "how to use the pause function in Linux" this article.

# # pause function

Function prototype:

Int pause (void)

Function function:

When a process calls the pause function, it will cause the process to actively suspend (be in a blocking state and actively abandon CPU) and wait for the signal to wake it up.

Return value:

We know that there are three ways of signal processing: 1. Default action; 2. Ignore the treatment; 3. Capture. When the process receives a signal, it processes the response signal before waking up the pause function. So there are the following situations:

If the default processing action of the signal is to terminate the process, the process will be terminated, that is, the process will be terminated as soon as it receives the signal, and the pause function has no chance to return at all.

If the default processing action of the signal is ignore, the process will directly ignore the signal, which means that the signal has not been received, the process continues to be suspended, and the pause function does not return

If the signal processing action is captured, after the process has called the signal processing function, pause returns-1 errno set to EINTR, which means "interrupted by the signal".

The signal received by the pause cannot be blocked, and if it is blocked, the pause cannot be awakened.

Because the alarm function can send the SIGALRM signal after the set time, and the pause function can suspend the process and wait for the signal, you can write a sleep function by combining the two functions, as follows:

# include # include # include void sig_alrm (int signo) {/ * nothing to do * /} unsigned int mysleep (unsigned int nsecs) {unsigned int unslept; signal (SIGALRM, & sig_alrm); unslept = alarm (nsecs); pause (); return unslept;} int main (void) {while (1) {mysleep (2); printf ("Two seconds passed\ n") } return 0;}

# # leading example of time Series Race

Before we talk about the specific phenomena of sequential racing, let's take a look at a common scene in life:

I wanted to take a 10-minute nap, so I set a 10-minute alarm clock in the hope that the alarm clock would wake me up 10 minutes later.

Normal situation: set the alarm clock, take a nap, and wake yourself up after 10 minutes

Abnormal situation: set the alarm clock, lie down and sleep for 2 minutes, be awakened by classmates to play ball, and come back to sleep after 20 minutes. But during the game, the alarm clock has already gone off and will not wake yourself up again.

This example bears great resemblance to the sequential racing that we will talk about later.

# # Analysis of timing race

Let's go back to the mysleep program written above. This function may be the following timing:

The default action of SIGALRM is to terminate the process, so we need to capture it and register the signal handling function with SIGALRM.

Call the alarm (1) function for 1 second

The alarm (1) call ends and the timer starts timing. Just then, the process loses CPU and waits for CPU in a ready state (equivalent to being woken up by a classmate to play ball). The way to lose CPU may be that the kernel dispatches a higher priority process to replace the current process, making it impossible for the current process to obtain CPU

We know that if the alarm function uses natural timing, the timer will be timed all the time, regardless of the process state. So, 1 second later, the alarm clock is timed, and the kernel sends a SIGALRM signal to the current process. The high priority process has not been completed, the current process is still unable to get CPU, continues to be in a ready state, and the signal cannot be processed (pending)

After the execution of the high priority process, the current process gets the CPU resources, and the kernel schedules back to the current process for execution. The SIGALRM signal is delivered and processed by the process

After the signal processing is finished, return to the current main control flow and call the pause () function to suspend the SIGALRM signal waiting for the alarm function to send to wake yourself up.

But the actual SIGALRM signal has been processed, and the pause () function will never wait.

# # solving the problem of timing race

Through the above timing analysis, we can see that the reason for the timing race is that the SIGALRM signal has been sent when the process loses CPU. To prevent this from happening, we can block the signal, "catch" it, and then immediately call the pause function to suspend the wait when unblocking. In this way, even if you lose the CPU when you call alarm, you can "release" the captured SIGALRM signal when the process regains the CPU, and wake up the subsequent pause function.

However, it is still possible to lose CPU between unblocking and pause waiting for a hang signal, unless these two steps are made into an "atomic operation". The sigsuspend function provided by the Linux system has this function. Therefore, in the case of strict timing requirements, we should use the sigsuspend function instead of the pause function.

Function prototype:

Int sigsuspend (const sigset_t * mask)

Function function: suspend waiting signal

Function parameter: mask, the input parameter, during the call of the sigsuspend function, the process signal mask word is specified by the parameter mask.

Specific usage: you can delete a signal (such as SIGALRM) from the temporary signal mask word mask, that is, unblock the signal when calling the sigsuspend function, and then suspend waiting for the signal. But we have changed the signal mask word of the process at this time, so after calling the sigsuspend function, we should restore the signal mask word of the process to its original state.

# include # include # include void sig_alrm (int signo) {/ * nothing to do * /} unsigned int mysleep (unsigned int nsecs) {struct sigaction newact, oldact; sigset_t newmask, oldmask, suspmask; unsigned int unslept; / / 1. Set the capture function for SIGALRM, an empty function newact.sa_handler = sig_alrm; sigemptyset (& newact.sa_mask); newact.sa_flags = 0; sigaction (SIGALRM, & newact, & oldact); / / 2. Set blocking signal set, blocking SIGALRM signal sigemptyset (& newmask); sigaddset (& newmask, SIGALRM); sigprocmask (SIG_BLOCK, & newmask, & oldmask); / / signal mask word mask / / 3. Timing n seconds, when the SIGALRM signal alarm (nsecs) can be generated; / * 4. Construct a temporary blocking signal set that calls sigsuspend, * unblock SIGALRM in the temporary blocking signal set * / suspmask = oldmask; sigdelset (& suspmask, SIGALRM) / * during the 5.sigsuspend call, replace the original blocking signal set with temporary blocking signal set suspmask * this signal set does not contain SIGALRM signals, while waiting, * when sigsuspend is awakened and returned by the signal, restore the original blocking signal set * / sigsuspend (& suspmask); unslept = alarm (0); / / 6. Restore the original processing action of SIGALRM, echoing the previous note 1 sigaction (SIGALRM, & oldact, NULL); / / 7. Unblock SIGALRM, echoing previous notes 2 sigprocmask (SIG_SETMASK, & oldmask, NULL); return (unslept);} int main (void) {while (1) {mysleep (2); printf ("Two seconds passed\ n");} return 0;}

# # reentrant function / non-reentrant function

When a function is called before the end of the call, the function is called repeatedly because of a certain timing, which is called "reentry". If you return from the signal processor, continue to execute the normal instruction sequence at the breakpoint of the process, and the environment on which the function depends remains unchanged during the process from recovery to breakpoint re-execution, that is to say, the function is reentrant, otherwise it is non-reentrant.

If you want to make a function into a reentrant function, the function cannot contain global variables and static variables, nor can you use malloc or free.

The above is all the contents of the article "how to use the pause function in Linux". Thank you for reading! I believe we all have a certain understanding, hope to share the content to help you, if you want to learn more knowledge, welcome to follow the industry information channel!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Servers

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report