This commit is contained in:
Morgan 2023-11-19 12:00:32 +09:00
parent d8aa0b48bb
commit 81e51f0e7f
1 changed files with 140 additions and 0 deletions

View File

@ -0,0 +1,140 @@
---
title: Linux Kernel, syscalls
date: 2022-11-19T
slug: linux-kernel-sys-fork
description: ""
---
#### sys_fork()
```asm
.align 2
_sys_fork:
call _find_empty_process
testl %eax,%eax
js 1f
push %gs
pushl %esi
pushl %edi
pushl %ebp
pushl %eax
call _copy_process
addl $20,%esp
1: ret
```
##### `FUNCTION find_empty_process()`
```assembly
A:
IF ++last_pid < 0
last_pid = 1
FOR i : 0 -> NR_TASKS
IF task[i] && task[i].pid == last_pid
GOTO A
FOR i : 1 -> NR_TASKS
IF NOT task[i]
RETURN i
RETURN -1
```
1. Set last_pid to 1 or more.
2. From taskid from 0 to max_tasks, if task exists and pid is last_pid then increases pid and again.
3. From taskid from 1 to max_tasks, if tasks not exists, return.
-> It just iterates through tasks and find last taskid linearly.
##### `FUNCTION copy_process`
`<- nr, EBP, EDI, ESI, GS, EBX~EDX, CS~FS, EIP, EFLAGS, ESP, SS`
`-> INT`
```assembly
TASK_STRUCT P
INT I
FILE F
P = (TASK_STRUCT)(GET_FREE_PAGE())
IF NOT P
RET ERR
SET P
START_TIME = RUNNING
PID = LAST_PID
FATHER = CURRENT_PID
COUNTER = PRIORITY
START_TIME = jiffies
SIGNAL, ALARM, LEADER, UTIME, STIME, CUTIME, CSDTIME, BACK_LINK = 0
SET TSS
BACK_LINK = 0
ESP0 = PAGE_SIZE + ADDR(P)
SS0 = 0x10
EAX = 0
ES ~ GS = 0xFFFF
LDT = _LDT(nr)
EIP, EFLAGS = ARGUMENT
ECX ~ EDI = ARGUMENT
TRACR_BITMAP = 0x80000000
COPY_MEM (nr, p)
IF <-
FREE_PAGE ADDR(P)
RET ERR
FOR i : 0 ~ NR_OPEN
IF
f = P.filp[i]
THEN
INCR f.f_count 1
IF
CURRENT.PWD
THEN
INCR CURRENT.PWD.i_count 1
IF
CURRENT.ROOT
THEN
INCR CURRENT.ROOT.i_count 1
SET_TSS_DESC <- (GDT + nr/2 + FIRST_TSS_ENTRY) , P.TSS
SET_LDT_DESC <- (GDT + nr/2 + FIRST_LDT_ENTRY) , P.LDT
task(nr) <- p
RET last_pid
```
"nr" passed is the index of the new task in the task array, where each element corresponds to a process slot.
fork() copies the parent's kernel context, as well as general registers and segment selectors required for a new process to run in user space.
It creates a new task structure from a new free page and sets up default values and certain parameters inherited from the parent, such as process ID, priority, and execution times.
Then it copies memory regions from the parent to the new process, referred to by "nr," which is the index of the new process in the task array.
Changes the parent process's working directory (PWD) and root directory reference counters, incrementing them by 1 to reflect the new child process now also using these resources.
Sets the Task State Segment (TSS) and Local Descriptor Table (LDT) entries, which are x86-specific structures used for task switching and memory segmentation, respectively.
TSS holds information about the task's stack for privilege level changes and also the hardware context when a task switch occurs.
LDT is a segment descriptor table that stores descriptors for local segments, giving a task its own set of segment registers.
Finally, it assigns the newly created task structure, p, to the task array at index "nr." This effectively makes the new task available for scheduling.
"sys_fork" finds an empty process ID using the search loop in `_find_empty_process`, then it invokes `_copy_process` to clone the parent's kernel context to the new process. This sets up a complete environment for the new process to run independently from the parent, but initially as a nearly identical copy.