Signal Linux system programming (five): signal set manipulation functions, pendi

Recommended for you: Get network issues from WhatsUp Gold. Not end users.

A, signal set and related operation function

Signal set is defined as a data type:

typedef struct {

                       unsigned long sig[_NSIG_WORDS],

} sigset_t

Set signal set is used to describe the signals, each signal occupies a (64). All signals supported by the Linux can appear in whole or in part in the signal, and signal blocking correlation function with the use of. Here is the correlation function is defined as the signal set operation:

#include <signal.h>

int sigemptyset(sigset_t *set),

int sigfillset(sigset_t *set),

int sigaddset(sigset_t *set, int signum)

int sigdelset(sigset_t *set, int signum),

int sigismember(const sigset_t *set, int signum),


sigemptyset(sigset_t *set)Initialized by the signal set specified set, signal set all signals inside is empty, the equivalent of 64 to 0,

sigfillset(sigset_t *set)After this call, set signal to a set that contains 64 kinds of signals supported by Linux, the equivalent of 64 is set to 1,

sigaddset(sigset_t *set, int signum)In set signal into Signum signal to concentrate, equivalent to the corresponding to the given signal position 1,

sigdelset(sigset_t *set, int signum)Deleting Signum signal in the signal set points, equivalent to the corresponding to the given signal position 0,

sigismember(const sigset_t *set, int signum)To determine whether the signal is Signum concentrated in the signal set points, equivalent to check a given signal of the corresponding bit is 0 or 1.

Sample program:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
void print_sigset(sigset_t *set);
int main(void)
{
    sigset_t myset;
    sigemptyset(&myset);
    sigaddset(&myset,SIGINT);
    sigaddset(&myset,SIGQUIT);
    sigaddset(&myset,SIGUSR1);
    sigaddset(&myset,SIGRTMIN);
    print_sigset(&myset);

    return 0;

}
void print_sigset(sigset_t *set)
{
    int i;
    for(i = 1; i <NSIG; ++i){
        if(sigismember(set,i))
            printf("1");
        else
            printf("0");
    }
    putchar('\n');
}

Result:

QQ截图20130715145238

You can see the add signal corresponding to the location of the 1

Two, outstanding and signal blocking

Man help:

Signal mask and pending signals

       A signal may be blocked, which means that it will not be delivered
       until it is later unblocked.  Between the time when it is generated
       and when it is delivered a signal is said to be pending.

       Each thread in a process has an independent signal mask, which
       indicates the set of signals that the thread is currently blocking.
       A thread can manipulate its signal mask using pthread_sigmask(3).  In
       a traditional single-threaded application, sigprocmask(2) can be used
       to manipulate the signal mask.
Execute action signal is called signal delivery of (Delivery), signal from production to delivery as between state, called signal pending (Pending). The process can choose to block (Block) of a signal. Will remain in a pending state signals are blocking occurs, until the process unblock this signal, then executes the delivery of action. Note, blocking and neglect is different, as long as the signal is blocked will not pass up, but neglect is a kind of action in the delivery of the optional. Each process has a used to describe what signal is delivered to the process when the signal is blocked, all the signals of the signal are concentrated in delivered to the process will be blocked. 
Signal representation in the kernel can be regarded as such: 

QQ截图20130715150052

Look and say: 
Block set (block set, shielding sets): signal by a process of shield, in the position corresponding to the 1 signal shielding
Pending set (pending signal set): if a signal is concentrated in the process of blocking, is also in the corresponding position pending concentration 1, said the signal cannot be handed over, will not be processed
handler(Signal processing functions): signal processing function corresponding to each signal, when the signal is not in the pending concentrated, will be called
 
The following is related with signal blocking and outstanding function operation: 

#include <signal.h>

int  sigprocmask(int  how,  const  sigset_t *set, sigset_t *oldset)),

int sigpending(sigset_t *set));

int sigsuspend(const sigset_t *mask)),


sigprocmask()According to the parameters of how to realize the signal set operation can function, there are three main types of operation:

sigpending(sigset_t *set))Get the current has been delivered to the process, all the signals are blocked, centralized return results in signal at set.

sigsuspend(const sigset_t *mask))To receive a signal, the signal mask temporary replacement process using mask, and the suspension of the execution of a process, until it receives a signal.

