📄 linux-process.txt
字号:
How the kernel sees a process
From the kernel point of view, a process is an entry in the process table. Nothing more.
The process table, then, is one of the most important data structures within the system,
together with the memory-management tables and the buffer cache. The individual item in the
process table is the task_struct structure, quite a huge one, defined in include/linux/sched.h.
Within the task_struct both low-level and high-level information is kept--ranging from the copy
of some hardware registers to the inode of the working directory for the process.
The process table is both an array and a double-linked list, as well as a tree. The physical
implementation is a static array of pointers, whose length is NR_TASKS, a constant defined in
include/linux/tasks.h, and each structure resides in a reserved memory page. The list structure
is achieved through the pointers next_task and prev_task, while the tree structure is quite
complex and will not be described here. You may wish to change NR_TASKS from the default vaue of
128, but be sure to have proper dependency files to force recompilation of all the source files
involved.
After booting is over, the kernel is always working on behalf of one of the processes, and the
global variable current, a pointer to a task_struct item, is used to record the running one.
current is only changed by the scheduler, in kernel/sched.c. When, however, all procecces must
be looked at, the macro for_each_task is used. It is conderably faster than a sequential scan of
the array, when the system is lightly loaded.
A process is always running in either ``user mode'' or ``kernel mode''. The main body of a user
program is executed in user mode and system calls are executed in kernel mode. The stack used
by the process in the two execution modes is different--a conventional stack segment is used
for user mode, while a fixed-size stack (one page, owned by the process) is used in kernel
mode. The kernel stack page is never swapped out, because it must be available whenever a
system call is entered.
System calls, within the kernel, exist as C language functions, their `official' name being
prefixed by `sys_'. A system call named, for example, burnout invokes the kernel function
sys_burnout().
The system call mechanism is described in chapter 3 of this guide. Looking at for_each_task
and SET_LINKS, in include/linux/sched.h can help understanding the list and tree structures in
the process table.
Creating and destroying processes
A unix system creates a process though the fork() system call, and process termination is
performed either by exit() or by receiving a signal. The Linux implementation for them resides
in kernel/fork.c and kernel/exit.c.
Forking is easy, and fork.c is short and ready understandable. Its main task is filling the
data structure for the new process. Relevant steps, apart from filling fields, are:
getting a free page to hold the task_struct
finding an empty process slot (find_empty_process())
getting another free page for the kernel_stack_page
copying the father's LDT to the child
duplicating mmap information of the father
sys_fork() also manages file descriptors and inodes.
The 1.0 kernel offers some vestigial support to threading, and the fork() system call shows
some hints to that. Kernel threads is work-in-progress outside the mainstream kernel.
Exiting from a process is trickier, because the parent process must be notified about any child
who exits. Moreover, a process can exit by being kill()ed by another process (these are Unix
features). The file exit.c is therefore the home of sys_kill() and the vairious flavours of
sys_wait(), in addition to sys_exit().
The code belonging to exit.c is not described here--it is not that interesting. It deals with a
lot of details in order to leave the system in a consistent state. The POSIX standard, then, is
quite demanding about signals, and it must be dealt with.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -