# 林納斯 Project 1 Cheatsheat
{%hackmd /vgoFfe-PQTioGuCz7JDuJA %}
## Cache Table
**page fault**
**3 system calls while creating a new thread (w/ pthread)**
> mmap, clone, mprotect
**what flags does syscall `clone` use**
> CLONEVM (进程和子进程在同一内存空间中运行)
> https://blog.csdn.net/narcissus2/article/details/86411460
**calculate details in linear addr to phys addr (x86-64)**
> - pgd_os = mm->pgd + (addr >> 39) & (2^9 - 1)
> - pud_os = pgdaddr(pgd) + (addr >> 30) & (2^9 - 1)
> - pmd_os = pudaddr(pud) + (addr >> 21) & (2^9 - 1)
> - pte_ps = pmdaddr(pmd) + (addr >> 12) & (2^9 - 1)
> - paddr = pteval(pte) & ~(2^12 - 1) | addr & (2^12 - 1)
**copy_from/to_user 目的、用途**
> because of the possible page fault hit that might occur, if accessing unpaged/paged out memory in user space (that wouldn't happen in kernel space, as above ensures). So copy_to/from would be normal memcpy, but wrapped in a page fault handler.
> copy_from/to nowadays also disables PAN/PXN before the operation, and restores it after.
**virtual addr 分幾段**
```
|64 sign extend 48|47 pgd offset 39|38 pud offset 30|29 pmd offset 21|20 pt offset 12|11 phys offset 0|
```
<!-- :::spoiler Image -->

> sauce: https://superuser.com/q/1740680
<!-- ::: -->
**current (實作?)**
> - x86:http://linux.laoqinren.net/kernel/sched/current/
> - 在x86体系结构中,使用了current_task这个每CPU变量,来存储当前正在使用cpu的进程的struct task_struct。 由于采用了每cpu变量current_task来保存当前运行进程的task_struct,所以在进程切换时,就需要更新该变量。
### very difficult, very powerful
**SYSCALL_DEFINEx**
> - https://member.adl.tw/ernieshu/syscall_3_14_4.html
> - 第一種方法(sys_xxx),是最接近 C 語言原生的實作方法;然而,由於 32 位元平台與 64 位元平台的差異性,Linux 曾出現了一個重大的系統漏洞(此漏洞在 CVE 上的編號是 CVE-2009-0029),為了解決這個漏洞,從 2.6.28.1 開始才提出了第二種方法(SYSCALL_DEFINEx),後來又增加了對 ftrace(一種系統函式的追蹤機制)的支援。也就是說,為了保證和其他系統機制能正確共同運作,應該盡可能使用第二種方法來實作。
> - https://blog.csdn.net/hxmhyp/article/details/22699669
> - 就是将系统调用的参数统一变为了使用long型来接收,再强转转为系统调用本来传下来的参数类型
> - 根据ABI的规定,32位的参数存放在64位的寄存器上要自己进行符号扩展,但是程序是人写的,可能是疏忽,也可能是有意,总之并不能完全保证这一点,那么传参的时候,就会出现只修改了低32位,并没有修改高32位的情况,那么如果高32位是ffffffff,这个数就变为了一个很大的负数,在内核中执行,sample[arg]就会取到一个非法地址。
**pgd_offset**
> mm->pgd + (addr >> 39) & (2^9 - 1)
**?_offset 數字貝多芬**
> ...just beethoven
**heap shared? (malloc in non-main thread) (arena)**
> https://stackoverflow.com/a/10706725
> glibc: ptmalloc
> arena: 管理 malloc 用到的東西,e.g. binary, malloc chunk
> 每個 thread 如果有用到 malloc 就會配一個 arena (包含 main thread)
> 如果 arena 數量超過系統上限,就會需要共用
> 32bit: Number of arena = 2 * number of cores + 1
> 64bit: Number of arena = 8 * number of cores + 1
> 共用方式就是找哪個 arena 沒上鎖,就去鎖它然後拿來用
> 如果沒有,塞住
**copy_to/from_user (kernel 不會 page fault?)**
> https://stackoverflow.com/a/64019765
> kernel threads never page fault: The page fault talked about is when making a virtual page resident, or bringing it back from swap. Kernel pages not only get paged in on kmalloc(), but also remain resident for their lifetime. The same does not hold for user space pages, which A) may be lazy allocated (i.e. just reserved as page table entries on malloc(), but not actually faulted in until a memset() or other dereference) and B) may be swapped out on low memory conditions.
**anonymous page**
**for_each_process: p->tasks.next ...**
**for_each_thread: p->signal ...**
---
:::info
(a Brief Summary of the Questions They'd Actually Asked
## BSQTAA
**pthread 用到哪些 system call?**
> mmap, clone, mprotect
**mmap push 在哪**
> stack
**mprotect 目的**
> 鎖住區段空間
**是鎖全部還鎖局部?**
> 可以指定鎖的位置所以是部分
**pthread 在用 clone 的時候立了哪些 flag?**
> 很多,最重要是 CLONE_VM
**那 CLONE_VM flag 是幹嘛用的?**
> 共享記憶體空間
**怎麼把 linear addr 轉成 phys addr**
> pgd, mask, ???
**pgd_irshift 是多少**
> 39
**SYSCALL_DEFINE3 vs asmlinkage**
**為什麼(我們)不用 asmlinkage**
**current 是什麼?指向哪?**
- per cpu
**copy-to-user 的目的**
> 避免 Page fault
**加分題實作細節:**
- task struct
- mm_struct
- start code
- end code
- linked list head 是哪個變數
:::