Sigsuspend returns will restore the signal mask before the call. The signal processing function is completed, the process will continue. The system call always returns -1, and set the errno to EINTR.

Sample program:

#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <fcntl.h>

#include <stdlib.h>
#include <stdio.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);
void printsigset(sigset_t *set)
{
    int i;
    for (i=1; i<NSIG; ++i)
    {
        if (sigismember(set, i))
            putchar('1');
        else
            putchar('0');
    }
    printf("\n");
}

int main(int argc, char *argv[])
{
    sigset_t pset;
    sigset_t bset;
    sigemptyset(&bset);
    sigaddset(&bset, SIGINT);
    if (signal(SIGINT, handler) == SIG_ERR)
        ERR_EXIT("signal error");
    if (signal(SIGQUIT, handler) == SIG_ERR)
        ERR_EXIT("signal error");

    sigprocmask(SIG_BLOCK, &bset, NULL);//The signal process of accession blocking concentration
    for (;;)
    {
        sigpending(&pset);
        printsigset(&pset);
        sleep(1);
    }
    return 0;
}

void handler(int sig)
{
    if (sig == SIGINT)
        printf("recv a sig=%d\n", sig);
    else if (sig == SIGQUIT)
    {
        sigset_t uset;
        sigemptyset(&uset);
        sigaddset(&uset, SIGINT);
        sigprocmask(SIG_UNBLOCK, &uset, NULL);
    }
}

Result:

QQ截图20130715152818

    Description: program the SIGINT signal to the process of blocking set (set in shielding), Didn't send SIGINT signals, So the process pending concentration signal is not in pending state, When we press the ctrl+c, To process SIGINT signal transmission, Due to the blocking SIGINT signal in the process of, So SIGINT signal can not be submitted as, Also is in a pending state, So when I print pending found SIGINT corresponding to 1, Now we press ctrl+\, Send SIGQUIT signal, Because of this signal has not been process blocking, So SIGQUIT signal directly handed over, Execute the corresponding handler, Remove the blocking process on SIGINT signal in the processing function, So the SIGINT signal transmitted prior to delivery., Execute the corresponding handler, But because the SIGINT signal is not a reliable signal, Does not support line, So in the end only one signal delivery of.

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <error.h>
#include <string.h>
#include <unistd.h>

/* Version 1, reliable signal will be delivery times */
#define MYSIGNAL SIGRTMIN+5
/* Version 2, not only by delivering a reliable signal */
//#define MYSIGNAL SIGTERM

void sig_handler(int signum)
{
    psignal(signum, "catch a signal");
}

int main(int argc, char **argv)
{
    sigset_t block, pending;
    int sig, flag;

    /* Sets the signal handler */
    signal(MYSIGNAL, sig_handler);

    /* Shielding the signal */
    sigemptyset(&block);
    sigaddset(&block, MYSIGNAL);
    printf("block signal\n");
    sigprocmask(SIG_BLOCK, &block, NULL);

    /* Two signal, signal will be triggered many times */
    printf("---> send a signal --->\n");
    kill(getpid(), MYSIGNAL);
    printf("---> send a signal --->\n");
    kill(getpid(), MYSIGNAL);

    /* Check the current pending signal */
    flag = 0;
    sigpending(&pending);
    for (sig = 1; sig <NSIG; sig++) {
        if (sigismember(&pending, sig)) {
            flag = 1;
            psignal(sig, "this signal is pending");
        } 
    }
    if (flag == 0) {
        printf("no pending signal\n");
    }

    /* Release the signal shielding, pending signal will be delivered */
    printf("unblock signal\n");
    sigprocmask(SIG_UNBLOCK, &block, NULL);

    /* Check pending signal again */
    flag = 0;
    sigpending(&pending);
    for (sig = 1; sig <NSIG; sig++) {
        if (sigismember(&pending, sig)) {
            flag = 1;
            psignal(sig, "a pending signal");
        } 
    }
    if (flag == 0) {
        printf("no pending signal\n");
    }

    return 0;
}

Result:

QQ截图20130715154540

Two implementation results of different: the first of a series of sending two unreliable signal, finally unblock, only one handed over, the unreliable signal does not support line.

Second implementation, two consecutive transmission reliable signal, to relieve the obstruction, handed over, reliable signal support line.

ok, This section was written



 

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download

Posted by Bernie at November 09, 2013 - 8:48 PM