Signal Data Structures

   

Before we get into the process of handling signals, let's look at the associated data structures. Figure 14-1 shows the various signal-related structures and how they relate to the proc and kthread structures.

Figure 14-1. Signal-Related Data Structures

graphics/14fig01.gif


With the advent of multithreaded processes in HP-UX version 11.0, the concept of signals became much more complicated, and several new data structures were created. At the same time, much of the data that used to be kept in the proc structure was moved into a new structure called a struct Process_Shared_Fields. The proc structure has a field, p_shared, that points to the Process_Shared_Fields structure. The Process_Shared_Fields is mostly made up of a group of fields of type ksigset_t, which is merely an array of integers used as a bitfield one bit per signal type. A variety of routines exist in the kernel for manipulating these bitfields setting or clearing individual bits, setting or clearing all bits, testing bits, and so on. The Process_Shared_fields structure is shown in Listing 14.1.

Listing 14.1. Process_Shared_fields structure
 struct Process_Shared_Fields {   ksigset_t pshared_sigignore;    /* signals being ignored */   ksigset_t pshared_sigcatch;     /* signals being caught by                                      user */   int       pshared_nsig;         /* # of signals recognizedby                                      process */   void    (*pshared_signal[_NSIG-1])();    /* disposition of                                      signals */   ksigset_t pshared_sighandmask[_NSIG-1];  /* signals to be                                      blocked */   ksigset_t pshared_sigreset;     /* reset handler after                                      catching */   ksigset_t pshared_siginfowanted;/* sigs to be delivered witv                                      siginfo*/   ksigset_t pshared_sigrestart;   /* restart interrupted sys                                      call */   ksigset_t pshared_signodefer;   /* Do not block sig in                                      handler */   ksigset_t pshared_sigonstack;   /* Signals to take on                                      sigstack */   void    (*pshared_sigreturn)(); /* handler return                                      address   proc_sigcontexttype_t pshared_sigcontexttype; }; 

In addition to the above structure, there are a few signal-related fields that are still in the proc structure (Listing 14.2).

Listing 14.2. Signal-related fields in proc structure
 struct proc {          ...    ksigset_t p_sig;            /* sigs pending on the                                                proc */    ksigset_t p_ksi_avail;      /* signals with siginfo                                                available */    ksigset_t p_ksifl_alloced;  /* signals with freelist                                                entries */    ksi_t *p_ksiactive;         /* active list of pending                                                signals */    ksi_t *p_ksifree;           /* free list of ksi_t's */    struct sigcount *p_sigcountp; /* # signals pending at                                                receivers */    ksigwait_t  *p_sigwaiters;   /* list of sigwaiting                                                threads */    int       p_cursig;          /* sig which caused proc                                                stop/exit */               ... }; 

Each process may also have a struct sigcount associated with it, pointed to by the field p_sigcountp in the proc structure. The sigcount structure keeps track of how many signals the process has outstanding that is, sent but not yet received. This structure is only used for signals sent with the sigqueue() system call, which allows the sender to specify data along with the signal. The kill() system call does not use the sigcount structure. There is a pool of these structures available to the system, kept on a free list. When a process sends a signal, a struct sigcount is taken from the pool and attached to the process. When the last of the signals is received, the structure is returned to the pool. The reason this is a separate structure rather than just a counter in the proc structure is that a process could send a signal, then exit before the signal is received. This gives us a persistent record of the signals sent. Listing 14.3 is the sigcount structure.

Listing 14.3. sigcount structure
 typedef struct sigcount {    unsigned int     sc_count:16;   /* sigqueues sent by this                                       process and                                       pending at a receiver */    sc_owner_state_t sc_owner_state:1;    unsigned int     sc_unused:7;    unsigned int     sc_cookie:8;  /* DS ID token */    struct sigcount *sc_next;      /* for freelist management */ } sigcount_t; 

Along with the sigcount structure, signals sent with sigqueue() also need a place to store the data that is sent along with the signal. This information must be outside of the proc structure for the same reason that the sigcount does it may have to persist after the process terminates. The structure that holds this data is a struct __ksi, or ksi_t. The more interesting fields include a pointer to the sigcount structure that's associated with the data, the number of the signal, the cause of the signal (user-generated, timer-generated, I/O completion, etc.), an errno that can be associated with the signal, and two data fields. The first of these fields, si_value, is used by the sigqueue() system call. When a user sends a signal using sigqueue(), he or she can specify a value to be sent along with the signal. The second data field, a large union called __data, contains various information depending on the signal number. Some examples are the faulting address for SIGSEGV or SIGBUS, or the status returned by a child for SIGCLD. Here's a partial list of what's in the ksi_t:

 typedef struct __ksi {    struct sigcount *si_countp;     /* sender's pending                                              signal count */    int               si_signo;   /* signal number */    sigval_t          si_value;    int               si_code;    /* cause of signal */    int               si_errno;   /* associated errno */    union {      ...    } __data; } ksi_t; 

Each kthread structure also has some data related to signals. These are as follows:

 struct kthread {      ...      char    kt_cursig;        /* number of current pending signal,                                    if any */      ksigset_t kt_sig;        /* signals pending to this thread */      ksigset_t kt_ksi_avail;  /* signals with siginfo available */      ksi_t *kt_ksiactive;     /* list of pending queued signals*/      ksigset_t kt_sigmask;    /* current signal mask */      int         kt_proc_sig; /* signo of sig directed at proc */      ...        } 

Finally, we have the ksigwait structure. Each thread that is explicitly waiting for a signal with the pause(), sigpause(), sigwait(), or sigsuspend() system calls will have one of these structures. The ksigwait structures are pointed to by the proc structure, and they in turn point to the thread that is waiting for the signal.



HP-UX 11i Internals
HP-UX 11i Internals
ISBN: 0130328618
EAN: 2147483647
Year: 2006
Pages: 167

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net