LINUX C language programming - signal processing function

xiaoxiao2021-03-06  26

Foreword: This chapter we discuss the signal processing function under Linux.

Signal Processing Functions under Linux:

1. Production of the signal

2. Treatment of the signal

3. Other signal functions

-------------------------------------------------- ------------------------------

An instance

1. Signal generation

The signal under Linux can class more than the INT under DOS or events under Windows. The signal that is believed when there is a signal to send to the corresponding process. The signal under Linux has the following. We use Kill -l The command can get the following output:

1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL

5) SigTrap 6) Sigabrt 7) Sigbus 8) SIGFPE

9) Sigkill 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2

13) SIGPIPE 14) SIGALRM 15) Sigterm 17) Sigchld

18) Sigcont 19) Sigstop 20) Sigtstp 21) Sigttin

22) Sigttou 23) Sigurg 24) SIGXCPU 25) SIGXFSZ

26) SigvTalRM 27) SigProf 28) Sigwinch 29) SIGIO

30) Sigpwr

For detailed explanations about these signals, check the output results of Man 7 Signal. There are two sources of signal events: one is the reason for hardware (such as we pressed the keyboard), one is the reason for the software (such as our system function or Is a command to send a signal). The most commonly used system functions are Kill, Raise, Alarm and Setitimer functions. Setitimer Functions We use the one of the timer to learn again.

#include

#include

#include

INT KILL (PID_T PID, INT SIG);

int Raise; INT SIG

Unisigned int alarm (unsigned int seconds);

Kill system call is responsible for sending a signal SIG to the process.

If the PID is a positive, the signal SIG is sent to the process PID.

If the PID is equal to 0, the signal SIG is sent to the process of the PID process in the same process group.

If the PID is equal to -1, the signal is sent to the process in all process tables, except for the maximum process number.

If the PID is like -1, and 0, it is only the transmission process group is -PID.

We use the most first case. Remember the example of our daemon? We used this function to kill the creation of the Parent process daemon.

The RAISE system call sends a SIG signal from you. We can use the above functions to implement this feature.

The ALARM function is a bit related. This function can send a SIGALRM signal to yourself after seconds seconds. What is the result of this function?

#include

Main ()

{

Unsigned Int i;

Alarm (1);

For (i = 0; 1; i )

Printf ("i =% d", i);

}

The default operation of SIGALRM is ending the process, so the program ends after 1 second, you can see how much your last I value is, compare the performance difference between everyone (I am 2232).

2. Signal operations sometimes we want the process correctly, and do not want the process to be affected by the signal, such as we hope that the above program is not ending after 1 second. At this time we have to perform the signal.

The most common method of signal operation is to block the signal shield. The signal mask is used to use several functions below.

#include

INT SiGemptySet (SIGSET_T * SET);

INT SigfillSet (SIGSET_T * SET);

Int SigaddSet (SigSet_t * set, int signo);

INT Sigdelset (SIGSET_T * SET, INT SIGNO);

Int Sigismember (SIGSET_T * SET, INT SIGNO);

INT SigProcmask (int how, const sigset_t * set, sigset_t * et);

SiGemptySet Function Initialization Signal Collection SET, set the SET set to empty. SigfillSet also initialize the signal set, just set the signal set to all signals. SigaddSet Adds SIGNO to the signal collection, SIGDELSET Remove the signal from the signal collection. SIGISMEMBER query signal is in the signal collection.

SigProcmask is a key function. To set the signal collection set before use. This function is to join the specified signal set set to the process of signal blocking set, if an OSET is provided, the current process signal The block collection will be saved inside OSET. The parameter how determines the operation of the function.

SIG_BLOCK: Add a signal set to the clogging collection of the current process.

SIG_UNBLOCK: Removes a signal collection from the current blockage collection.

SIG_SETMASK: Set the current signal set to the signal blocking collection.

Use an example to explain the use of these functions.

#include

#include

#include

#include

INT main (int Argc, char ** argv)

