Process
08 August 2020
Process
每個proces都有一個獨自的pid,當process結束時,pid會釋放出來,其他process創立時就能用該pid(但一班而言現在都會對這種release的pid有delay assign的做法)
Execution state
- new: OS 產生新的Process給資源
- Ready: process準備好可以跑, 等CPU執行
- running: process在跑
- waiting: 等待event發生在繼續執行(這時沒在執行)
- terminated: process結束, OS free掉資源
做IO時就會進入waiting state,等IO做完會進ready state, 等OS context switch後此process就可以回到running state
不會IO做完後馬上進入running state, 因為CPU可能在忙其他process
Process State Queues
OS會對於上述各個state會有一個queue, 所以會有 ready queue, wait queue, running queue, 每個queue裡都會有多個PCB, 一個PCB代表一個process, 當process改變state時,會從該state queue移動到另一個state queue.
Running Queue的size就是core的數量, 另外每個IO device都會有自己的wait queue
special process
pid 0
scheduler process(a.k.a swapper), 算是linux kernel 的一部分
kernel space的process
pid 1
init process,在bootstrap結束時kernel會呼叫這個process,負責把整個unix系統帶起來,在/sbin/init
相關設定在 /etc/init.d 或 /etc/rc* 或 /etc/inittab
他是一個user space的process,會一直持續執行,他可以負則收容zombie process
pid2
pagedaemon,負責virtual memory的paging
Create process
fork(void)
call 1 return twice的一個function call
當次接收到是return 0的話就是在child process,如果接收到的return值是非0,那就是parent process得到child process的pid。
if ((pid = fork()) < 0) {error fork};
else if(pid == 0) {child process execution}
else {parent process execution}
fork();
fork();
上述這個Case會有4個Process, 原本A process會call 第一個fork, 此時會有兩個process A,B. 接著A,B會再繼續call fork 產生兩個process, 總共4個process
因此如果call下面這樣程式, 會產生exponential數量的process
while(True){ fork();}
Dataspace
當call完fork後,會產生兩個process(parent,child),他們都會接續執行接下來的指令。
child process是一個parent process的copy,擁有一樣的data space, heap, stack value,但是複製出完整一份,而不是shared data。但是程式碼片段是shared的。
如果IO有redirect的話,child process也會跟著被redirect。因為file descriptor也是shared的,因此會同時修改到同一份檔案,等於file table複製一份,但他都指向同樣的file。File Offset也是shared的,所以本身一方寫完另一方可以接續寫,自動file offset會移到後面。
Race Condition
另外因為kernel scheduler的關係,我們並不能確保parent,child process的運行的關係,因此很可能parent比較快或child比較快,此時就容易發生race condition,因此就要用signal的方式來避免,不能用timeout或sleep。尤其是像是在同時寫同個file時。
polling(一直跑loop)方式當然也可,但就浪費cpu資源
Copy on write
因為整個copy出一個新的data space是很花時間的,所以採用Copy on write的技術,即剛開始parent process child process共用data space,一旦其中一方改寫memory的話,這時再複製那個部分的memory出來就好,可以不用一開始就複製整塊data space。可以省空間又省時間
IO buffering
要注意的是,如果IO buffer(line buffer / fully buffer)不是空的時候,此時fork就會變成兩個process都會有這個IO Buffer,裡面都有buffer的值。
因此假設fork前call IO,如果有buffer住,這個IO buffer和裡面的值會傳進fork後的兩個process裡。
因此要確定fork後process的IO正確,要確定IO Buffer沒有東西在裡面。
Shared and not shared
Shared
- 各種ID(user id, group id, effective user/group id, process group id)
- session ID
- current working dir, root dir
- signal mask, disposition
- env, memory mappings, resource limits
- File mode creation mask
not shared
- Pid, parent pid
- child process的time value(tms_cstime,tms_utime and etc)都被射成0
- file lock(只能有一個write lock,不能複製成兩個R)
- pending alarms/signal (child process pending alarms會清空)
vfork
vfork和fork的不同處
- vfork保證child process先執行,直到child跑到exec或_exit,parent才會繼續
- 不會複製dataspace的資料,所以dataspace是和parent共用,共用相同address space,因此如果child process有改寫資料會出事
exit and _exit
_exit不會flush IO buffer,exit會。因此假設在用vfork的話最後child process使用exit,那在IO buffer裡面的東西都被清掉,而兩者共用IO Buffer,parent的IO Buffer瞬間清空。因此若要保留Buffer裡面資料給Parent的話,child process要使用_exit來確保Buffer沒被flushed
orphan process
當parent process fork出一個child process後,好死不死parent process比child process早掛掉,此時child process直接變成孤兒(zombie process),然後會認領新媽媽(init process),然後init process就wait她,把她結束掉。
Zombie process
這種狀況是child process結束,理論上parent process要wait他來清空child process的資源跟取得他的terminate status。但parent process沒有wait,所以那個結束的child process就掛在那邊晃來晃去。佔用資源
wait waitpid
pid_t wait(int *statloc);
pid_t waitpid(pid_t pid, int *statloc, int opt)
因為process運行是async的方式,所以他們如果沒specify是不會等彼此的,有突發事件要透過signal才能傳達給對方。
當一個process結束時,kernel會發一個SIGCHILD的signal給parent process,告知child process已經結束,該去向工程師一樣做回收了。這時parent process可以有一個signal handler來處理,但default是ignore啦030,不處理。
wait, waitpid就是回收child process,釋放資源、取得terminate status的function。他有以下特性
- BLock,這個函式沒return前(沒等到child process前)是不會繼續往下執行的
- reutrn temination status of a child process
- 如果waitpid等的pid不存在的話,回傳error
- statloc pointer就是存放termination status的地方,如果對status沒應去,可以傳null就好
Difference between wait and waitpid
- wait會等任一個parent process下terminate的child process,waitpid會等specified的child process
- waitpid是non-blocking
wait3 wait4
大部分unix系統都有,內容跟wait差不多,差別在他會另外提供resource usage的參數,能夠得知child process resource usage的狀況(包括CPU time, page faults, signals received …..)
Exec
execve(*pathname, argv[])
execve("./test","-f","inoput...."...)
有非常多種exec,要用時在查。基本上pathname可以是絕對或相對路徑,相對的話會從PATH這個環境變數開始找,找有沒有該檔案
fork函式能夠產生新的process,exec直接把新的process改成新的program來執行,基本上call exec後child process的dataspace(stack,text,heap)都會直接被洗掉改成新的program的dataspace。但前面所提到關於signal mask, user/group ID, file locks, cwd, root dir, pending signals, resource limits這些都會從該process(child process)繼承到新的program。即在child process做的改動,很大部分在call了exec後,新的program還是會保留child process做的變動
Process Control Block(PCB)
紀錄process的state(包括program counter,register,memory),主要是在context switch時要喚回某process所需要的所有資訊, 內容包括:
- Process State(run,wait,terminate…)
- Pid, Program Counter
- Stack Pointer, Memory Management info, Register
- Username of owner
- List of opened files
- Scheduling information
- IO info
基本上就是把PCB的位址放進各個execution的queue裡面, 當process state改變時在unlink然後把PCB的位址push進另一個state queue裡面
Reference: youtube link
System
system(cmdstring'
基本上就是一個function內部含有fork,exec,waitpid的功能,這個function就是會fork一個child process執行/bin裡面或者PATH變數裡面有的執行檔,最後再由parent process把child process回收。
Process Scheduling
nice(int incr); 決定自己的priroity
inct = 0 ~ 2*NZERO-1
setpriority 決定process的priority
基本上process的context switch是由scheduler來決定的,但user可以透過nice指令來決定process的priroity,決定process的優先程度,某種程度可以影響、決定scheduler的做法。
基本上nice自己只能把自己priority降低,除非是privileged process才能用nice提高自己priroity。
Process time
clock_t times(struct tms *buf)
struct tms{
clock_t tms_utime; // user cpu time
clock_t tms_stime; // system cpu time
clock_t tms_cutime; // user cpu time of child process(terminated)
clock_t tms_cstime; // system cpu time of child process(terminated)
}
nice可以決定自己這個process的優先度。
PEB結構
Process Environment Block(PEB): windows中用來記錄process資訊的結構,包括
- stack / imagebase address
- section address, DLL資訊
- number of section等等
process communication
兩個process要溝通或共享資源
- IPC
- Shared Memory(mmap)