Fix
This commit is contained in:
parent
d8aa0b48bb
commit
81e51f0e7f
|
@ -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.
|
Loading…
Reference in New Issue