/[lkdp]/lkdp/pm/signal.tex
ViewVC logotype

Diff of /lkdp/pm/signal.tex

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.2 by kdlinux2001, Thu Nov 21 13:08:15 2002 UTC revision 1.3 by kdlinux2001, Tue Dec 17 08:58:20 2002 UTC
# Line 1  Line 1 
1  \chapter{System calls \& Signals}  \chapter{System calls \& Signals}
2    
3          \section{User to Kernel space}          \section{User to Kernel space}
4    
5               System calls are used to perform "low-level" operations on the system. System calls are the bridges between user space and kernel space. So it is the bridge between a user application and the system hardware.               \textbf{\Large S}ystem calls are used to perform "low-level" operations on the system. System calls are the bridges between user space and kernel space. So it is the bridge between a user application and the system hardware.
6          \par Each system call \footnote{System calls are defined in \url{include/asm-i386/unistd.h}} has its own unique identifying number. The kernel uses this number as an index into a table of system call entry points, which point to where the system calls reside in memory along with the number of arguments that should be passed to them.          \par Each system call \footnote{System calls are defined in \url{include/asm-i386/unistd.h}} has its own unique identifying number. The kernel uses this number as an index into a table of system call entry points, which point to where the system calls reside in memory along with the number of arguments that should be passed to them.
7          \par When a process makes a system call, the behavior is similar to that with interrupts and exceptions. Like exception handling, the general purpose registers and the number of the system call are pushed onto the stack. And, the system call handler is invoked, which calls the routine within the kernel that will do the actual work.          \par When a process makes a system call, the behavior is similar to that with interrupts and exceptions. Like exception handling, the general purpose registers and the number of the system call are pushed onto the stack. And, the system call handler is invoked, which calls the routine within the kernel that will do the actual work.
8          \par When a user mode program invokes a system call, the libc library transfers control to kernel mode using software interrupt 0x80 registered during IRQ initialization \footnote{set\_system\_gate(SYSCALL\_VECTOR,\&system\_call); in trap\_init() in \url{arch/i386/kernel/traps.c}} and the kernel executes the system call related function. The system call within the kernel is its counterpart in user space prefixed by sys. So, when user calls fork/clone/vfork, kernel executes sys\_fork/sys\_clone/sys\_vfork function. Since, the system call is invoked from user space in order to enter kernel space,it has to pass through the call gate \footnote{Call gates are used to change priviledge level to perform priviledged operatios. Refer appendix ~\ref{appendix B}.} to ensure that user code moves up to the higher privilege level at a specific location within the kernel.          \par When a user mode program invokes a system call, the libc library transfers control to kernel mode using software interrupt 0x80 registered during IRQ initialization \footnote{set\_system\_gate(SYSCALL\_VECTOR,\&system\_call); in trap\_init() in \url{arch/i386/kernel/traps.c}} and the kernel executes the system call related function. The system call within the kernel is its counterpart in user space prefixed by sys. So, when user calls fork/clone/vfork, kernel executes sys\_fork/sys\_clone/sys\_vfork function. Since, the system call is invoked from user space in order to enter kernel space,it has to pass through the call gate \footnote{Call gates are used to change priviledge level to perform priviledged operations. Refer appendix ~\ref{appendix B}.} to ensure that user code moves up to the higher privilege level at a specific location within the kernel.
9          \subsection{sys\_call\_table} \index{sys\_call\_table}          \subsection{sys\_call\_table} \index{sys\_call\_table}
10          The \textit{system\_call} code and the \textit{sys\_call\_table} is defined in the asm code \url{arch/i386/kernel/entry.S}          The \textit{system\_call} code and the \textit{sys\_call\_table} is defined in the asm code \url{arch/i386/kernel/entry.S}
11          % TODO explain code          \begin{verbatim}
12          \begin{verbatim}  
13            ENTRY(system_call)      # LINE : 230
14          ENTRY(system_call)      # LINE : 230              pushl %eax          # save orig_eax
15              pushl %eax          # save orig_eax              SAVE_ALL
16              SAVE_ALL              GET_THREAD_INFO(%ebx)
17              GET_THREAD_INFO(%ebx)              cmpl $(NR_syscalls), %eax
18              cmpl $(NR_syscalls), %eax              jae syscall_badsys
19              jae syscall_badsys                                  # system call tracing in operation
20                                  # system call tracing in operation              testb $_TIF_SYSCALL_TRACE,TI_FLAGS(%ebx)
21              testb $_TIF_SYSCALL_TRACE,TI_FLAGS(%ebx)              jnz syscall_trace_entry
22              jnz syscall_trace_entry          syscall_call:
23          syscall_call:              call *sys_call_table(,%eax,4)
24              call *sys_call_table(,%eax,4)              movl %eax,EAX(%esp)     # store the return value
25              movl %eax,EAX(%esp)     # store the return value          syscall_exit:
26          syscall_exit:              cli                 # make sure we don't miss an interrupt
27              cli                 # make sure we don't miss an interrupt                                  # setting need_resched or sigpending
28                                  # setting need_resched or sigpending                                  # between sampling and the iret
29                                  # between sampling and the iret              movl TI_FLAGS(%ebx), %ecx
30              movl TI_FLAGS(%ebx), %ecx              testw $_TIF_ALLWORK_MASK, %cx   # current->work
31              testw $_TIF_ALLWORK_MASK, %cx   # current->work              jne syscall_exit_work
32              jne syscall_exit_work          restore_all:
33          restore_all:                  RESTORE_ALL
34                  RESTORE_ALL  
35            \end{verbatim}
36          \end{verbatim}          The system\_call entry point is explained below. It starts with saving all the registers. The macro GET\_THREAD\_INFO stores the address of current process descriptor to ebx register.\footnote{Process descriptor is obtained by rounding kernel stack pointer to muliple of 8192 (8 KB).} If the system call is invalid, value of \textit{ENOSYS} is returned through the eax regiser. Else, the function takes the value of system call from eax register and uses it to index into the sys\_call\_table.
37          % TODO examples , fork -> sys_fork          \par   As an example, when \textit{fork system call} is invoked using the fork system call, int 0x80 is invoked, with the register \%eax containing the fork exception number. The exception calls the \textit{system\_call} assembly function. The function uses the exception number to index into the sys\_call\_table and invokes the sys\_fork function. [ \textbf{call *sys\_call\_table(,\%eax,4)}]. The second index 4 is the size of the long or function pointer in x86 system. When the funtion returns, it restores all registers using RESTORE\_ALL macro.
38    
39          \par Scheduling is performed during a system call, to check if any interrupts, signals are missed.          \\ \\ \par Scheduling is performed during a system call, to check if any interrupts, signals are missed.
40    
41          % TODO explain          \begin{verbatim}
42    
43          \begin{verbatim}              ALIGN
44            work_pending:
45              ALIGN              testb $_TIF_NEED_RESCHED, %cl
46          work_pending:              jz work_notifysig
47              testb $_TIF_NEED_RESCHED, %cl          work_resched:
48              jz work_notifysig              call schedule
49          work_resched:              cli                 # make sure we don't miss an interrupt
50              call schedule                                  # setting need_resched or sigpending
51              cli                 # make sure we don't miss an interrupt                                  # between sampling and the iret
52                                  # setting need_resched or sigpending              movl TI_FLAGS(%ebx), %ecx
53                                  # between sampling and the iret              andl $_TIF_WORK_MASK, %ecx      # is there any work to be done other
54              movl TI_FLAGS(%ebx), %ecx                                  # than syscall tracing?
55              andl $_TIF_WORK_MASK, %ecx      # is there any work to be done other              jz restore_all
56                                  # than syscall tracing?              testb $_TIF_NEED_RESCHED, %cl
57              jz restore_all              jnz work_resched
58              testb $_TIF_NEED_RESCHED, %cl          work_notifysig:                         # deal with pending signals and
59              jnz work_resched                                                  # notify-resume requests
60                testl $(VM_MASK),EFLAGS(%esp)
61          \end{verbatim}              movl %esp, %eax
62                jne work_notifysig_v86          # returning to kernel-space or
63          \par When the system call is invoked , the call number is stored in \textit{\%eax register} and the system call handler is picked from the system\_call\_table as defined below.                                              # vm86-space
64          \begin{verbatim}              xorl %edx, %edx
65                call do_notify_resume
66          .data              jmp restore_all
67          ENTRY(sys_call_table)  
68              .long sys_ni_syscall    /* 0 - old "setup()" system call*/          \end{verbatim}
69              .long sys_exit  
70              .long sys_fork             As shown in the following text diagram, when a system call is invoked, it finds the address of the corresponding kernel function from \url{arch/i386/kernel/entry.S} assembly code. It saves the system call number in the eax register and uses the ebx register to index into the process (thread) table. And inovkes the appropriate system call from \textit{sys\_call\_table}.
71              .long sys_read             \par When the system call returns, if checks whether any interrupt or signal missed during the execution of system call. This is performed by jumping to \textit{work\_pending}. If the TIF\_NEED\_RESCHED flag is set, then it calls the schedule function. The flag is a part of CR0 register(Master Status Word) of the i386 architecture and it is set when a task switch occurs. The VM\_MASK bit is also the part of FLAGS register used to emulate virtual 8086 mode.
72              .long sys_write             \par When the code jumps to \textit{work\_notifysig}, it calls the \texit{do\_notify\_resume} function from \url{arch/i386/kernel/signal.c} to deal with the pending signals.
73              .long sys_open          /* 5 */  
74              .long sys_close          \vspace{10pt} \noindent
75              .          \begin{tabularx}{15cm}{lX}
76              .          {\bf Table of User \& Kernel space functions} & \\ \\
77              .            \\  * USER SPACE *  &            * KERNEL SPACE * \\
78              .rept NR_syscalls-(.-sys_call_table)/4          -----------------------------  &  \\
79                   .long sys_ni_syscall              system call (e.g.fork )    &  \\
80              .endr          -----------------------------  &  \\
81             & ------------------------------  \\
82          \end{verbatim}           &         SAVEALL  \\
83             &         syscall function  \\
84          \section{Signal data structure in a process} \label{sig:structs}           &         (e.g. sys\_fork ) \\
85          A  Signal is an asynchronous notification to an application, by the kernel.The application can override default actions for signals, by specifying handlers to be invoked on signal occurences. But, only certain signals can be overridden.           & ------------------------------  \\
86          \par Signals can only be processed when the process is in user mode. If a signal has been sent to a process that is in kernel mode, it is dealt with immediately on returning to user mode.Since, signals are received by user processes and the signal handlers also represents a thread of execution in user space, they can do anything bounded by user privileges. e.g. open/close files, invoke sytstem calls etc.           &         return from syscall     \\
87          \subsection{signals in task\_struct}           & ------------------------------  \\
88          \par The process structure \textit{[task\_struct]} contains following structures related to signals. These are described below, in details.           &         Checking if work\_pending   \\
89             & ------------------------------   \\
90          \begin{verbatim}           &         Checking if work\_resched   \\
91             & ------------------------------   \\
92               /* signal handlers */           &         For scheduling, call     \\
93              spinlock_t sigmask_lock;        /* Protects signal and blocked */           &         schedule function        \\
94              struct signal_struct *sig;      /* signal structure */           & ------------------------------   \\
95             &         RESTORE\_ALL             \\
96              sigset_t blocked;           &         For pending signals, call \\
97              struct sigpending pending;      /* pending signals  */           &         do\_notify\_resume \\
98             & ------------------------------   \\
99              unsigned long sas_ss_sp;          -----------------------------  &  \\
100              size_t sas_ss_size;              system call returns        &  \\
101              int (*notifier)(void *priv);          -----------------------------  &  \\
102              void *notifier_data;          \end{tabularx}
103              sigset_t *notifier_mask;        /* new signal notification bit mask */  
104            \par When the system call is invoked , the call number is stored in \textit{\%eax register} and the system call handler is picked from the system\_call\_table as defined below. The parameters for the system call are not passed using the traditional stack copy method. They are copied to the CPU registers and later copied to kernel mode stack when the sys\_* function starts execution.
105          \end{verbatim}          \begin{verbatim}
106    
107          \subsection{signal\_struct} \index{signal\_struct}          .data
108          The \textit{signal\_struct} is a generic signal structure defined in \url{include/linux/sched.h}. This contains the signal count per process and the spin-lock to protect the signals over multiple CPUs. It also contains an array of size \textit{\_NSIG} \footnote{NSIG is the maximum number of signals supported.} and of type \textit{k\_sigaction} defined below. This array defines the actions to be taken upon receiving any of the \_NSIG [NSIG = 64] signals.          ENTRY(sys_call_table)
109          \begin{verbatim}              .long sys_ni_syscall    /* 0 - old "setup()" system call*/
110                .long sys_exit
111          struct signal_struct {              .long sys_fork
112              atomic_t                count;              .long sys_read
113              struct k_sigaction      action[_NSIG];              .long sys_write
114              spinlock_t              siglock;              .long sys_open          /* 5 */
115          };              .long sys_close
116                .
117          struct k_sigaction {              .
118              struct sigaction sa;              .
119          };              .rept NR_syscalls-(.-sys_call_table)/4
120                     .long sys_ni_syscall
121          \end{verbatim}              .endr
122    
123          \subsection{sigset\_t and struct sigaction}          \end{verbatim}
124          The \textit{sigset\_t} contains a bitmask of 2 words (64 bits), with each bit per signal. This bitmask can be used to check whether any signals are pending for a process or any new signals have arrived. Bit0 corresponds to signal0 and running upwards. An important thing to note here, is that all 64 signals are only available in kernel mode signal handling. At user level, only 32 signals can be handled. Earlier versions of linux used to support only 32 signals in kernel space also. As as result of this, we have oldsigset\_t structure defined in kernel. As a result of this, we also have struct sigaction and struct old\_sigaction defined in \url{include/asm-i386/signal.h}, which differ only in the sigset\_t field. These sigaction structures are used by signal and sigaction system calls explained in section ~\ref{sig:regi}.  
125            \section{Signal data structure in a process} \label{sig:structs}
126          \begin{verbatim}          A  Signal is an asynchronous notification to an application, by the kernel.The application can override default actions for signals, by specifying handlers to be invoked on signal occurences. But, only certain signals can be overridden.
127            \par Signals can only be processed when the process is in user mode. If a signal has been sent to a process that is in kernel mode, it is dealt with immediately on returning to user mode.Since, signals are received by user processes and the signal handlers also represents a thread of execution in user space, they can do anything bounded by user privileges. e.g. open/close files, invoke sytstem calls etc.
128          #ifdef __KERNEL__          \subsection{signals in task\_struct}
129          typedef struct {          \par The process structure \textit{[task\_struct]} contains following structures related to signals. These are described below, in details.
130              unsigned long sig[_NSIG_WORDS];  
131          } sigset_t;          \begin{verbatim}
132              #define _NSIG           64  
133              #define _NSIG_BPW       32               /* signal handlers */
134              #define _NSIG_WORDS     (_NSIG / _NSIG_BPW)              spinlock_t sigmask_lock;        /* Protects signal and blocked */
135                struct signal_struct *sig;      /* signal structure */
136          typedef unsigned long old_sigset_t;  
137                sigset_t blocked;
138          #else              struct sigpending pending;      /* pending signals  */
139    
140              #define NSIG            32              unsigned long sas_ss_sp;
141              typedef unsigned long sigset_t;              size_t sas_ss_size;
142                int (*notifier)(void *priv);
143          #endif              void *notifier_data;
144                sigset_t *notifier_mask;        /* new signal notification bit mask */
145          struct sigaction {  
146              __sighandler_t sa_handler;          \end{verbatim}
147              unsigned long sa_flags;  
148              void (*sa_restorer)(void);          \subsection{signal\_struct} \index{signal\_struct}
149              sigset_t sa_mask;       /* mask last for extensibility */          The \textit{signal\_struct} is a generic signal structure defined in \url{include/linux/sched.h}. This contains the signal count per process and the spin-lock to protect the signals over multiple CPUs. It also contains an array of size \textit{\_NSIG} \footnote{NSIG is the maximum number of signals supported.} and of type \textit{k\_sigaction} defined below. This array defines the actions to be taken upon receiving any of the \_NSIG [NSIG = 64] signals.
150          };          \begin{verbatim}
151    
152          \end{verbatim}          struct signal_struct {
153                atomic_t                count;
154          \subsection{struct sigpending}              struct k_sigaction      action[_NSIG];
155          The list of pending signals is maintained as circular linked list with header node and reference to tail node. The sigqueue structure contains the \textit{siginfo\_t} structure along with a bitmask.              spinlock_t              siglock;
156          \begin{verbatim}          };
157    
158          struct sigpending {          struct k_sigaction {
159              struct sigqueue *head, **tail;              struct sigaction sa;
160              sigset_t signal;          };
161          };  
162            \end{verbatim}
163          \end{verbatim}  
164            \subsection{sigset\_t and struct sigaction}
165          \section{Registering Signals} \label{sig:regi}          The \textit{sigset\_t} contains a bitmask of 2 words (64 bits), with each bit per signal. This bitmask can be used to check whether any signals are pending for a process or any new signals have arrived. Bit0 corresponds to signal0 and running upwards. An important thing to note here, is that all 64 signals are only available in kernel mode signal handling. At user level, only 32 signals can be handled. Earlier versions of linux used to support only 32 signals in kernel space also. As a result of this, we have oldsigset\_t structure defined in kernel. As a result of this, we also have struct sigaction and struct old\_sigaction defined in \url{include/asm-i386/signal.h}, which differ only in the sigset\_t field. These sigaction structures are used by signal and sigaction system calls explained in section ~\ref{sig:regi}.
166           When sending a signal to a process, kernel saves the context of the current thread of execution in user-space itself and overwrites the process's thread context with the signal handlers context. While delivering a signal, kernel stores the thread state of the previous thread of execution in the user-stack.  
167           \par The kernel keeps track of pending signals in each process's process structure. This is a 32-bit value, in user space \footnote{Refer to sigset\_t struct above.} in which each bit represents a single signal. Because it is only one bit per signal, there can only be one signal pending of each type. Its possible that the process to which you want to send the signal is sleeping. If that process is sleeping at an interruptible priority, then the process will be awaken to handle the signal.          \begin{verbatim}
168          \par Whenever a new signal handler is registered by a process using the \textit{signal or sigaction} system call, the kernel updates invokes the sys\_signal function from \url{kernel/signal.c}, or the sys\_sigaction function from \url{acrh/i386/kernel/signal.c}. These functions update the various signal parameters within kernel signal information. Both of these functions call \textit{do\_sigaction} to update signal statisticks.  
169          \begin{verbatim}          #ifdef __KERNEL__
170            typedef struct {
171           /* User space system call */              unsigned long sig[_NSIG_WORDS];
172          sighandler_t signal(int signum, sighandler_t handler);          } sigset_t;
173                #define _NSIG           64
174           /* sys_signal function */              #define _NSIG_BPW       32
175          asmlinkage unsigned long              #define _NSIG_WORDS     (_NSIG / _NSIG_BPW)
176          sys_signal(int sig, __sighandler_t handler)  
177          {          typedef unsigned long old_sigset_t;
178              struct k_sigaction new_sa, old_sa;  
179              int ret;          #else
180    
181              new_sa.sa.sa_handler = handler;              #define NSIG            32
182              new_sa.sa.sa_flags = SA_ONESHOT | SA_NOMASK;              typedef unsigned long sigset_t;
183    
184              ret = do_sigaction(sig, &new_sa, &old_sa);          #endif
185    
186              return ret ? ret : (unsigned long)old_sa.sa.sa_handler;          struct sigaction {
187          }              __sighandler_t sa_handler;
188                unsigned long sa_flags;
189          \end{verbatim}              void (*sa_restorer)(void);
190                sigset_t sa_mask;       /* mask last for extensibility */
191          The function stores the passed handler into new signal handler and calls the do\_sigaction function. If the do\_sigaction function returns success, the old signal handler is returned to the calling process, which can be restored using another signal() system call.          };
192    
193          \begin{verbatim}          \end{verbatim}
194    
195           /* User space system call */          \subsection{struct sigpending}
196          int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);          The list of pending signals is maintained as circular linked list with header node and reference to tail node. The sigqueue structure contains the \textit{siginfo\_t} structure along with a bitmask.
197            \begin{verbatim}
198           /* sys_sigaction function */  
199          asmlinkage int          struct sigpending {
200          sys_sigaction(int sig, const struct old_sigaction *act,              struct sigqueue *head, **tail;
201               struct old_sigaction *oact)              sigset_t signal;
202            };
203           /* INCOMOPLETE CODE */  
204            \end{verbatim}
205          if (act) {  
206              old_sigset_t mask;          \section{Registering Signal handlers} \label{sig:regi}
207              __get_user(new_ka.sa.sa_flags, &act->sa_flags);           When sending a signal to a process, kernel saves the context of the current thread of execution in user-space itself and overwrites the process's thread context with the signal handlers context. While delivering a signal, kernel stores the thread state of the previous thread of execution in the user-stack.
208              _get_user(mask, &act->sa_mask);           \par The kernel keeps track of pending signals in each process's process structure. This is a 32-bit value, in user space \footnote{Refer to sigset\_t struct above.} in which each bit represents a single signal. Because it is only one bit per signal, there can only be one signal pending of each type. Its possible that the process to which you want to send the signal is sleeping. If that process is sleeping at an interruptible priority, then the process will be awaken to handle the signal.
209              siginitset(&new_ka.sa.sa_mask, mask);          \par Whenever a new signal handler is registered by a process using the \textit{signal or sigaction} system call, the kernel updates invokes the sys\_signal function from \url{kernel/signal.c}, or the sys\_sigaction function from \url{acrh/i386/kernel/signal.c}. These functions update the various signal parameters within kernel signal information. Both of these functions call \textit{do\_sigaction} to update signal statistics.
210          }          \begin{verbatim}
211    
212          ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);           /* User space system call */
213            sighandler_t signal(int signum, sighandler_t handler);
214              __put_user(old_ka.sa.sa_flags, &oact->sa_flags);  
215              __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);           /* sys_signal function */
216            asmlinkage unsigned long
217          \end{verbatim}          sys_signal(int sig, __sighandler_t handler)
218            {
219          \newline \par The system call sigaction is used to modify the complete signal action associated with a signal rather than merely changing the handler. Hence, it takes the \textit{struct sigation} as function arguments. The kernel function sys\_sigaction uses \textit{\_\_get\_user}\footnote{\_\_get\_user is a privileged operation which works across system memory spaces, user and kernel. See also, copy\_from\_user.} to copy the new sigaction structure from user space to kernel space. And calls the do\_sigaction function. When the function returns, it calls \textit{\_\_put\_user} to copy the old sigaction structure from kernel space to user space.              struct k_sigaction new_sa, old_sa;
220                int ret;
221          \subsection{Function do\_sigaction}  
222          The function do\_sigaction is described below:              new_sa.sa.sa_handler = handler;
223          \begin{verbatim}              new_sa.sa.sa_flags = SA_ONESHOT | SA_NOMASK;
224    
225          int              ret = do_sigaction(sig, &new_sa, &old_sa);
226          do_sigaction(int sig, const struct k_sigaction *act, struct k_sigaction *oact)  
227          {              return ret ? ret : (unsigned long)old_sa.sa.sa_handler;
228              struct k_sigaction *k;          }
229    
230              if (sig < 1 || sig > _NSIG ||          \end{verbatim}
231                  (act && (sig == SIGKILL || sig == SIGSTOP)))  
232                      return -EINVAL;  /*  1. */          The function stores the passed handler into new signal handler and calls the do\_sigaction function. If the do\_sigaction function returns success, the old signal handler is returned to the calling process, which can be restored using another signal() system call.
233    
234              k = &current->sig->action[sig-1];  /*  2. */          \begin{verbatim}
235    
236              spin_lock(&current->sig->siglock);           /* User space system call */
237            int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
238              if (oact)  
239                  *oact = *k;   /*  3. */           /* sys_sigaction function */
240            asmlinkage int
241              if (act) {          sys_sigaction(int sig, const struct old_sigaction *act,
242                  *k = *act;    /*  4. */               struct old_sigaction *oact)
243                  sigdelsetmask(&k->sa.sa_mask, sigmask(SIGKILL) | sigmask(SIGSTOP));  
244             /* INCOMOPLETE CODE */
245                  if (k->sa.sa_handler == SIG_IGN  
246                      || (k->sa.sa_handler == SIG_DFL          if (act) {
247                          && (sig == SIGCONT ||              old_sigset_t mask;
248                              sig == SIGCHLD ||              __get_user(new_ka.sa.sa_flags, &act->sa_flags);
249                              sig == SIGWINCH ||              _get_user(mask, &act->sa_mask);
250                              sig == SIGURG))) {              siginitset(&new_ka.sa.sa_mask, mask);
251                          spin_lock_irq(&current->sigmask_lock);          }
252                          if (rm_sig_from_queue(sig, current))  
253                              recalc_sigpending();    /*  5. */          ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
254                          spin_unlock_irq(&current->sigmask_lock);  
255                  }              __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
256              }              __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
257    
258              spin_unlock(&current->sig->siglock);          \end{verbatim}
259              return 0;  
260          }          \\ \par The system call sigaction is used to modify the complete signal action associated with a signal rather than merely changing the handler. Hence, it takes the \textit{struct sigaction} as function arguments. The kernel function sys\_sigaction uses \textit{\_\_get\_user}\footnote{\_\_get\_user is a privileged operation which works across system memory spaces, user and kernel. See also, copy\_from\_user.} to copy the new sigaction structure from user space to kernel space. And calls the do\_sigaction function. When the function returns, it calls \textit{\_\_put\_user} to copy the old sigaction structure from kernel space to user space.
261    
262          \end{verbatim}          \subsection{Function do\_sigaction}
263            The function do\_sigaction is described below:
264          \begin{enumerate}          \begin{verbatim}
265          \item The function checks the validity of signal. And compares gig with SIGKILL, SIGSTOP because, Changing the signal handlers of SIGKILL or SIGSTOP is not allowed.  
266          \item The signal lock used for sigsignal handler for the signal is accessed from the sig field of the current process. Signals start with SIGHUP as number 1, and arrays start with number 0, hence [sig-1] is used.          int
267          \item  This signal handler is stored as old signal handler. The signal lock in the signal\_struct for the process is grabbed, here and released after pending signals are recalculated.          do_sigaction(int sig, const struct k_sigaction *act, struct k_sigaction *oact)
268          \item The new signal handler passed, is stored as signal handler in the current process sig field.          {
269          \item For the valid signals, the function removes the signal from the sigqueue and updates the sigqueue structure. For the valid signals, the function removes the signal from the sigqueue and updates the sigqueue structure. The inline function \textit{recalc\_sigpending} defined in \url{include/linux/sched.h} re-calculates signal pending state from the set of locally pending signals, globally pending signals, and blocked signals for the \textbf{current} process.              struct k_sigaction *k;
270          \begin{verbatim}  
271          static inline void recalc_sigpending(void)              if (sig < 1 || sig > _NSIG ||
272          {                  (act && (sig == SIGKILL || sig == SIGSTOP)))
273              if (has_pending_signals(&current->pending.signal, &current->blocked))                      return -EINVAL;  /*  1. */
274                  set_thread_flag(TIF_SIGPENDING);  
275              else              k = &current->sig->action[sig-1];  /*  2. */
276                  clear_thread_flag(TIF_SIGPENDING);  
277          }              spin_lock(&current->sig->siglock);
278          \end{verbatim}  
279          \end{enumerate}              if (oact)
280                    *oact = *k;   /*  3. */
281          \section{Sending Signals to process} \label{sig:send}  
282          % TODO              if (act) {
283          \subsection{Function send\_sig()}                  *k = *act;    /*  4. */
284          % TODO from entry.S                  sigdelsetmask(&k->sa.sa_mask, sigmask(SIGKILL) | sigmask(SIGSTOP));
285          % send_sig; send_sig_info; deliver_signal; send_signal, signal_wake_up  
286          % force_sig; force_sig_info;send_sig_info; deliver_signal; send_signal                  if (k->sa.sa_handler == SIG_IGN
287          \section{Response of processes to signals}                      || (k->sa.sa_handler == SIG_DFL
288          \subsection{Function do\_signal()}                          && (sig == SIGCONT ||
289          % TODO                              sig == SIGCHLD ||
290          % do_signal, handle_signal, setup_frame                              sig == SIGWINCH ||
291          \begin{verbatim}                              sig == SIGURG))) {
292           movl $__NR_sigreturn                          spin_lock_irq(&current->sigmask_lock);
293           int $0x80                          if (rm_sig_from_queue(sig, current))
294          \end{verbatim}                              recalc_sigpending();    /*  5. */
295                            spin_unlock_irq(&current->sigmask_lock);
296           The "\_\_NR\_sigreturn" system call helps the kernel to restore the previous thread's context. When the signal handler exits, it returns to an area in stack where the kernel had already set the trap to make the signal handler execute the system call transparently.                  }
297                }
298    
299                spin_unlock(&current->sig->siglock);
300                return 0;
301            }
302    
303            \end{verbatim}
304    
305            \begin{enumerate}
306            \item The function checks the validity of signal. And compares gig with SIGKILL, SIGSTOP because, Changing the signal handlers of SIGKILL or SIGSTOP is not allowed.
307            \item The signal lock used for sigsignal handler for the signal is accessed from the sig field of the current process. Signals start with SIGHUP as number 1, and arrays start with number 0, hence [sig-1] is used.
308            \item  This signal handler is stored as old signal handler. The signal lock in the signal\_struct for the process is grabbed, here and released after pending signals are recalculated.
309            \item The new signal handler passed, is stored as signal handler in the current process sig field.
310            \item For the valid signals, the function removes the signal from the sigqueue and updates the sigqueue structure. For the valid signals, the function removes the signal from the sigqueue and updates the sigqueue structure. The inline function \textit{recalc\_sigpending} defined in \url{include/linux/sched.h} re-calculates signal pending state from the set of locally pending signals, globally pending signals, and blocked signals for the \textbf{current} process.
311            \begin{verbatim}
312            static inline void recalc_sigpending(void)
313            {
314                if (has_pending_signals(&current->pending.signal, &current->blocked))
315                    set_thread_flag(TIF_SIGPENDING);
316                else
317                    clear_thread_flag(TIF_SIGPENDING);
318            }
319            \end{verbatim}
320            \end{enumerate}
321    
322            \section{Sending Signals to process} \label{sig:send}
323               When kernel wishes to send a signal to some process, it calls the function \textit{send\_sig}. If the signal needs to be forced, it calls the function \textit{force\_sig}. The difference between the two functions is that send\_sig has an optional parameter which can be passed to ignore the signal. The force\_sig function can not ignore the signal. The parameters is used to indicate whether the signal has come from USEP space or KERNEL space. The examples are given below:
324            \begin{enumerate} \label{sig:test}
325            \item send\_sig function. If segment violation occurs, send SIGSEGV signal. The siginfo structure value of 1, is dummy. This is explained in send\_signal function.[Section ~\ref{sig:sendsig}]
326            \begin{verbatim}
327            /*  kernel/exec\_domain.c */
328            default_handler(int segment, struct pt_regs *regp)
329            {
330                if (current_thread_info()->exec_domain->handler != default_handler)
331                    current_thread_info()->exec_domain->handler(segment, regp);
332                else
333                    send_sig(SIGSEGV, current, 1);
334            }
335            \end{verbatim}
336            \item force\_sig function. For trap exeption, send the signal using force\_sig.
337            \begin{verbatim}
338            /*  arch/i386/kernel/traps.c  */
339            trap_signal: {
340                  struct task_struct *tsk = current;
341                  tsk->thread.error_code = error_code;
342                  tsk->thread.trap_no = trapnr;
343                  force_sig(signr, tsk);
344            \end{verbatim}
345            \end{enumerate}
346             The send\_sig and force\_sig functions are explained below in detail.
347            \subsection{Functions send\_sig() \& force\_sig()}
348              The basic operation performed by both of theses is functions is to update the sigpending structure of process and wake that process to handle the signal. The kernel performs this in following steps. Note, All these functions are defined in \utl{kernel/signal.c}.
349            \begin{itemize}
350            \item \textit{send\_sig\_info()} \& \textit{force\_sig\_info()}
351                \par These functions are the wrappers for the send\_sig and force\_sig functions. They are kept for backward compatibility with the other kernel source. The force\_sig\_info function changes the signhandler from ignore [SIG\_IGN] to default [SIG\_DFL] and calls the send\_sig\_info function. Thus, from this point onwards both the functions show similar bahaviour.
352                \par The send\_sig\_info functions performs the signal sanity checks by checking for bad\_signal, ignored\_signal and calls the deliver\_signal function.
353    
354            \item \textit{bad\_signal()}
355                \par This function checks if the signal is valid or not. It also checks whether the effective process ids of the process are matching with the current process ids.
356    
357            \item \textit{handle\_stop\_signal()}
358                \par The function deals with the signals related to process stopping, viz. SIGKILL, SIGSTOP, SIGCONT, SIGSTP and so on. If any of these signals is to sent, it wakes up the process and then removes unwanted signals from signal queue.
359    
360            \item \textit{ignored\_signal()}
361                \par The function deals with ignoring or posting of the signal. The functions performs follwing actions depending on the signal type. The remaining set of functions are not invoked for signals of type 0.
362            \begin{verbatim}
363            *  Signal type:
364            *    < 0 : global action (kill - spread to all non-blocked threads)
365            *    = 0 : ignored
366            *    > 0 : wake up.
367            \end{verbatim}
368    
369            \item \textit{deliver\_signal()}
370                \par This function invokes the send\_signal function by passing the pending signals of the task as argument. If send\_signal returns Success [0], and if the signal to be send is NOT blocked by the process, it wakes up the receiving process.
371    
372            \section{Function send\_signal()} \label{sig:sendsig}
373            \item \textit{send\_signal()}
374            \begin{verbatim}
375            if (atomic_read(&nr_queued_signals) < max_queued_signals) {
376                q = kmem_cache_alloc(sigqueue_cachep, GFP_ATOMIC);
377            }
378    
379            if (q) {
380                atomic_inc(&nr_queued_signals);
381                q->next = NULL;
382                *signals->tail = q;
383                signals->tail = &q->next;
384                switch ((unsigned long) info) {
385                    case 0:
386                        q->info.si_signo = sig;
387                        q->info.si_errno = 0;
388                        q->info.si_code = SI_USER;
389                        q->info.si_pid = current->pid;
390                        q->info.si_uid = current->uid;
391                        break;
392                    case 1:
393                        q->info.si_signo = sig;
394                        q->info.si_errno = 0;
395                        q->info.si_code = SI_KERNEL;
396                        q->info.si_pid = 0;
397                        q->info.si_uid = 0;
398                        break;
399                    default:
400                        copy_siginfo(&q->info, info);
401                        break;
402                }
403            } else if (sig >= SIGRTMIN && info && (unsigned long)info != 1
404                   && info->si_code != SI_USER) {
405                return -EAGAIN;
406            }
407    
408            sigaddset(&signals->signal, sig);
409            return 0;
410    
411            \end{verbatim}
412                \par This function allocates a new sigqueue structure \footnote{The sigqueue is allocated by invoking \textit{kmem\_cache\_alloc()} function.} and updates it with the siginfo structure with the info passed as parameter to the function. It also, updated the sigpending structure of the process.
413            \par The siginfo structure carried from all the above functions is dummy. This can be verified from the test code seen above [~\ref{sig:test}]. This parameter differenciates the send\_sig or the force\_sig function. A value of 1 indicates that the forceful [KERNEL priviledged signal] and 0 indidates optional singal [coming from USER space].
414            \par Thus, at this point the sigqueue as well as the sigpending structure is updated.
415            \item \textit{signal\_wake\_up()}
416                \par This function sets the TASK-PENDING bit for the thread associated with the process. Then, if the process is in TASK\_RUNNING state, it calls the kick\_if\_running function. And if the process is in TASK\_INTERRUPTIBLE state, it calls function to wake it up [wake\_up\_process.]
417            \item \textit{kick\_if\_running()}
418                \par This function is SMP specific and defined in \url{kernel/sched.c}. If the task is running on the current CPU, it prohibites the remote CPUs from running the process to which the signal is to be sent, by rescheduling the tasks.
419            \item \textit{wake\_up\_process()}
420                \par This function is used to wake up the new process receiving the signal. Please refer to section ~\ref{sched:wakeup} for more details.
421            \end{itemize}
422    
423            \section{Invoking Signal handlers}
424            \par Thus, as we have seen in the above section, when a signal is send to a process, the signal structures for the destined process(viz. pending bits) are updated. The linux kernel checks for new signals while returning from an interrupt \textit{(ret\_from\_intr)}, before resuming execution in user space. This is checked for any pending work everytime an interrupt or exception is handled.
425            \\ \par The assemble code from \url{arch/i386/kernel/entry.S} is as follows:
426            \begin{verbatim}
427            ret_from_intr:
428                    preempt_stop
429                    DEC_PRE_COUNT(%ebx)
430            ret_from_exception:
431                    movl EFLAGS(%esp), %eax         # mix EFLAGS and CS
432                    movb CS(%esp), %al
433                    testl $(VM_MASK | 3), %eax
434                    jz resume_kernel                # returning to kernel or vm86-space
435            ENTRY(resume_userspace)
436                    cli  
437                    movl TI_FLAGS(%ebx), %ecx
438                    andl $_TIF_WORK_MASK, %ecx      # is there any work to be done
439                    jne work_pending
440                    jmp restore_all
441    
442            work_pending:
443                    testb $_TIF_NEED_RESCHED, %cl
444                    jz work_notifysig
445    
446            work_notifysig:                         # deal with pending signals and
447                                                    # notify-resume requests
448                    testl $(VM_MASK),EFLAGS(%esp)
449                    movl %esp, %eax
450                    jne work_notifysig_v86          # returning to kernel-space or
451                                                    # vm86-space
452                    xorl %edx, %edx
453                    call do_notify_resume
454                    jmp restore_all
455            \end{verbatim}
456                As shown in the code above, the kernel checks for work\_pending in ret\_from\_intr and ret\_from\_exception. Later, it checks if any non-blocking signals are pending and need servicing and calls the \textit{do\_notify\_resume} function from \url{arch/i386/kernel/signal.c} which effectively calls the famous \textit{do\_signal} function.
457    
458            \subsection{Function do\_signal()}
459                The do\_signal function checks the priviledge level of code segment that entered here. The lower two bits of the segment selector indicate the priviledge level. 0 (binary 00) indicate kernel mode while 3 (binary 11) indicate user mode. If a kernel segment enters here, the function returns back quitely.
460    
461            \begin{verbatim}
462            /* INCOMPLETE CODE */
463            int do_signal(struct pt_regs *regs, sigset_t *oldset)
464            {
465                if ((regs->xcs & 3) != 3)
466                    return 1;
467                signr = get_signal_to_deliver(&info, regs);
468                if (signr > 0) {
469                    handle_signal(signr, &info, oldset, regs);
470                    return 1;
471                }
472            }
473            \end{verbatim}
474                Then, the function collects all the signals that need to be delivered using \textit{get\_signal\_to\_deliver}. This function dequeues the signals by repetadely calling \textit{dequeu\_signal} from the signal queue, till there are no pending signals. It also checks for special conditions of signals, e.g. SIGKILL, SIGSTOP, SIGCHLD. If they exits, it notifies the parent process and calls \textit{schedule()} function. Refer to \url{kernel/signal.c} for the architecture independant function. The function deals with the system offered signal handlers here, viz. for signals SIGCONT, SIGSTOP, SIGTTIN, SIGABRT, SIGTRAP, SIGSEGV. The special signals for which the process has registered its own handlers are dealt by calling function \textit{handle\_signal} to dispatch them to the user space processes. The complete mechanism is described below:
475    
476            \subsubsection{User space signal handlers}
477                A signal handler represents a thread of execution in user space just like the main program. They can open files, write files, issue system calls that sleep, and do anything bounded by user privileges.
478            \par The only fuzzy thing about signal handlers is that neither the main thread of execution directly call the signal handler nor it knows where it returns. Hence, signal handlers are special, in the sense that \textbf{Signal handlers are functions written in user space and invoked by the kernel. They execute with the priviledge level of user space}.
479            \par To achieve this, while delivering signal to user space process, the kernel saves the context of the current thread of execution in user space on the userstack and overwrite the calling process's thread context (one inside the kernel space) with the signal handlers context.
480            \\ \par The code is explained below:
481            \begin{verbatim}
482            static void
483            handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
484                struct pt_regs * regs)
485            {
486                struct k_sigaction *ka = &current->sig->action[sig-1];
487                /* INCOMPLETE CODE */
488                /* Set up the stack frame */
489                if (ka->sa.sa_flags & SA_SIGINFO)
490                    setup_rt_frame(sig, ka, info, oldset, regs);
491                else
492                    setup_frame(sig, ka, oldset, regs);
493            }
494            \end{verbatim}
495               The function handle\_signal calls the function setup\_frame or setup\_rt\_frame to set up the environment to execute user space signal handler and return back to kernel mode. both of these functions are similar, with only the difference in frame structure. The setup\_rt\_frame() uses extended frame with an additional element of siginfo structure. Refer to \url{arch/i386/kernel/signal.c} for structures of \textit{sigframe} and \textit{rt\_sigframe}. We describe the setup\_frame function below:
496    
497            \subsubsection{Function setup\_frame()}
498            \begin{verbatim}
499            static void setup_frame(int sig, struct k_sigaction *ka,
500                     sigset_t *set, struct pt_regs * regs)
501            {
502                struct sigframe *frame;
503                int err = 0;
504    
505                frame = get_sigframe(ka, regs, sizeof(*frame));  /*  1. */
506    
507                if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
508                    goto give_sigsegv;
509    
510                err |= __put_user((current_thread_info()->exec_domain
511                           && current_thread_info()->exec_domain->signal_invmap
512                           && sig < 32
513                           ? current_thread_info()->exec_domain->signal_invmap[sig]
514                           : sig),
515                          &frame->sig);        /*  2. */
516                if (err)
517                    goto give_sigsegv;
518                err |= setup_sigcontext(&frame->sc, &frame->fpstate, regs, set->sig[0]);
519                if (err)          /*  3. */
520                    goto give_sigsegv;
521    
522                if (_NSIG_WORDS > 1) {
523                    err |= __copy_to_user(frame->extramask, &set->sig[1],
524                              sizeof(frame->extramask));   /*  4. */
525                }
526                if (err)
527                    goto give_sigsegv;
528    
529                /* Set up to return from userspace.  If provided, use a stub
530                   already in userspace.  */
531                if (ka->sa.sa_flags & SA_RESTORER) {
532                    err |= __put_user(ka->sa.sa_restorer, &frame->pretcode);
533                } else {
534                    err |= __put_user(frame->retcode, &frame->pretcode);
535                    /* This is popl %eax ; movl $,%eax ; int $0x80 */
536                    err |= __put_user(0xb858, (short *)(frame->retcode+0));
537                    err |= __put_user(__NR_sigreturn, (int *)(frame->retcode+2));
538                    err |= __put_user(0x80cd, (short *)(frame->retcode+6));
539                }   /*   5.  */
540    
541                if (err)
542                    goto give_sigsegv;
543                /* Set up registers for signal handler */
544                regs->esp = (unsigned long) frame;            /*  6. */
545                regs->eip = (unsigned long) ka->sa.sa_handler;
546    
547                set_fs(USER_DS);
548                regs->xds = __USER_DS;
549                regs->xes = __USER_DS;
550                regs->xss = __USER_DS;     /*  7.  */
551                regs->xcs = __USER_CS;
552                regs->eflags &= ~TF_MASK;
553                return;
554    
555            give_sigsegv:
556                if (sig == SIGSEGV)
557                    ka->sa.sa_handler = SIG_DFL;    /*  8.  */
558                force_sig(SIGSEGV, current);
559    
560            \end{verbatim}
561    
562            Initially, the function obtains the appropriate signal frame structure and then calls functions to populate the elements of the sigframe structure.
563            \begin{verbatim}
564    
565            struct sigframe
566            {
567                    char *pretcode;
568                    int sig;
569                    struct sigcontext sc;
570                    struct _fpstate fpstate;
571                    unsigned long extramask[_NSIG_WORDS-1];
572                    char retcode[8];
573            };
574            \end{verbatim}
575    
576            \begin{enumerate}
577            \item Initially, the function calls get\_sigframe to get frame pointer. This pointer is obtained from the esp (Stack pointer) minus frame size or restorer function pointer if defined. The pointer vulue is cast to sigframe type and used as user mode frame pointer.
578            \item Then, the function checks whether the associated exec domain (binary interface) uses reverse signal mappings. If yes, the sig number is saved in the frame using reverse mapping. Otherwise, it is simply copied to stack frame.
579            \item Then, the function sets up the signal context for the frame. This involves copying the elements (viz xes, cx, eip, thread info ) of the sigcontext to the stack frame using \textit{\_\_put\_user()} call. Refer to \url{include/asm-i386/sigcontext.h} for sigcontext structure elements. It also copies the floating point registers needed for the frame using \texit{save\_i387()} function call from \url{arch/i386/kernel/i387.c}.
580            \item Then, the function copies the extramask used for real time signals to new frame.
581            \item This is an important step. The function sets up the sigreturn system call to return back to kernel space after execution of signal handler. This is achieved by invoking sigreturn system call; \textbf{int 0x80h}.
582            \item Then, the function sets the instruction pointer and stack frame appropriately so that the signal handler is ready to start execution. So at the end of this function, the current process resumes execution in user mode, with the signal handler.
583            \item The function also sets up all segment registers used by the segmentation mechanism to point to user space areas and the signal handler execution begins.
584            \item In case, the code violates any segments boundaries and tries to access restricted pages, a segment violation fault is triggered.
585            \end{enumerate}
586    
587            \subsubsection{Signal handler termination}
588            \begin{verbatim}
589             movl $__NR_sigreturn
590             int $0x80
591            \end{verbatim}
592    
593             The "\_\_NR\_sigreturn" system call helps the kernel to restore the previous thread's context. When the signal handler exits, it returns to an area in stack where the kernel had already set the trap to make the signal handler execute the system call transparently.
594    
595            \begin{image}
596            \begin{verbatim}
597            -----------------------------   <----- ESP when a sig Handler is invoked.
598                Return Address    --------------------------
599            -----------------------------                   |
600                sigNumber                                   |                               |
601            -----------------------------                   |
602                struct sigcontext                           |
603            ( includes the entire register context )        |
604            -----------------------------                   |
605                fpstate                                     |
606            -----------------------------                   |
607                extra mask[]                                |
608            -----------------------------                   |
609                popl %eax <---------------------------------
610                movl $__NR_sigreturn
611                int $0x80
612            -----------------------------
613            /*
614             *    STACK high address. Grows upwards.
615             *    The entire context of previous thread is accessible to the
616             *    signal handler althoug this is not documented. One can
617             *    verify this information with the linux kernel sources.
618             *    See the data structure "struct sigframe".
619             */
620    
621            asmlinkage int sys_sigreturn(unsigned long __unused)
622            {
623                /* INCOMPLETE CODE */
624                struct sigframe *frame = (struct sigframe *)(regs->esp - 8);
625    
626                if (restore_sigcontext(regs, &frame->sc, &eax))
627                    goto badframe;
628                return eax;
629            }
630    
631            \end{verbatim}
632            \end{image}
633            When the sigreturn system call is invoked, it calls sys\_sigreturn kernel function to return to kernel mode. The kernel stack frame is retrived using the esp pointer of regs.\footnote{Recall that the function arguments to a system call are not passed through the stack frame, but using the CPU registers.}. The complete kernel signal context is restored back by calling \texit{restore\_signcontext} which sets upt the appropriate values of segments (fs,cs,es) and registers(esp, esi, eip) etc.

Legend:
Removed from v.1.2  
changed lines
  Added in v.1.3

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26