[筆記]Linux的thread和signal
上一篇文章整理Linux的process群組(session、process group)與其signal傳遞機制。若要處理的case是像JVM這種喜歡single process multi thread的程序架構,就會需要瞭解thread/thread group這一階層的概念。
Linux thread
大家知道在linux thread的機制是後來加上去的,所以底層在很多地方是將thread和process一視同仁。整理linux thread機制如下:
- linux 有一個類似fork的clone syscall,和fork的差別它起的process會和parent process share context/resource等很多資源
- 在linux thread是以LWP的方式實現,也就在底層行程管理和排程將thread和process一視同。thread是一群比較特別的process,他們彼此share資源。
- 在linux就是用clone syscall去起thread,也就是建立啟動時不新建PID/context的child process
- 現代linux的thread實做稱為NPTL (Native POSIX Thread Library) ,開發者要使用thread功能,通常會引用pthread函式庫
- 同process的thread會有相同的process id,且個別有thread id。對於multithread的process,process id又稱為thread group id
下圖用htop實際觀察process/thread階層關係:
圖中PPID, PID和TGID三個欄位是這邊特別要觀察的,分別是parent process id, process id, thread group id。
- 可以看到thread group id是該thread group第一個process (leader)的process id
- 同thread group的parent process id是其中第一個process的parent process id
- 圖中Command欄位是綠色代表這是一個thread,其PID欄位值其實是thread id。圖中ipython共有有三個thread(一個leader, 兩個member)
Linux thread對signal的處理
thread比較常和同group內的其他thread通訊,比較不會從thread group外部以signal和特定thread交流的況況。
對於thread group內的signal傳遞pthread library提供pthread_kill()做thread group內部溝通。
對於從thread group外部打signal到特定thread,Linux提供tgkill system call,來發signal到某個thread group的某個thread。tgkill syscall在glibc沒有提供wrapper,要call的話只能透過syscall呼叫。
在Linux提供kill system call發signal到某個process。若這個process是mutlithread,則根據文件會是其中隨機一個thread會收到此signal。
上述kill是system call,不應該和linux的kill command攪混。kill command雖然文件寫是吃PID,但實驗若是給TID,還是會發送signal。
照上述說法,有一個疑問是為何下kill command可以中止mutlithread程序呢?這是因為當任意thread收到terminatiion,預設都會中止整個thread group中所有的thread。