{

Double Y;

Sigset_t intmask;

INT I, REPEAT_FACTOR;

IF (argc! = 2)

{

FPRINTF (stderr, "usage:% s repeat_factor / n / a", argv [0]);

Exit (1);

}

IF ((Repeat_Factor = ATOI (Argv [1])) <1) REPEAT_FACTOR = 10;

SiGemptyset (& INTMASK); / * Set the signal set to empty * /

SigaddSet (& INTMASK, SIGINT); / * Add to Interrupt CTRL C Signal * /

While (1)

{

/ * Block signal, we don't want to save the original collection, so the parameter is null * /

SigProcmask (SIG_BLOCK, & INTMASK, NULL);

FPRINTF (stderr, "sigint signal blocked / n");

For (i = 0; i

FPrintf (stderr, "blocked calculation is finished / n");

/ * Cancellation * /

SigProcmask (SIG_UNBLOCK, & INTMASK, NULL);

FPRINTF (stderr, "sigint signal unblocked / n");

For (i = 0; i

FPRINTF (stderr, "unblocked calculation is finished / n");

}

exit (0);

}

When the program is running, we should use Ctrl C to end. If we issue a sigint signal when we first calculate, the program is not reflected because the signal is already blocked. The program will end when the signal is canceled. Note that we can only send a SIGINT signal, because the signal mask is just adding the signal to the signal block collection, and does not discard this signal. Once the signal shield is canceled, this signal will work.

Sometimes we want to make a timely reflection on the signal, such as when you press CTRL C, we don't want to do something, we want to tell the user that your operation is not good, please don't try, not any reflection Nothing. At this time we have to use the SigAction function.

#include

Int SigAction (int Signo, Const Struct SigAction * ACT,

Struct SigAction * Oact);

Struct sigaction {

Void (* SA_Handler) (Int Signo);

Void (* sa_sigction) (int SigInfo_T * INFO, VOID * ACT);

Sigset_t sa_mask; int sa_flags;

Void (* sa_restore) (void);

}

This function and structure look a bit a little horrible. Don't be scared by this, in fact, this function is quite simple. Let's explain the meaning of each parameter. Signo is very simple is the signal we have to handle, it can be Any legal signal. There are two signals that cannot be used (SIGKILL and SIGSTOP). ACT contains information we have to handle this signal. Oact is more simple, it is the process of processing this function, mainly used to save Information, usually OK is used in NULL.

The signal structure is a bit complicated. Don't take our slow learning.

SA_HANDALER is a function type pointer, this pointer points to a function, this function has a parameter. This function is the function we have to perform. Sa_SigAction, SA_RESTORE and SA_HANDAL are almost the same, but the parameters are different. These two elements are very Even if you use it.

SA_FLAGS is used to set all the circumstances of the signal operation. Generally set to 0 well. SA_MASK We have already learned

When using sa_handler points to our signal operation function, you can. SA_Handler has two special values: SIG_DEL and SIG_IGN.SIG_DEL are using the default signal operation function, while SIG_IGN is the operation of ignoring the signal. function.

This function is complex, we use an instance to explain. The following function can capture the user's CTRL C signal. And output a prompt statement.

#include

#include

#include

#include

#include

#define prompt "Do you want to terminate the program?"

Char * prompt = prompt;

Void Ctrl_C_OP (int Signo)

{

Write (stderr_fileno, prompt, strlen (prompt));

}

int main ()

{

Struct SigAction Act;

Act.sa_handler = ctrl_c_op;

SiGemptySet (& Act.sa_mask);

Act.sa_flags = 0;

IF (Sigction (Sigint, & Act, Null <0)

{

FPRINTF (stderr, "install signal action error:% s / n / a", strrror (errno));

Exit (1);

}

While (1);

}

Among the signal operation functions of the above program, we used the Write function without using the fprintf function. Because we have to take into account the following situation. If we have a signal in the signal operation, then how the program runs What? In order to handle the occurrence of the signal when the signal processing function is running, we need to set the SA_mask member. We add the signal we want to mask to the SA_mask structure, so these functions will be blocked when signal processing.

3. Other signal functions are more complicated due to the operation and processing of signals, and we will introduce several signal operation functions.

#include

#include

INT PAUSE (VOID);

Int Sigsuspend (const sigset_t * sigmask);

The PAUSE function is simple, that is, the process is hanging until a signal occurs. And Sigsuspend is also a suspend process only in the call time with Sigmask replaces the current signal blocking collection.

#include

Int SigsetJMP (Sigjmp_BUF ENV, INT VAL);

Void Siglongjmp (Sigjmp_buf Env, Int Val);

Remember the goto function or setjmp and longjmp function. These two signal jump functions can also implement the program's jump to make us jump from the functions to what we need.

Due to the few functions above, we rarely encountered, so just explain it, please check the online help.

4. An instance remember which program we created in the daemon? The daemon will strengthen the program here. Below this program can also check the user's mail. But provide a switch, if the user does not want to prompt a new The message arrives, you can send a SIGUSR2 signal to the program. If you want to provide a prompt, you can send a SIGUSR1 signal. # Include

#include

#include

#include

#include

#include

#include

#include

#include

/ * Linux's Direct personal email address is / var / spool / mail / * /

#define mail_dir "/ var / spool / mail /"

/ * Sleep 10 seconds * /

#define sleep_time 10

#define max_filename 255

Unsigned char notifyflag = 1;

Long get_file_size (const char * filename)

{

Struct stat BUF;

IF (Stat (FileName, &; BUF) == - 1)

{

IF (errno == enoent) return 0;

Else Return -1;

}

Return (long) buf.st_size;

}

Void Send_mail_notify (void)

{

FPRINTF (stderr, "new mail has arrived / 007 / n");

}

Void TURN_ON_NOTIFY (int Signo)

{

Notifyflag = 1;

}

Void Turn_off_notify (int Signo)

{

Notifyflag = 0;

}

INT CHECK_MAIL (const char * filename)

{

Long old_mail_size, new_mail_size;

Sigset_t blockset, EMPTYSET;

SiGemptyset (&; blockset);

SiGemptySet (&; EMPTYSET);

SigaddSet (&; Blockset, Sigusr1);

SigaddSet (&; Blockset, SIGUSR2);

Old_mail_size = get_file_size (filename);

IF (Old_mail_SIZE <0) Return 1;

IF (old_mail_size> 0) Send_mail_notify ();

Sleep (Sleep_Time);

While (1)

{

IF (SigProcmask (SIG_BLOCK, &; Blockset, NULL) <0) Return 1;

While (NotifyFlag == 0) Sigsuspend (&; EMPTYSET);

IF (SigProcmask (SIG_SETMASK, &; EMPTYSET, NULL) <0) RETURN 1;

NEW_MAIL_SIZE = GET_FILE_SIZE (FileName);

IF (new_mail_size> old_mail_size) send_mail_notify;

OLD_MAIL_SIZE = New_MAIL_SIZE;

Sleep (Sleep_Time);

}

}

Int main (void)

{

Char mailfile [max_filename];

Struct SigAction Newact;

Struct Passwd * Pw;

IF ((pw = getpwuid (getuid ())) == NULL)

{

FPRINTF (stderr, "get login name error:% s / n / a", strrror (errno)); exit (1);

}

STRCPY (Mailfile, Mail_Dir);

STRCAT (Mailfile, PW-> PW_NAME);

Newact.sa_handler = TURN_ON_NOTIFY;

Newact.sa_flags = 0;

SiGemptySet (&; newact.sa_mask);

SigaddSet (&; newact.sa_mask, sigusr1);

SigaddSet (&; newact.sa_mask, sigusr2);

IF (Sigctions (Sigusr1, &; Newact, NULL) <0)

FPrintf (stderr, "turn on error:% s / n / a", strrror (errno));

Newact.sa_handler = TURN_OFF_NOTIFY;

IF (Sigctions (Sigusr1, &; Newact, NULL) <0)

FPRINTF (stderr, "turn off error:% s / n / a", strrror (errno));

Check_mail (mailfile);

exit (0);

}

Signal operation is a very complicated thing, more complicated than the complexity in our imagination, if you want to completely understand the various problems of the signal operation, then you should look at the online manual in addition to a lot of exercises. But if We are just the general use, and there are few functions above. We will introduce it here.

转载请注明原文地址:https://www.9cbs.com/read-82286.html

New Post(0)