1 |
\chapter{System calls \& Signals} |
\chapter{System calls \& Signals} |
2 |
|
|
3 |
\section{User to Kernel space using system\_call()} |
\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. |
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. |
6 |
\par Each system call 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. The system calls are defined in the file \url{include/asm-i386/unistd.h} |
\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 |
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 |
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 ~\ref{Appendix 2}.} 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 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. |
9 |
The system\_call code and the sys\_call\_table is defined in the asm code \url{arch/i386/kernel/entry.S} |
\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} |
11 |
% TODO explain code |
% TODO explain code |
12 |
\begin{verbatim} |
\begin{verbatim} |
13 |
|
|
14 |
ENTRY(system_call) # LINE : 230 |
ENTRY(system_call) # LINE : 230 |
15 |
pushl %eax # save orig_eax |
pushl %eax # save orig_eax |
16 |
SAVE_ALL |
SAVE_ALL |
32 |
jne syscall_exit_work |
jne syscall_exit_work |
33 |
restore_all: |
restore_all: |
34 |
RESTORE_ALL |
RESTORE_ALL |
35 |
|
|
36 |
\end{verbatim} |
\end{verbatim} |
37 |
% TODO examples , fork -> sys_fork |
% TODO examples , fork -> sys_fork |
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 |
42 |
|
|
43 |
\begin{verbatim} |
\begin{verbatim} |
44 |
|
|
45 |
ALIGN |
ALIGN |
46 |
work_pending: |
work_pending: |
47 |
testb $_TIF_NEED_RESCHED, %cl |
testb $_TIF_NEED_RESCHED, %cl |
57 |
jz restore_all |
jz restore_all |
58 |
testb $_TIF_NEED_RESCHED, %cl |
testb $_TIF_NEED_RESCHED, %cl |
59 |
jnz work_resched |
jnz work_resched |
60 |
|
|
61 |
\end{verbatim} |
\end{verbatim} |
62 |
|
|
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. |
\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. |
64 |
\begin{verbatim} |
\begin{verbatim} |
65 |
|
|
66 |
.data |
.data |
67 |
ENTRY(sys_call_table) |
ENTRY(sys_call_table) |
68 |
.long sys_ni_syscall /* 0 - old "setup()" system call*/ |
.long sys_ni_syscall /* 0 - old "setup()" system call*/ |
78 |
.rept NR_syscalls-(.-sys_call_table)/4 |
.rept NR_syscalls-(.-sys_call_table)/4 |
79 |
.long sys_ni_syscall |
.long sys_ni_syscall |
80 |
.endr |
.endr |
81 |
|
|
82 |
\end{verbatim} |
\end{verbatim} |
83 |
|
|
84 |
\section{Signal data structure in a process} |
\section{Signal data structure in a process} \label{sig:structs} |
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. |
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 |
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. |
\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. |
87 |
The process structure [task\_struct] contains following structures related to signals. These are described below, in details. |
\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. |
89 |
|
|
90 |
\begin{verbatim} |
\begin{verbatim} |
91 |
/* signal handlers */ |
|
92 |
|
/* signal handlers */ |
93 |
spinlock_t sigmask_lock; /* Protects signal and blocked */ |
spinlock_t sigmask_lock; /* Protects signal and blocked */ |
94 |
struct signal_struct *sig; /* signal structure */ |
struct signal_struct *sig; /* signal structure */ |
95 |
|
|
101 |
int (*notifier)(void *priv); |
int (*notifier)(void *priv); |
102 |
void *notifier_data; |
void *notifier_data; |
103 |
sigset_t *notifier_mask; /* new signal notification bit mask */ |
sigset_t *notifier_mask; /* new signal notification bit mask */ |
104 |
|
|
105 |
\end{verbatim} |
\end{verbatim} |
106 |
|
|
107 |
The signal\_struct is a generic signal structure defined in \url{include/linux/sched.h}. This contains the singal count per process and the spin-lock to protect the signals over multiple CPUs. It also contains an array of size \_NSIG \footnote{NSIG is the maximum number of singals supported.} and of type k\_sigaction defined below. |
\subsection{signal\_struct} \index{signal\_struct} |
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. |
109 |
\begin{verbatim} |
\begin{verbatim} |
110 |
|
|
111 |
struct signal_struct { |
struct signal_struct { |
112 |
atomic_t count; |
atomic_t count; |
113 |
struct k_sigaction action[_NSIG]; |
struct k_sigaction action[_NSIG]; |
114 |
spinlock_t siglock; |
spinlock_t siglock; |
115 |
}; |
}; |
116 |
|
|
117 |
|
struct k_sigaction { |
118 |
|
struct sigaction sa; |
119 |
|
}; |
120 |
|
|
121 |
\end{verbatim} |
\end{verbatim} |
122 |
|
|
123 |
The 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. |
\subsection{sigset\_t and struct sigaction} |
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 |
|
|
126 |
\begin{verbatim} |
\begin{verbatim} |
127 |
|
|
132 |
#define _NSIG 64 |
#define _NSIG 64 |
133 |
#define _NSIG_BPW 32 |
#define _NSIG_BPW 32 |
134 |
#define _NSIG_WORDS (_NSIG / _NSIG_BPW) |
#define _NSIG_WORDS (_NSIG / _NSIG_BPW) |
135 |
|
|
136 |
|
typedef unsigned long old_sigset_t; |
137 |
|
|
138 |
#else |
#else |
139 |
|
|
140 |
#define NSIG 32 |
#define NSIG 32 |
142 |
|
|
143 |
#endif |
#endif |
144 |
|
|
145 |
|
struct sigaction { |
146 |
|
__sighandler_t sa_handler; |
147 |
|
unsigned long sa_flags; |
148 |
|
void (*sa_restorer)(void); |
149 |
|
sigset_t sa_mask; /* mask last for extensibility */ |
150 |
|
}; |
151 |
|
|
152 |
\end{verbatim} |
\end{verbatim} |
153 |
|
|
154 |
|
\subsection{struct sigpending} |
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. |
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. |
156 |
\begin{verbatim} |
\begin{verbatim} |
157 |
|
|
158 |
struct sigpending { |
struct sigpending { |
159 |
struct sigqueue *head, **tail; |
struct sigqueue *head, **tail; |
160 |
sigset_t signal; |
sigset_t signal; |
161 |
}; |
}; |
162 |
|
|
163 |
\end{verbatim} |
\end{verbatim} |
164 |
|
|
165 |
\section{Sending Signal to process} |
\section{Registering Signals} \label{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. |
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 |
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. |
\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. |
168 |
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. |
\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. |
|
Whenever a new signal handler is registered by a process using the signal system call, the kernel updates invokes the sys\_signal function from \url{kernel/signal.c}. This function updates the various signal parameters within kernel signal information. |
|
169 |
\begin{verbatim} |
\begin{verbatim} |
170 |
|
|
171 |
/* User space system call */ |
/* User space system call */ |
172 |
sighandler_t signal(int signum, sighandler_t handler); |
sighandler_t signal(int signum, sighandler_t handler); |
173 |
|
|
189 |
\end{verbatim} |
\end{verbatim} |
190 |
|
|
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. |
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. |
|
% TODO do_sigaction |
|
192 |
|
|
193 |
\begin{verbatim} |
\begin{verbatim} |
194 |
|
|
195 |
|
/* User space system call */ |
196 |
|
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact); |
197 |
|
|
198 |
|
/* sys_sigaction function */ |
199 |
|
asmlinkage int |
200 |
|
sys_sigaction(int sig, const struct old_sigaction *act, |
201 |
|
struct old_sigaction *oact) |
202 |
|
|
203 |
|
/* INCOMOPLETE CODE */ |
204 |
|
|
205 |
|
if (act) { |
206 |
|
old_sigset_t mask; |
207 |
|
__get_user(new_ka.sa.sa_flags, &act->sa_flags); |
208 |
|
_get_user(mask, &act->sa_mask); |
209 |
|
siginitset(&new_ka.sa.sa_mask, mask); |
210 |
|
} |
211 |
|
|
212 |
|
ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); |
213 |
|
|
214 |
|
__put_user(old_ka.sa.sa_flags, &oact->sa_flags); |
215 |
|
__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); |
216 |
|
|
217 |
|
\end{verbatim} |
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. |
220 |
|
|
221 |
|
\subsection{Function do\_sigaction} |
222 |
|
The function do\_sigaction is described below: |
223 |
|
\begin{verbatim} |
224 |
|
|
225 |
|
int |
226 |
|
do_sigaction(int sig, const struct k_sigaction *act, struct k_sigaction *oact) |
227 |
|
{ |
228 |
|
struct k_sigaction *k; |
229 |
|
|
230 |
|
if (sig < 1 || sig > _NSIG || |
231 |
|
(act && (sig == SIGKILL || sig == SIGSTOP))) |
232 |
|
return -EINVAL; /* 1. */ |
233 |
|
|
234 |
|
k = ¤t->sig->action[sig-1]; /* 2. */ |
235 |
|
|
236 |
|
spin_lock(¤t->sig->siglock); |
237 |
|
|
238 |
|
if (oact) |
239 |
|
*oact = *k; /* 3. */ |
240 |
|
|
241 |
|
if (act) { |
242 |
|
*k = *act; /* 4. */ |
243 |
|
sigdelsetmask(&k->sa.sa_mask, sigmask(SIGKILL) | sigmask(SIGSTOP)); |
244 |
|
|
245 |
|
if (k->sa.sa_handler == SIG_IGN |
246 |
|
|| (k->sa.sa_handler == SIG_DFL |
247 |
|
&& (sig == SIGCONT || |
248 |
|
sig == SIGCHLD || |
249 |
|
sig == SIGWINCH || |
250 |
|
sig == SIGURG))) { |
251 |
|
spin_lock_irq(¤t->sigmask_lock); |
252 |
|
if (rm_sig_from_queue(sig, current)) |
253 |
|
recalc_sigpending(); /* 5. */ |
254 |
|
spin_unlock_irq(¤t->sigmask_lock); |
255 |
|
} |
256 |
|
} |
257 |
|
|
258 |
|
spin_unlock(¤t->sig->siglock); |
259 |
|
return 0; |
260 |
|
} |
261 |
|
|
262 |
|
\end{verbatim} |
263 |
|
|
264 |
|
\begin{enumerate} |
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. |
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. |
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. |
270 |
|
\begin{verbatim} |
271 |
|
static inline void recalc_sigpending(void) |
272 |
|
{ |
273 |
|
if (has_pending_signals(¤t->pending.signal, ¤t->blocked)) |
274 |
|
set_thread_flag(TIF_SIGPENDING); |
275 |
|
else |
276 |
|
clear_thread_flag(TIF_SIGPENDING); |
277 |
|
} |
278 |
|
\end{verbatim} |
279 |
|
\end{enumerate} |
280 |
|
|
281 |
|
\section{Sending Signals to process} \label{sig:send} |
282 |
|
% TODO |
283 |
|
\subsection{Function send\_sig()} |
284 |
|
% TODO from entry.S |
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 |
287 |
|
\section{Response of processes to signals} |
288 |
|
\subsection{Function do\_signal()} |
289 |
|
% TODO |
290 |
|
% do_signal, handle_signal, setup_frame |
291 |
|
\begin{verbatim} |
292 |
movl $__NR_sigreturn |
movl $__NR_sigreturn |
293 |
int $0x80 |
int $0x80 |
294 |
\end{verbatim} |
\end{verbatim} |
295 |
|
|
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. |
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 |
|
|
|
\section{Responce of processes to signals} |
|