# Linux system call呼叫 & `fork()` ###### tags: `learning` ## `fork` System Call如何呼叫 - 早期(v3.7及之前): `sys_fork()`呼叫`do_fork()` ```c asmlinkage long sys_fork(struct pt_regs regs) { return do_fork(SIGCHLD, regs.rsp, &regs, 0); } ``` - 後期(~v5.9): `SYS_DEFINEx()`(x代表參數個數)呼叫`do_fork()` ```c #ifdef __ARCH_WANT_SYS_FORK SYSCALL_DEFINE0(fork) { #ifdef CONFIG_MMU return _do_fork(SIGCHLD, 0, 0, NULL, NULL, 0); #else /* can not support in nommu mode */ return -EINVAL; #endif } #endif ``` - 最新版(v5.10之後): `SYS_DEFINEx()`呼叫`kernel_clone()` ```c #ifdef __ARCH_WANT_SYS_FORK SYSCALL_DEFINE0(fork) { #ifdef CONFIG_MMU struct kernel_clone_args args = { .exit_signal = SIGCHLD, }; return kernel_clone(&args); #else /* can not support in nommu mode */ return -EINVAL; #endif } #endif ``` - [ref](https://blog.csdn.net/boyemachao/article/details/112983228) ## fork/vfork/clone - `fork()`將parent的<font color='red'>全部`task_struct`資源</font>copy給child - 使用Copy On Write技術,parent與child共享資源,如果有寫入才分配新的空間給child - `vfork()`將parent<font color='blue'>除了`mm_stuct`</font>的全部資源copy給child - 即parent及child共享data section,但有各自的記憶體空間 - `vfork`創建的child process會先於parent執行 - `clone()`<font color='green'>利用`CLONE_xxx` flag指定parent的哪些資源</font>copy給child - v5.10之前`fork/vfork/clone`底層皆呼叫`_do_fork()`,並利用第一個參數的flag區別 - `fork`: `SIGCHLD` - child終止後會發送SIGCHLD信號給parent - `vfork`: `CLONE_VFORK | CLONE_VM | SIGCHLD` - `clone`: 由User自定義flag - v5.10-rc1之後將原本的`_do_fork`替換成`kernel_clone`,`fork/vfork/clone`底層全部呼叫`kernel_clone` ## `kernel_clone`流程(與`_do_fork`基本一致) 1. `copy_process()` :複製parent的`task_struct`給child,return值為`task_struct` Pointer 2. `get_task_pid()`取得child pid 2. 如果是`vfork`,初始化vfork處理資訊 3. `wake_up_new_task()`將child加入scheduler,至此完成fork,child準備執行 4. 啟動`ptrace`,如果child開始執行就告訴parent 4. 如果是`vfork`,執行`wait_for_vfork_done()`,parent等待child完成,當child調用`exec`或`exit`之後,parent才可以繼續執行 - [ref1](https://blog.csdn.net/jasonactions/article/details/115316642) - [ref2](https://blog.csdn.net/jasonactions/article/details/115316642) - [ref3](https://cloud.tencent.com/developer/article/1891524)