English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
During the process of program development, we often need to use some timers, usually if the time accuracy requirement is not high, we can use sleep, uslepp functions to make the process sleep for a period of time to implement timing,
The former unit is second (s), and the latter is microsecond (us); but sometimes we don't want the process to be blocked in sleep, we need the process to execute normally, and then perform the corresponding operation when the specified time arrives,
Under Linux, we generally use the alarm function and setitimer function to implement timing functions;
The following is a detailed analysis of these two functions:
(1) alarm function
alarm is also known as the alarm function, which can set a timer in the process. When the timer reaches the specified time, it sends a SIGALRM signal to the process;
The prototype of the alarm function is as follows:
unsigned int alarm(unsigned int seconds); //seconds: Specify the number of seconds
Required header file
#include<unistd.h>
Function prototype
unsigned int alarm(unsigned int seconds)
Function parameters
seconds: Specify the number of seconds
Function return value
Success: If the process has already set the alarm time before calling this alarm(), it returns the remaining time of the last alarm time, otherwise it returns 0.
Error:-1
Below is a simple example of the alarm() function:
void sigalrm_fn(int sig) { printf("alarm!\n"); alarm(2); return; } int main(void) { signal(SIGALRM, sigalrm_fn); //The following function must have an int parameter alarm(1); while(1) pause(); }
(2) setitimer() function
Under Linux, if the timing requirement is not very precise, alarm() and signal() can be used. However, if a higher precision timing function needs to be implemented, the setitimer function must be used.
setitimer() is an API for Linux, not part of the C language Standard Library. setitimer() has two functions: one is to specify a function to be executed after a certain period of time, and the other is to execute a function at regular intervals;
Linux schedules3An internal timer:
ITIMER_REAL: A real-time timer, regardless of the mode in which the process is running (even if the process is suspended), it always counts. When the timer reaches, a SIGALRM signal is sent to the process.
ITIMER_VIRTUAL: This is not a real-time timer. It calculates the process execution time when the process is in user mode (i.e., when the program is executing). After the timer reaches, a SIGVTALRM signal is sent to the process.
ITIMER_PROF: The process counts in user mode (i.e., when the program is executing) and kernel mode (i.e., when the process is scheduled). The timer reaches and generates a SIGPROF signal. The time recorded by ITIMER_PROF is longer than ITIMER_VIRTUAL by the time spent on process scheduling.
When the timer is initialized, it is assigned an initial value, which decreases over time, and emits a signal when it decreases to 0, while also restoring the initial value. In the task, we can use one or all three types of timers, but only one timer of the same type can be used at the same time.
The prototype of the setitimer function is as follows:
#include <sys/time.h> int setitimer(int which, const struct itimerval *new_value, struct itimerval *old_value); Timer values are defined by the following structures: struct itimerval { struct timeval it_interval; /* next value */ struct timeval it_value; /* current value */ }; struct timeval { time_t tv_sec; /* seconds */ suseconds_t tv_usec; /* microseconds */ };
it_interval is used to specify how often the task is executed, and it_value is used to save how much time is left until the task is executed. For example, if you specify it_interval as2seconds (microseconds are 0), at the beginning, we also set the it_value time to2seconds (microseconds are 0), when a second has passed, it_value decreases by one to1, and then after1seconds, then it_value decreases again1, becomes 0 at this time, a signal is emitted (telling the user that the time is up and the task can be executed), and the system automatically resets the it_value to the it_interval value, that is2seconds, and then re-count
Here is a simple example of setitimer:
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <signal.h> #include <sys/time.h> void test_func() { static count = 0; printf("count is %d\n", count++); } void init_sigaction() { struct sigaction act; act.sa_handler = test_func; //Set the function to handle the signal act.sa_flags = 0; sigemptyset(&act.sa_mask); sigaction(SIGPROF, &act, NULL);//Send SIGPROF signal when the time is up } void init_time() { struct itimerval val; val.it_value.tv_sec = 1; //1seconds later the timer is enabled val.it_value.tv_usec = 0; val.it_interval = val.it_value; //The timer interval is1s setitimer(ITIMER_PROF, &val, NULL); } int main(int argc, char **argv) { init_sigaction(); init_time(); while(1); return 0; }
It can be seen that each second outputs a count value:
The following is the running result:
[root@localhost 5th]# ./test
count is 0
count is 1
count is 2
count is 3
count is 4
count is 5
count is 6
count is 7
count is 8
count is 9
Appendix:
signal
1. Header file
#include <signal.h>
2. Function
. Set the corresponding action for a signal
3. Function prototype
void (*signal(int signum,void(* handler)(int)))(int);
Decomposed:
typedef void (*sig_t) (int);
sig_t signal(int sig, sig_t func);
The first parameter is the target signal. The func parameter is a pointer to a function that handles the signal. This signal handling function takes an int parameter and should return void.
The func parameter can also be set to some of the following values:
SIG_IGN: If the func parameter is set to SIG_IGN, the signal will be ignored.
SIG_DFL: If the func parameter is set to SIG_DFL, the signal will be handled according to the defined behavior.
4. sig signal types
1) #define SIGHUP 1 /* hangup */
SIGHUP is a signal commonly used by Unix system administrators. Many background service processes will reread their configuration files after receiving this signal. However, the actual function of this signal is to notify the process that its control terminal has been disconnected. The default behavior is to terminate the process.
2) #define SIGINT 2 /* interrupt */
For Unix users, SIGINT is another commonly used signal. Many shells use CTRL-C combination makes this signal well-known. The formal name of the signal is interrupt signal. The default behavior is to terminate the process.
3) #define SIGQUIT 3 /* quit */
SIGQUIT signal is used to receive the shell's CTRL-/In addition, it is used to inform the process to exit. This is a common signal used to notify the application to close gracefully (i.e., to perform some exit actions before ending). The default behavior is to terminate the process and create a core dump.
4) #define SIGILL 4 /* illegal instr. (not reset when caught) */
If the process being executed contains illegal instructions, the operating system will send the SIGILL signal to the process. If your program uses threads or pointer functions, you may try to catch this signal to assist in debugging. (Note: The original sentence is 'If your program makes use of use of threads, or pointer functions, try to catch this signal if possible for aid in debugging.' The two 'use of use of' may be a typographical error in the original book or I may not understand its meaning; besides, I often hear 'functions pointer', for 'pointer functions', after searching on Google, it seems to be something from Fortran, no matter what, I really don't know its exact meaning, please correct me if you know [/The default behavior is to terminate the process and create a core dump.
5) #define SIGTRAP 5 /* trace trap (not reset when caught) */
SIGTRAP is a signal defined by the POSIX standard for debugging purposes. When a debugged process receives this signal, it means that it has reached a debugging breakpoint. Once this signal is delivered, the debugged process will stop, and its parent process will be notified. The default behavior is to terminate the process and create a core dump.
6) #define SIGABRT 6 /* abort() */
SIGABRT provides a method to create a core dump while aborting a process. However, if the signal is caught and the signal handler does not return, the process will not terminate. The default behavior is to terminate the process and create a core dump.
7) #define SIGFPE 8 /* floating point exception */
When a process encounters a floating-point error, the SIGFPE signal is sent to the process. For programs that handle complex mathematical operations, it is generally recommended to catch this signal. The default behavior is to terminate the process and create a core dump.
8) #define SIGKILL 9 /* kill (cannot be caught or ignored) */
SIGKILL is the most difficult to deal with among these signals. As you can see from the comment next to it, this signal cannot be caught or ignored. Once the signal is delivered to a process, the process will terminate. However, there are some rare cases where SIGKILL will not terminate the process. These rare cases occur when handling a 'non-interruptible operation' (such as disk I/O) occurs. Although such situations are rare, if they do occur, they can cause a deadlock in the process. The only way to end the process is to restart it. The default behavior is to terminate the process.
9) #define SIGBUS 10 /* bus error */
As its name suggests, the SIGBUS signal is generated when the CPU detects an error on the data bus. This signal is generated when a program tries to access a memory address that is not properly aligned. The default behavior is to terminate the process and create a core dump.
10) #define SIGSEGV 11 /* segmentation violation */
SIGSEGV is another C/C++A signal familiar to programmers. When a program does not have the right to access a protected memory address, or accesses an invalid virtual memory address (dirty pointers, dirty pointers, note: due to not being synchronized with the content of the backup storage. For more information about wild pointers, see http://en.wikipedia.org/wiki/Explanation of Wild_pointer. The default behavior is to terminate the process and create a core dump.
11) #define SIGSYS 12 /* non-existent system call invoked */
The SIGSYS signal is delivered when a process executes a non-existent system call. The operating system delivers this signal, and the process is terminated. The default behavior is to terminate the process and create a core dump.
12) #define SIGPIPE 13 /* write on a pipe with no one to read it */
The function of a pipe is like a telephone, allowing communication between processes. If a process attempts to write to a pipe and there is no responder on the other end of the pipe, the operating system will deliver the SIGPIPE signal to this annoying process (which is the process that intends to write). The default behavior is to terminate the process.
13) #define SIGALRM 14 /* ) #define SIGALRM */
alarm clock
When the timer of the process expires, the SIGALRM signal will be delivered to the process. These timers are set by the setitimer and alarm calls mentioned later in this chapter.
14default behavior is to terminate the process. 15 /* ) #define SIGTERM */
software termination signal from kill
15SIGTERM signal is sent to the process to notify the process that it is time to terminate and perform some cleanup activities before termination. SIGTERM signal is the default signal sent by the Unix kill command and is also the default signal sent to the process when the operating system is shutting down. The default behavior is to terminate the process. 16 /* ) #define SIGURG */
urgent condition on IO channel
16When certain conditions occur on the sockets that the process has opened, SIGURG will be sent to the process. If the process does not catch this signal, it will be discarded. The default behavior is to discard this signal. 17 /* ) #define SIGSTOP */
sendable stop signal not from tty
The signal cannot be caught or ignored. Once the process receives the SIGSTOP signal, it will stop immediately until it receives another SIGCONT
17) #define SIGTSTP 18 /* stop signal from tty */
SIGSTP is similar to SIGSTOP, but the difference is that the SIGSTP signal can be caught or ignored. When the shell receives CTRL-When Z is reached, this signal is delivered to the process. The default behavior is to stop the process until a SIGCONT signal is received.
18) #define SIGCONT 19 /* continue a stopped process */
SIGCONT is also an interesting signal. As mentioned before, when a process stops, this signal is used to inform the process to resume execution. The interesting thing about this signal is that it cannot be ignored or blocked, but it can be caught. This is meaningful because a process might not want to ignore or block the SIGCONT signal, otherwise, what should the process do when it receives SIGSTOP or SIGSTP? The default behavior is to discard the signal.
19) #define SIGCHLD 20 /* to parent on child stop or exit */
SIGCHLD was introduced by Berkeley Unix and is better than SRV 4 The implementation on Unix has a better interface. (If the signal is not a retroactive process, then the BSD SIGCHID signal implementation is better. In the system V Unix implementation, if the process requests to catch this signal, the operating system will check if there are any unfinished child processes (these child processes are already exited) and if there are any parent processes waiting to call wait to collect their status). If the child process exits with some terminating information, then the signal handler will be called. So, simply requesting to catch this signal will cause the signal handler to be called (translator's note: that is, the so-called 'signal retroactivity'), which is a rather chaotic situation.) Once a process's child process status changes, the SIGCHLD signal will be sent to the process. As I mentioned in the previous chapter, although the parent process can fork child processes, there is no need to wait for the child process to exit. Generally speaking, this is not good because once the process exits, it may become a zombie process. However, if the parent process catches the SIGCHLD signal, it can use one of the wait series calls to collect the status of the child process or determine what happened. When sending SIGSTOP, SIGSTP, or SIGCONF signals to the child process, the SIGCHLD signal will also be sent to the parent process. The default behavior is to discard the signal.
20) #define SIGTTIN 21 /* to readers pgrp upon background tty read */
When a background process attempts to perform a read operation, the SIGTTIN signal is sent to the process. The process will be blocked until the SIGCONT signal is received. The default behavior is to stop the process until the SIGCONT signal is received.
21#define SIGTTOU 22 /* like TTIN if (tp-t_local<OSTOP) */
The SIGTTOU signal is similar to SIGTTIN, the difference being that the SIGTTOU signal is generated when a background process attempts to write to a tty that has the TOSTOP attribute set. However, if the tty does not have this attribute set, SIGTTOU will not be sent. The default behavior is to stop the process until the SIGCONT signal is received.
22#define SIGIO 23 /* input/possible output signal */
If the process has an I/For O operations, the SIGIO signal will be sent to this process. The process can set it through the fcntl call. The default behavior is to discard the signal.
23) #define SIGXCPU 24 /* exceeded CPU time limit */
If the process exceeds its CPU limit (CPU limit) that it can use, the SIGXCPU signal is sent to it. This limit can be set using the setrlimit discussed later. The default behavior is to terminate the process.
24) #define SIGXFSZ 25 /* exceeded file size limit */
If the process exceeds its file size limit that it can use, the SIGXFSZ signal is sent to it. We will continue to discuss this signal later. The default behavior is to terminate the process.
25) #define SIGVTALRM 26 /* virtual time alarm */
If the process exceeds its set virtual timer count, the SIGVTALRM signal is sent to it. The default behavior is to terminate the process.
26) #define SIGPROF 27 /* profiling time alarm */
When a timer is set, SIGPROF is another signal that will be sent to the process. The default behavior is to terminate the process.
27) #define SIGWINCH 28 /* window size changes */
When the process adjusts the line or column of the terminal (such as increasing the size of your xterm), the SIGWINCH signal is sent to the process. The default behavior is to discard the signal.
28) #define SIGUSR1 29 /* user defined signal 1 */
29) #define SIGUSR2 30 /* user defined signal 2 */
SIGUSR1and SIGUSR2These two signals are designed for user specification. They can be set to complete any of your needs. In other words, the operating system has no behavior associated with these two signals. The default behavior is to terminate the process. (Translation note: The translation of these two sentences from the original seems a bit contradictory.)
5. Example
5.1. Ctrl under Linux+C Implementation under WindowsOne
The usual practice under Linux:
signal(SIGINT, sigfunc); // Set signal void sigfunc(int signo) { ... //Handle operations related to signals }
Below is Ctrl under Linux+C Implementation under Windows
#include <stdio.h> #include <windows.h> static is_loop = 1; // Capture Console Ctrl+C Event Function BOOL CtrlHandler( DWORD fdwCtrlType ) { switch (fdwCtrlType) { /* Handle the CTRL-C signal. */ case CTRL_C_EVENT: printf("CTRL_C_EVENT \n"); break; case CTRL_CLOSE_EVENT: printf("CTRL_CLOSE_EVENT \n"); break; case CTRL_BREAK_EVENT: printf("CTRL_BREAK_EVENT \n"); break; case CTRL_LOGOFF_EVENT: printf("CTRL_LOGOFF_EVENT \n"); break; case CTRL_SHUTDOWN_EVENT: printf("CTRL_SHUTDOWN_EVENT \n"); break; default: return FALSE; } is_loop = 0; return (TRUE); } int main(int argc, char *argv[]) { printf("Set Console Ctrl Handler\n"); SetConsoleCtrlHandler((PHANDLER_ROUTINE)CtrlHandler, TRUE); while (is_loop); return 0; }
5.2Ctrl in Linux+C Implementation in Windows
#include <stdio.h> #include <windows.h> #define CONTRL_C_HANDLE() signal(3, exit) int main(int argc, char *argv[]) { printf("Set Console Ctrl Handler\n"); CONTRL_C_HANDLE(); while (1); system("PAUSE"); return 0; }
This is the full content of the brief introduction to the use of several timing functions in Linux brought to you by the editor. Hope everyone will support and cheer for the tutorial~