1 |
\chapter{Process Creation} |
\chapter{Process Management} |
2 |
\section{Process 0 swapper} |
\section{Process 0 swapper} |
3 |
When the CPU switches from real mode to protected mode, it initializes segmentation and paging. Then, it sets up execution environment for the process 0\index{swapper} [swapper]. The assembly code to create the startup swapper proces is in the file \url{arch/i386/kernel/head.S}. |
When the CPU switches from real mode to protected mode, it initializes segmentation and paging. Then, it sets up execution environment for the process 0\index{swapper} [swapper]. The assembly code to create the startup swapper proces is in the file \url{arch/i386/kernel/head.S}. |
4 |
|
% TODO startup_32 \index {startup\_32} |
|
% TODO startup_32 |
|
5 |
% TODO init_idle |
% TODO init_idle |
6 |
|
|
7 |
\section{Process 1 init} |
\section{Process 1 init} \index{init} |
8 |
After the initialization of paging, memory and timers in the start\_kernel function, kernel threads \index{kernel\_thread} are created. The function kernel\_thread() is defined in \url{arch/i386/kernel/process.c} and called from the initialization routine start\_kernel (Refer to section~\ref{init:sk}). |
After the initialization of paging, memory and timers in the \textit{start\_kernel} function, kernel threads \index{kernel\_thread} are created. The function \textit{kernel\_thread()} is defined in \url{arch/i386/kernel/process.c} and called from the initialization routine start\_kernel (Refer to section~\ref{init:sk}). |
9 |
|
|
10 |
|
\subsection{kernel\_thread} \label{proc:kt} \index{kernel\_thread} |
11 |
% TODO kernel_thread |
% TODO kernel_thread |
12 |
|
|
13 |
\par The init function (fn parameter to kernel\_thread) locks the kernel and performs the basic setup related to foll. items. |
\par The init function (fn parameter to kernel\_thread) locks the kernel and performs the basic setup related to foll. items. |
14 |
|
|
15 |
Function : do\_basic\_setup |
\newline \textbf{Function : do\_basic\_setup} \newline |
16 |
The function do\_basic\_setup starts a migration thread, context thread and performs socket initialization. |
The function do\_basic\_setup starts a migration thread, context thread and performs socket initialization. |
17 |
|
|
18 |
\begin{description} |
\begin{description} |
19 |
\item[migration thread] \index{migration\_thread} A migration thread (kernel\_thread) is started by calling migration\_init function [ \url{kernel/sched.c} ] for all cpus. Refer to ~\ref{smp:boot} for SMP initialization details. |
\item[migration thread] \index{migration\_thread} A migration thread (kernel\_thread) is started by calling \textit{migration\_init} function [\url{kernel/sched.c} ] for all cpus. Refer to section ~\ref{smp:all} for SMP initialization details. |
20 |
% migration _thread |
|
21 |
|
\subsection{migration\_thread} \label{proc:mt} \index{migration\_thread} |
22 |
|
% TODO migration _thread |
23 |
\begin{verbatim} |
\begin{verbatim} |
24 |
|
|
25 |
/* Note, smp_num_cpus is configured during smp boot process |
/* Note, smp_num_cpus is configured during smp boot process |
26 |
in smp_boot_cpu function in arch/i386/kernel/smpboot.c |
in smp_boot_cpu function in arch/i386/kernel/smpboot.c |
27 |
*/ |
*/ |
30 |
CLONE\_FS | CLONE\_FILES | CLONE\_SIGNAL) < 0) |
CLONE\_FS | CLONE\_FILES | CLONE\_SIGNAL) < 0) |
31 |
BUG(); |
BUG(); |
32 |
} |
} |
33 |
|
|
34 |
\end{verbatim} |
\end{verbatim} |
35 |
\item[Sockets] Performs initialization related to sockets. The function sock\_init is defined in \url{net/socket.c}. |
\item[Sockets] Performs initialization related to sockets. The function sock\_init is defined in \url{net/socket.c}. |
36 |
% TODO kern_mount NFS mount |
% TODO kern_mount NFS mount |
37 |
\item[context\_thread] The function start\_context\_thread creates a kernel\_thread named context\_thread. The function is defined in \url{kernel/context.c} |
\item[context\_thread] The function start\_context\_thread creates a kernel\_thread named context\_thread. The function is defined in \url{kernel/context.c} |
38 |
\begin{verbatim} |
\begin{verbatim} |
39 |
|
|
40 |
kernel_thread(context_thread, NULL, CLONE_FS | CLONE_FILES); |
kernel_thread(context_thread, NULL, CLONE_FS | CLONE_FILES); |
41 |
|
|
42 |
\end{verbatim} |
\end{verbatim} |
43 |
|
|
44 |
\item[init\_calls] The function do\_init\_call flushes the pending tasks in the init queue, if any. |
\item[init\_calls] The function do\_init\_call flushes the pending tasks in the init queue, if any. |
45 |
\end{description} |
\end{description} |
46 |
|
|
47 |
% TODO prepare_namespace, dup |
\par The init function opens a console (viz. /dev/console) and finally, executes the "/sbin/init" or "/etc/init" or "/bin/init" or "/bin/sh" program (in this priority order). |
|
\par The init function opens a console (viz. /dev/console) and finally, executes the "/sbin/init" or "/etc/init" or "/bin/init" or "/bin/sh" (in this order) program. |
|
48 |
|
|
49 |
\par The code is explained below. |
\newline \par The code is explained below. |
50 |
|
|
51 |
\begin{verbatim} |
\begin{verbatim} |
52 |
|
|
53 |
lock_kernel(); |
lock_kernel(); |
54 |
do_basic_setup(); |
do_basic_setup(); |
55 |
|
|
69 |
execve("/bin/init",argv_init,envp_init); |
execve("/bin/init",argv_init,envp_init); |
70 |
execve("/bin/sh",argv_sh,envp_init); |
execve("/bin/sh",argv_sh,envp_init); |
71 |
panic("No init found. Try passing init= option to kernel."); |
panic("No init found. Try passing init= option to kernel."); |
72 |
|
|
73 |
\end{verbatim} |
\end{verbatim} |
74 |
|
|
75 |
The init program is the first process run after the kernel is up. It is configured with the "/etc/inittab" file. It contains following system configuration. |
\subsection{Namespaces} \index{prepare\_namespace} |
76 |
|
% TODO prepare_namespace, dup |
77 |
|
The function calls prepare\_namespace. |
78 |
|
|
79 |
|
\subsection{Function init()} \index{init} |
80 |
|
\newline \par The \textit{init} program is the first process run after the kernel is up. It is configured with the "/etc/inittab" file. It contains following system configuration. |
81 |
|
|
82 |
\begin{description} |
\begin{description} |
83 |
\item[Runlevel] Start up system run level. |
\item[Runlevel] Start up system run level. |
87 |
\item[Other prcesses] Certain actions or processes to be run if certain signals or user actions are indicated. |
\item[Other prcesses] Certain actions or processes to be run if certain signals or user actions are indicated. |
88 |
\end{description} |
\end{description} |
89 |
|
|
90 |
\section{Structures} |
\section{Structures} |
91 |
Within the linux kernel, every process is associated with a process descriptor defined by struct task\_struct\footnote{defined in \url{include/linux/sched.h}}. The structure contains various information related to process state, process threads, executable domain, process priority, signals, parent child relationships,filesystems and various limits. All the elements of these structure are initialized when a new process is created and destroyed when the process terminates. In order to understand process scheduling, it is necessary to understand how these scheduling information is initialized. This is explained in \label{do_fork} do\_fork function. Following paragraph describes the task\_struct in detail. |
Within the linux kernel, every process is associated with a process descriptor defined by struct \textit{task\_struct} \footnote{defined in \url{include/linux/sched.h}}. The structure contains various information related to process state, process threads, executable domain, process priority, signals, parent child relationships,filesystems and various limits. All the elements of these structure are initialized when a new process is created and destroyed when the process terminates. In order to understand process scheduling, it is necessary to understand how these scheduling information is initialized. This is explained in the do\_fork ~\ref{proc:do_fork} function. First we shall describe the \textit{task\_struct} in detail. |
92 |
|
|
93 |
|
\subsection{The process [task\_struct] structure} \index{task\_struct} |
94 |
% TODO task_struct and others |
% TODO task_struct and others |
95 |
|
|
96 |
\section{Creating New process} |
\section{Creating New process} |
97 |
|
|
98 |
% TODO dup resource , copy on write , __clone LWP , _syscall |
% TODO dup resource , copy on write , __clone LWP , _syscall |
99 |
Linux kernel 2.4 supports 3 types of processes. |
Linux kernel 2.4 supports 3 types of processes. |
100 |
\begin{description} |
\begin{description} |
101 |
\item[\large{1. idle threads}] |
\item[\large{1. idle threads}] |
102 |
\par The idle thread is created after initialization for the first CPU while for others, it is created by calling fork\_by\_hand() in \url{arch/i386/kernel/smpboot.c}. Idle tasks are unique per cpu with a pid of 0. |
\par The idle thread is created after initialization for the first CPU while for others, it is created by calling fork\_by\_hand() in \url{arch/i386/kernel/smpboot.c}. Idle tasks are unique per cpu with a pid of 0. |
103 |
\item[\large{2. kernel threads}] |
\item[\large{2. kernel threads}] |
104 |
\par Kernel threads are created using kernel\_thread() function. The "fn" argument is the function which starts executing in daemon mode using the daemonize() function. |
\par Kernel threads are created using kernel\_thread() function. The "fn" argument is the function which starts executing in daemon mode using the daemonize() function. |
105 |
|
|
106 |
Example of a kernel\_thread : |
\begin{minipage}{0.90\textwidth} |
107 |
In order to create a migration\_thread, kernel\_thread is created in the function migration\_init. Refer to \url{kernel/sched.c} for each cpu. |
Example of a kernel\_thread : |
108 |
|
In order to create a migration\_thread, kernel\_thread is created in the function migration\_init. Refer to \url{kernel/sched.c} for each cpu. |
109 |
\begin{verbatim} |
\begin{verbatim} |
110 |
|
|
111 |
for (cpu = 0; cpu < smp\_num\_cpus; cpu++) { |
for (cpu = 0; cpu < smp\_num\_cpus; cpu++) { |
112 |
if (kernel\_thread(migration\_thread, (void *) (long) cpu, |
if (kernel\_thread(migration\_thread, (void *) (long) cpu, |
113 |
CLONE\_FS | CLONE\_FILES | CLONE\_SIGNAL) < 0) |
CLONE\_FS | CLONE\_FILES | CLONE\_SIGNAL) < 0) |
114 |
BUG(); |
BUG(); |
115 |
} |
} |
116 |
|
|
117 |
\end{verbatim} |
\end{verbatim} |
118 |
The function migration\_init daemonizes itself. |
The function migration\_init daemonizes itself. |
119 |
\begin{verbatim} |
\begin{verbatim} |
120 |
|
|
121 |
static int migration\_thread(void * bind\_cpu) { |
static int migration\_thread(void * bind\_cpu) { |
122 |
int ret; |
int ret; |
123 |
\end{verbatim} |
\end{verbatim} |
126 |
sigfillset(¤t->blocked); |
sigfillset(¤t->blocked); |
127 |
set\_fs(KERNEL\_DS); |
set\_fs(KERNEL\_DS); |
128 |
} |
} |
129 |
|
|
130 |
\end{verbatim} |
\end{verbatim} |
131 |
|
\end{minipage} \end{center} |
132 |
|
|
133 |
\item[\large{3. user tasks}] |
\item[\large{3. user tasks}] |
134 |
\par user tasks are generally created by user applications using fork() or clone() function calls. |
\par user tasks are generally created by user applications using fork() or clone() function calls. |
135 |
\end{description} |
\end{description} |
136 |
|
|
137 |
\section{fork, clone calls and the do\_fork function} |
\section{fork, clone system calls} |
138 |
New processes are created by using fork, clone, vfork system calls. 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 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. |
New processes are created by using fork, clone, vfork system calls. 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 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. |
139 |
\par These functions are defined in \url{arch/i386/kernel/process.c} |
\par These functions are defined in \url{arch/i386/kernel/process.c} while the system call numbers are defined in \url{include/asm-i386/unistd.h} |
|
while the system call numbers are defined in \url{include/asm-i386/unistd.h} |
|
140 |
|
|
141 |
\par Example of fork system call : |
\par Example of fork system call : \index{fork} |
142 |
|
|
143 |
\begin{enumerate} |
\begin{enumerate} |
144 |
\item User calls fork(); |
\item User calls fork(); |
148 |
\item Kernel exits the handler by calling ret\_from\_sys\_call(); |
\item Kernel exits the handler by calling ret\_from\_sys\_call(); |
149 |
\end{enumerate} |
\end{enumerate} |
150 |
|
|
151 |
\par When a new process is created using fork/clone/vfork system call, kernel executes sys\_fork/sys\_clone/sys\_vfork function respectively, defined in \url{arch/i386/kernel/process.c}. These functions are architecture specific which call the generic function do\_fork to create the new process. The first "flags" parameter is properly substituted and the function do\_fork is invoked. |
\par When a new process is created using fork/clone/vfork system call, kernel executes sys\_fork/sys\_clone/sys\_vfork function respectively, defined in \url{arch/i386/kernel/process.c}. These functions are architecture specific which call the generic function do\_fork to create the new process. The first "flags" parameter is properly substituted and the function do\_fork is invoked. |
152 |
|
|
153 |
|
\newline \par Example of sys\_clone function : |
154 |
|
|
|
\par Example of sys\_clone function : |
|
|
|
|
155 |
\begin{verbatim} |
\begin{verbatim} |
156 |
|
|
157 |
asmlinkage int sys_clone(struct pt_regs regs) |
asmlinkage int sys_clone(struct pt_regs regs) |
158 |
{ |
{ |
159 |
struct task_struct *p; |
struct task_struct *p; |
166 |
p = do_fork(clone_flags & ~CLONE_IDLETASK, newsp, ®s, 0); |
p = do_fork(clone_flags & ~CLONE_IDLETASK, newsp, ®s, 0); |
167 |
return IS_ERR(p) ? PTR_ERR(p) : p->pid; |
return IS_ERR(p) ? PTR_ERR(p) : p->pid; |
168 |
} |
} |
169 |
|
|
170 |
\end{verbatim} |
\end{verbatim} |
171 |
|
|
172 |
Function do\_fork() \label{proc:do_fork} |
\subsection{do\_fork function} \index{do\_fork} |
173 |
\textit{File: }\url{kernel/fork.c}\\ |
Function do\_fork() \label{proc:do_fork} |
174 |
|
\textit{File: }\url{kernel/fork.c}\\ \newline |
175 |
|
|
176 |
\par Following paragraph explains the steps taken by the kernel do\_fork function in order to create a new process. The steps are more relevant from process scheduling point of view. |
\par Following paragraph explains the steps taken by the kernel do\_fork function in order to create a new process. The steps are more relevant from process scheduling point of view. |
177 |
|
|
178 |
\begin{verbatim} |
\begin{verbatim} |
179 |
struct task_struct *do_fork(unsigned long clone_flags, |
struct task_struct *do_fork(unsigned long clone_flags, |
180 |
unsigned long stack_start, |
unsigned long stack_start, |
181 |
struct pt_regs *regs, |
struct pt_regs *regs, |
182 |
unsigned long stack_size) |
unsigned long stack_size) |
183 |
\end{verbatim} |
\end{verbatim} |
184 |
|
|
185 |
The do\_fork function takes foll. arguments |
The do\_fork function takes foll. arguments. |
186 |
\begin{description} |
\begin{description} |
187 |
\item[clone\_flags] : Flags to create process. This is different for fork/clone/vfork calls. |
\item[clone\_flags] : Flags to create process. This is different for fork/clone/vfork calls. |
188 |
\item[stack\_start] : top of stack required for copy\_routine. |
\item[stack\_start] : top of stack required for copy\_routine. |
189 |
\item[regs] : The register structure defined in \url{include/asm-i386/ptrace.h} |
\item[regs] : The register structure defined in \url{include/asm-i386/ptrace.h} |
190 |
\item[stack\_size] : Size of stack, usually 0. |
\item[stack\_size] : Size of stack, usually 0. |
191 |
\item[] |
\item[] \& |
192 |
\item[return value] : (pointer to) Newly created task. |
\item[return value] : (pointer to) Newly created task. |
193 |
\end{description} |
\end{description} |
194 |
|
|
195 |
\par The code is explained below in parts. |
\par The code is explained below in parts. |
196 |
|
|
197 |
\begin{verbatim} |
\begin{verbatim} |
198 |
|
|
217 |
|
|
218 |
if (nr_threads >= max_threads) |
if (nr_threads >= max_threads) |
219 |
goto bad_fork_cleanup_count; |
goto bad_fork_cleanup_count; |
220 |
|
|
221 |
\end{verbatim} |
\end{verbatim} |
222 |
Initially, the kernel checks for validity for clone\_flags. If the process is part of New Namespace Group (CLONE\_NEWNS) AND fs sharing flag (CLONE\_FS) are set,simoultaneously, it retuns an error. Then it creates a new task by duplicating the currently running task(current). |
Initially, the kernel checks for validity for clone\_flags. If the process is part of New Namespace Group (CLONE\_NEWNS) AND fs sharing flag (CLONE\_FS) are set,simoultaneously, it retuns an error. Then it creates a new task by duplicating the currently running task(current). |
223 |
The kernel limits the number of user processes owned by a process.\footnote{Refer to \url{include/asm-i386/resource.h} for the resource constants.} If this value, is greater or equal to current resource limit of number of processes, it returns an error. Else, it updates the user struct\footnote{defined in \url{linux/sched.h}} for that process. The function "capable()"\footnote{defined in \url{linux/sched.h}} checks for a particular capability. The file \url{include/linux/capability.h} enumerates the list of capabilities e.g. CAP\_SYS\_ADMIN. Then, the kernel checks if the number of threads exceed the limit max\_therads.\footnote{limit set up in fork\_init function of start\_kernel code}. |
\newline \par The kernel limits the number of user processes owned by a process.\footnote{Refer to \url{include/asm-i386/resource.h} for the resource constants.} If this value, is greater or equal to current resource limit of number of processes, it returns an error. Else, it updates the user struct\footnote{defined in \url{linux/sched.h}} for that process. The function \textit{"capable()"} checks for a particular capability. The file \url{include/linux/capability.h} enumerates the list of capabilities e.g. CAP\_SYS\_ADMIN. Then, the kernel checks if the number of threads exceed the limit max\_therads.\footnote{limit set up in fork\_init function of start\_kernel code}. |
224 |
% dup_task_struct |
% TODO dup_task_struct |
225 |
|
|
226 |
\begin{verbatim} |
\begin{verbatim} |
227 |
|
|
239 |
copy_flags(clone_flags, p); |
copy_flags(clone_flags, p); |
240 |
p->pid = get_pid(clone_flags); |
p->pid = get_pid(clone_flags); |
241 |
p->proc_dentry = NULL; |
p->proc_dentry = NULL; |
242 |
|
|
243 |
\end{verbatim} |
\end{verbatim} |
244 |
Linux kernel has the ability to execute the binaries compiled for other operating systems (assuming kernel compatible machine code). The execution domain for the running thread is specified by the structure exec\_domain defined in \url{include/linux/personality.h} \footnote{map\_segment}. The structure defines varioous personlities of the target execution environment supported by the kernel. e.g. PER\_LINUX for linux systems, PER\_BSD for bsd uix. The personality value is set by personality() system call. the macro get\_exec\_domain is used to increament the module count of the module associated with the exec\_domain while its counterpart put\_exec\_domain is used to decreament it. |
|
245 |
\par Then, the kernel increments the module's reference count only for modularised binary format. Then, it resets executed, swappable flags ans sets task state to TASK\_UNINTERRUPTIBLE. The new flags are set for the process p, especially in case of sys\_clone call. |
Linux kernel has the ability to execute the binaries compiled for other operating systems (assuming kernel compatible machine code). The execution domain for the running thread is specified by the structure exec\_domain defined in \url{include/linux/personality.h} \footnote{map\_segment TODO }. The structure defines varioous personlities of the target execution environment supported by the kernel. e.g. PER\_LINUX for linux systems, PER\_BSD for bsd uix. The personality value is set by \textit{personality()} system call. the macro \textit{get\_exec\_domain} is used to increament the module count of the module associated with the \textit{exec\_domain} while its counterpart \textit{put\_exec\_domain} is used to decreament it. |
246 |
|
|
247 |
|
% TODO map_segment |
248 |
|
\par Then, the kernel increments the module's reference count only for modularised binary format. Then, it resets executed, swappable flags ans sets task state to TASK\_UNINTERRUPTIBLE. The new flags are set for the process p, especially in case of \textit{sys\_clone} call. |
249 |
|
|
250 |
\begin{verbatim} |
\begin{verbatim} |
251 |
|
|
278 |
p->tty_old_pgrp = 0; |
p->tty_old_pgrp = 0; |
279 |
p->times.tms_utime = p->times.tms_stime = 0; |
p->times.tms_utime = p->times.tms_stime = 0; |
280 |
p->times.tms_cutime = p->times.tms_cstime = 0; |
p->times.tms_cutime = p->times.tms_cstime = 0; |
281 |
|
|
282 |
\end{verbatim} |
\end{verbatim} |
|
\par The INIT\_LIST\_HEAD macro is used to initialize the next and prev pointers of a linked list. Both the pointers are set to the macro argument, representing a circular linked list of a single element \footnote{Linked lists are described \url{include/linux/list.h}} while init\_waitqueue\_head initializes the waitqueue header node which contains the spinlock along with the linked list. |
|
|
The inline function clear\_tsk\_thread\_flag (defined in \url{include/linux/sched.h}) calls clear\_ti\_thread\_flag (defined in \url{include/linux/thread_info.h}) to clear the flag information of the thread within the task structure. |
|
283 |
|
|
284 |
|
The \textit{INIT\_LIST\_HEAD} macro is used to initialize the next and prev pointers of a linked list. Both the pointers are set to the macro argument, representing a circular linked list of a single element \footnote{Linked lists are described \url{include/linux/list.h}} while \textit{init\_waitqueue\_head} initializes the waitqueue header node which contains the spinlock along with the linked list. |
285 |
|
\par The inline function \textit{clear\_tsk\_thread\_flag} (defined in \url{include/linux/sched.h}) calls \textit{clear\_ti\_thread\_flag} (defined in \url{include/linux/thread_info.h}) to clear the flag information of the thread within the task structure. |
286 |
|
|
287 |
|
\index{bitops} \index{btrl} |
288 |
\begin{verbatim} |
\begin{verbatim} |
289 |
|
|
290 |
/*** File : {include/asm-i386/bitops.h} ***/ |
/*** File : {include/asm-i386/bitops.h} ***/ |
291 |
static __inline__ void clear_bit(int nr, volatile unsigned long * addr) |
static __inline__ void clear_bit(int nr, volatile unsigned long * addr) |
292 |
{ |
{ |
295 |
:"=m" (ADDR) |
:"=m" (ADDR) |
296 |
:"Ir" (nr)); |
:"Ir" (nr)); |
297 |
} |
} |
|
\end{verbatim} |
|
|
|
|
|
\textit{init\_completion} is wrapper inline function to initialize the wait queue header specially used during vfork() system call. The function init\_sigpending initializes the signal structure containing struct sigqueue\footnote{defined in \url{include/linux/signal.h}} and sigset\_t\footnote{defined in \url{include/asm-i386/signal.h}} structure. The head and tail pointers of sigqueue are set to NULL to initialize the circular linked list of single element while the number of words per signal [\_NSIG\_WORDS] of sigset\_t structure are set to zero. |
|
|
The dynamic timer associated with the task structure is real\_timer. When, a new task is created, the timer is initialized using init\_timer and the data is field set to the newly created process p. Thus, the whole process structure is available to the function which is called when the timer expires. |
|
298 |
|
|
299 |
|
\end{verbatim} |
300 |
|
% TODO explain code |
301 |
|
\textit{init\_completion} is wrapper inline function to initialize the wait queue header specially used during \textit{vfork()} system call. The function \textit{init\_sigpending} initializes the signal structure containing struct sigqueue\footnote{defined in \url{include/linux/signal.h}} and sigset\_t\footnote{defined in \url{include/asm-i386/signal.h}} structure. Refer to section ~\ref{sig:structs} for more details. The head and tail pointers of sigqueue are set to NULL to initialize the circular linked list of single element while the number of words per signal [\_NSIG\_WORDS] of sigset\_t structure are set to zero. |
302 |
|
\par The dynamic timer associated with the task structure is \textit{real\_timer}. When, a new task is created, the timer is initialized using \textit{init\_timer} and the data is field set to the newly created process p. Thus, the whole process structure is available to the function which is called when the timer expires. |
303 |
\begin{verbatim} |
\begin{verbatim} |
304 |
|
|
305 |
#ifdef CONFIG_SMP |
#ifdef CONFIG_SMP |
306 |
{ |
{ |
307 |
int i; |
int i; |
313 |
spin_lock_init(&p->sigmask_lock); |
spin_lock_init(&p->sigmask_lock); |
314 |
} |
} |
315 |
#endif |
#endif |
316 |
|
|
317 |
\end{verbatim} |
\end{verbatim} |
318 |
This part of code is SMP specific. It resets the values of user timer (utime) and system time (stime) for all cpus for the current process. It also initializes the sigmask\_lock used to block the signals by the process. Refer to ~\ref{signals} for more details. |
This part of code is SMP specific. It resets the values of user timer (utime) and system time (stime) for all cpus for the current process. It also initializes the \textit{sigmask\_lock} used to block the signals by the process. Refer to ~\ref{sig:structs} for more details. |
319 |
|
|
320 |
\begin{verbatim} |
\begin{verbatim} |
321 |
|
|
322 |
p->array = NULL; |
p->array = NULL; |
323 |
p->lock_depth = -1; /* -1 = no lock */ |
p->lock_depth = -1; /* -1 = no lock */ |
324 |
p->start_time = jiffies; |
p->start_time = jiffies; |
343 |
if (copy_namespace(clone_flags, p)) |
if (copy_namespace(clone_flags, p)) |
344 |
goto bad_fork_cleanup_mm; |
goto bad_fork_cleanup_mm; |
345 |
retval = copy_thread(0, clone_flags, stack_start, stack_size, p, regs); |
retval = copy_thread(0, clone_flags, stack_start, stack_size, p, regs); |
346 |
|
|
347 |
\end{verbatim} |
\end{verbatim} |
348 |
The initial part of code sets the task starting time to jiffies.\footnote{jiffies contains the time right from the system startup and the value is increamented during every timer interrupt}. The final process execution time is updated during process accounting [do\_acct\_process function in \url{kernel/acct.c}]. |
The initial part of code sets the task starting time to jiffies.\footnote{jiffies contains the time right from the system startup and the value is increamented during every timer interrupt}. The final process execution time is updated during process accounting [do\_acct\_process function in \url{kernel/acct.c}]. |
349 |
Then, various system resources are copied to the newly created process. |
\par Then, various system resources are copied to the newly created process. The following explains the the functions in short. |
350 |
copy\_sighand copies all signal handlers action |
\begin{itemize} |
351 |
memcpy(tsk->sig->action, current->sig->action, sizeof(tsk->sig->action)); |
\item copy\_semundo : This copies the sem\_undo\_list object from parent task to child. This object is required to avoid deadlock, when tasks are spawned with the semundo locks. Please refer to \url{ipc/sem.c} for details. |
352 |
|
\item copy\_files : This function [defined in \url{kernel/fork.c}] determines the number of open files by the parent process and copies those file descriptors to the child process. |
353 |
|
\item copy\_fs : This function [defined in \url{kernel/fork.c}] copies the file system information associated with the process [struct fs\_struct]. It contains elements like root, umask, pwd etc. |
354 |
|
\item copy\_sighand : This function copies all signal handlers actions from the parent to child process. Thus, all signals are inherited to child depending on clone\_flags. |
355 |
|
\item copy\_mm : This function [defined in \url{kernel/fork.c}] copies the memory resources form parent process to child [struct mm\_struct]. It is done by allocating new kmem\_cache for child process. |
356 |
|
\item copy\_namespace : This function [defined in \url{fs/namespace.c}] copies the namespace resources form parent process to child [struct namespace]. It is done by allocating new namespace in kernel to accomodate the new child task. |
357 |
|
\item copy\_thread : This function [defined in \url{arch/i386/kernel/process.c}] copies the thread information form parent process to child [struct thread\_struct]. This contains the stack pointer, instruction pointer. This thread structure contains the CPU specific state of the task. |
358 |
|
\end{itemize} |
359 |
\begin{verbatim} |
\begin{verbatim} |
360 |
|
|
361 |
/*** Now, setup other process attributes ***/ |
/*** Now, setup other process attributes ***/ |
366 |
p->swappable = 1; |
p->swappable = 1; |
367 |
p->exit_signal = clone_flags & CSIGNAL; |
p->exit_signal = clone_flags & CSIGNAL; |
368 |
p->pdeath_signal = 0; |
p->pdeath_signal = 0; |
369 |
|
|
370 |
\end{verbatim} |
\end{verbatim} |
371 |
The self\_exec\_id and parent\_exec\_id are set to same value after a fork. When the execution domain of a process changes, its self\_exec\_id is increamented. These values are checked while existing the process, only. The death\_signal [cause of death of a process] is reset to 0. The signal value 0 is unused. Signals are listed in \url{include/asm-i386/signal.h}. |
The \textit{self\_exec\_id} and \textit{parent\_exec\_id} are set to same value after a fork. When the execution domain of a process changes, its self\_exec\_id is increamented. These values are checked while existing the process, only. The death\_signal [cause of death of a process] is reset to 0. The signal value 0 is unused. Signals are listed in \url{include/asm-i386/signal.h}. |
372 |
|
|
373 |
\begin{verbatim} |
\begin{verbatim} |
374 |
|
|
384 |
} |
} |
385 |
p->sleep_timestamp = jiffies; |
p->sleep_timestamp = jiffies; |
386 |
__restore_flags(flags); |
__restore_flags(flags); |
387 |
|
|
388 |
\end{verbatim} |
\end{verbatim} |
389 |
Since the code updates the process time\_slice, the interrupts should be disabled during this operation. The macros \_\_save\_flags, \_\_cli are used to clear interrupts on the current CPU while \_\_restore\_flgs enables it again. |
Since the code updates the process time\_slice, the interrupts should be disabled during this operation. The macros \_\_save\_flags, \_\_cli are used to clear interrupts on the current CPU while \_\_restore\_flgs enables it again. |
390 |
When new child process is created, the time\_slice\footnote{Renamed counter field of kernel version 2.2 to time\_slice in kernel 2.4} of the parent process is split into two halves, one for the parent process and the other for child process. This is done to prevent an unlimited access to CPU by a single process. If the parent process is created recently in terms of time\_slice (time\_slice == 0 or 1), then the scheduler is called to reschedule the processes with the user and system time parameters as zero. These parameter are used by the scheduler\_tick() function to update the kernel statisticks. |
\par When new child process is created, the \textit{time\_slice}\footnote{Renamed counter field of kernel version 2.2 to time\_slice in kernel 2.4} of the parent process is split into two halves, one for the parent process and the other for child process. This is done to prevent an unlimited access to CPU by a single process. If the parent process is created recently in terms of time\_slice (time\_slice == 0 or 1), then the scheduler is called to reschedule the processes with the user and system time parameters as zero. These parameter are used by the \textit{scheduler\_tick()} function to update the kernel statisticks. |
391 |
|
|
392 |
\begin{verbatim} |
\begin{verbatim} |
393 |
|
|
417 |
hash_pid(p); |
hash_pid(p); |
418 |
nr_threads++; |
nr_threads++; |
419 |
write_unlock_irq(&tasklist_lock); |
write_unlock_irq(&tasklist_lock); |
|
\end{verbatim} |
|
|
At this point of time, all the resources required by the process are available. So, the process can get a chance to execute on the CPU and Hence, it needs to be added to list of runqueues. The newly created process acts as the leader of thread group and initializes itself. But if the flags contain CLONE\_THREAD, [i.e. new process is derived from some other process] then the thread leadership is retained to the thread leader of the calling process and newly created process is added to the linked list of its parents' thread [i.e. calling process's thread]. |
|
|
To set the parent child relationship for the newly created process, we need to access parent process also, Hence an irq lock is obtained. This lock will disable pre-eption on the SMP architecure. This lock is released when the process is added to runqueue. The macro SET\_LINKS inserts the new process in the linked list of process lists. Refer to list management in \url{include/linux/list.h}. |
|
|
\par \textbf{Hashing Process Ids } |
|
|
|
|
420 |
|
|
421 |
\par All the process ids (pids) are hashed in a hashing table pidhash[PIDHASH\_SZ] defined in \url{include/linux/sched.h}. This is an array of pointers to task\_struct of size PIDHASH\_SZ\footnote{This value is currently hardcoded to [4096/4], but should be dynamic and should be set to [NR\_TASKS/4]}. This hashed pids avoid sequencial scanning of the process list and thus, improves performance. The hash\_pid function adds the new task to the hash table using process pid as key and pid\_fashfn as hashing function. |
\end{verbatim} |
422 |
|
At this point of time, all the resources required by the process are available. So, the process can get a chance to execute on the CPU and Hence, it needs to be added to list of runqueues. The newly created process acts as the leader of thread group and initializes itself. But if the flags contain CLONE\_THREAD, [i.e. new process is derived from some other process] then the thread leadership is retained to the thread leader of the calling process and newly created process is added to the linked list of its parents' thread [i.e. calling process's thread]. |
423 |
|
\par To set the parent child relationship for the newly created process, we need to access parent process also, Hence an irq lock is obtained. This lock will disable pre-eption on the SMP architecure. This lock is released when the process is added to runqueue. The macro SET\_LINKS inserts the new process in the linked list of process lists. Refer to list management in \url{include/linux/list.h}. |
424 |
|
\par \textbf{ |
425 |
|
\newline |
426 |
|
Hashing Process Ids } \index{hash\_pid} |
427 |
|
\newline |
428 |
|
\par All the process ids (pids) are hashed in a hashing table pidhash[PIDHASH\_SZ] defined in \url{include/linux/sched.h}. This is an array of pointers to task\_struct of size PIDHASH\_SZ\footnote{This value is currently hardcoded to [4096/4], but should be dynamic and should be set to [NR\_TASKS/4]}. This hashed pids avoid sequencial scanning of the process list and thus, improves performance. The \textit{hash\_pid} function adds the new task to the hash table using process pid as key and pid\_fashfn as hashing function. |
429 |
|
|
430 |
\begin{verbatim} |
\begin{verbatim} |
431 |
#define pid_hashfn(x) ((((x) >> 8) ^ (x)) & (PIDHASH_SZ - 1)) |
#define pid_hashfn(x) ((((x) >> 8) ^ (x)) & (PIDHASH_SZ - 1)) |
432 |
\end{verbatim} |
\end{verbatim} |
433 |
|
|
434 |
The nr\_threads value (total number of processes) is increamented. This value should not exceed max\_threads limit. And the irq lock is returned will re-enables the process pre-emption. |
The nr\_threads value (total number of processes) is increamented. This value should not exceed max\_threads limit. And the irq lock is returned will re-enables the process pre-emption. |
435 |
|
|
436 |
\begin{verbatim} |
\begin{verbatim} |
437 |
|
|
438 |
wake_up_forked_process(p); |
wake_up_forked_process(p); |
439 |
++total_forks; |
++total_forks; |
440 |
if (clone_flags & CLONE_VFORK) |
if (clone_flags & CLONE_VFORK) |
441 |
wait_for_completion(&vfork); |
wait_for_completion(&vfork); |
442 |
else |
else |
443 |
set_need_resched(); |
set_need_resched(); |
444 |
|
|
445 |
\end{verbatim} |
\end{verbatim} |
446 |
The wake\_up\_forked\_process adds the newly created process to the runqueue and activates it.In order to activate task, it is queued at the tail of the runqueue using enqueue\_task function and the priority bitmap of the task is also updated. Refer to \url{kernel/sched.c} for detail functions. The exclusive operations related to runqueues are performed within the rq\_lock and rq\_unlcok function block. These functions enable and disable interrupts(irqs) on local cpu [cpu corresponding to the runqueue, usually refered by using smp\_processor\_id() macro.] in addition to using spin\_lock. |
The \textit{wake\_up\_forked\_process} adds the newly created process to the runqueue and activates it.In order to activate task, it is queued at the tail of the runqueue using enqueue\_task function and the priority bitmap of the task is also updated. Refer to \url{kernel/sched.c} for detail functions. The exclusive operations related to runqueues are performed within the \textit{rq\_lock} and \textit{rq\_unlcok} function block. These functions enable and disable interrupts(irqs) on local cpu [cpu corresponding to the runqueue, usually refered by using \textit{smp\_processor\_id()} macro.] in addition to using spin\_lock. |
447 |
|
|
448 |
|
\subsection{ABI: Application binary interface} |
449 |
|
% TODO ABI |
450 |
|
|
451 |
\section{Destroying process} |
\section{Destroying process} |
452 |
There are several reasons for tasks to terminate: |
There are several reasons for tasks to terminate: |
453 |
|
|
454 |
\begin{enumerate} |
\begin{enumerate} |
455 |
\item exit() system call or end of program. |
\item exit() system call or end of program. |
457 |
\item forcing a task to die when kernel receives exception running on behalf of process. |
\item forcing a task to die when kernel receives exception running on behalf of process. |
458 |
\end{enumerate} |
\end{enumerate} |
459 |
|
|
460 |
The sys\_exit function is defined in \url{kernel/exit.c} which calls function do\_exit(). The do\_exit function releases all the resources such as memory, open files, semaphores owned by the process. Following code explains the step by step process. |
The sys\_exit function is defined in \url{kernel/exit.c} which calls function do\_exit(). The do\_exit function releases all the resources such as memory, open files, semaphores owned by the process. Following code explains the step by step process. |
461 |
|
|
462 |
\par The code is explained below in parts. |
\subsection{do\_exit function} |
463 |
|
\newline \par The code is explained below in parts. |
464 |
|
|
465 |
\begin{verbatim} |
\begin{verbatim} |
466 |
|
|
467 |
struct task_struct *tsk = current; |
struct task_struct *tsk = current; |
468 |
|
|
469 |
if (in_interrupt()) |
if (in_interrupt()) |
479 |
printk(KERN_INFO "note: %s[%d] exited with preempt_count %d\n", |
printk(KERN_INFO "note: %s[%d] exited with preempt_count %d\n", |
480 |
current->comm, current->pid, |
current->comm, current->pid, |
481 |
preempt_get_count()); |
preempt_get_count()); |
482 |
|
|
483 |
\end{verbatim} |
\end{verbatim} |
484 |
The "current" task global variable always points to the current task running. The process can not be destroyed while executing an interrupt handler. The processes 0 (idle), 1 (init) can not be destroyed. The macro "unlikely" is GNU compiler version specific\footnote{defined in \url{include/linux/compiler.h}} and gets reduced to macro argument while the macro "preempt\_get\_count" is SMP PRE-EMPTION specific and returns the preemption count. This value should be 0 while exiting the system call. |
The \textit{"current"} task global variable always points to the current task running. The process can not be destroyed while executing an interrupt handler. The processes 0 (idle), 1 (init) can not be destroyed. The macro "unlikely" is GNU compiler version specific\footnote{defined in \url{include/linux/compiler.h}} and gets reduced to macro argument while the macro \textit{"preempt\_get\_count"} is SMP PRE-EMPTION specific and returns the preemption count. This value should be 0 while exiting the system call. |
485 |
|
|
486 |
\begin{verbatim} |
\begin{verbatim} |
487 |
|
|
488 |
acct_process(code); |
acct_process(code); |
489 |
__exit_mm(tsk); |
__exit_mm(tsk); |
490 |
|
|
504 |
|
|
505 |
tsk->exit_code = code; |
tsk->exit_code = code; |
506 |
exit_notify(); |
exit_notify(); |
507 |
|
|
508 |
\end{verbatim} |
\end{verbatim} |
509 |
|
|
510 |
\par The code removes memory, files, filesystem resources. All these steps are exactly opposite to those performed while creating the process (only in reverse order). |
The code removes memory, files, filesystem resources. All these steps are exactly opposite to those performed while creating the process (only in reverse order). |
511 |
Before exiting a process, the file information changed by the process should be updated. These task of process accounting is performrd by the "acct\_process" function \footnote{refer to \url{kernel/acct.c} for detail accounting}. |
\par Before exiting a process, the file information changed by the process should be updated. These task of process accounting is performrd by the "acct\_process" function \footnote{refer to \url{kernel/acct.c} for detail accounting}. |
512 |
% TODO details exit_namespace , exit_sighand, exit_thread |
% TODO details exit_namespace , exit_sighand, exit_thread |
513 |
|
|
514 |
\begin{verbatim} |
\begin{verbatim} |
515 |
|
|
516 |
schedule(); |
schedule(); |
517 |
BUG(); |
BUG(); |
518 |
|
|
519 |
\end{verbatim} |
\end{verbatim} |
520 |
Finally, it calls the schedule() function and does not return. The function prototype in \url{include/linux/kernel.h} indicates it, too. Thus, a process deletion leads to rescheduling of all the processes. |
Finally, it calls the schedule() function and does not return. The function prototype in \url{include/linux/kernel.h} indicates it, too. Thus, a process deletion leads to rescheduling of all the processes. |
521 |
\begin{verbatim} |
\begin{verbatim} |