自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

面試官,您確定要讓我展開(kāi)講進(jìn)程嗎?

系統(tǒng) Linux
Linux系統(tǒng)創(chuàng)建進(jìn)程都是由已存在的進(jìn)程創(chuàng)建的(除了0號(hào)進(jìn)程),被創(chuàng)建的進(jìn)程叫做子進(jìn)程,創(chuàng)建子進(jìn)程的進(jìn)程就做父進(jìn)程。這句話(huà)是不是有點(diǎn)熟悉,沒(méi)錯(cuò),Linux進(jìn)程串起來(lái)也是一顆樹(shù)的結(jié)構(gòu)。

[[426358]]

本文轉(zhuǎn)載自微信公眾號(hào)「CS指南」,作者大白。轉(zhuǎn)載本文請(qǐng)聯(lián)系CS指南公眾號(hào)。

大家好呀,我是大白!準(zhǔn)備了好久,我的 Linux 系列文章終于和大家見(jiàn)面了。最近為了籌備 Linux 的文章,以程序員的視角看城市系列都沒(méi)時(shí)間寫(xiě)了,最近不光讀者催我,一些喜歡我城市系列文章的號(hào)主也在催我,哈哈?,F(xiàn)在我的第一篇寫(xiě) Linux 的文章終于寫(xiě)出來(lái)了,第二篇、第三篇會(huì)越來(lái)越快,質(zhì)量也會(huì)越來(lái)越高,希望大家多多支持我呀!

面試中經(jīng)常會(huì)被問(wèn)到進(jìn)程和線程的區(qū)別,你給面試官回答一個(gè)進(jìn)程里包含許多線程他又不太高興,嫌你答的太少了,要掛你。這個(gè)系列我們就以 Linux 中的進(jìn)程和線程為例,好好的拆開(kāi)講一講里面的細(xì)節(jié)。今天這篇文章先展開(kāi)講一講 Linux 的進(jìn)程是如何創(chuàng)建的。這個(gè)系列還會(huì)不斷更新,歡迎持續(xù)關(guān)注呀!

Linux的進(jìn)程是怎樣創(chuàng)建的

Linux系統(tǒng)創(chuàng)建進(jìn)程都是由已存在的進(jìn)程創(chuàng)建的(除了0號(hào)進(jìn)程),被創(chuàng)建的進(jìn)程叫做子進(jìn)程,創(chuàng)建子進(jìn)程的進(jìn)程就做父進(jìn)程。這句話(huà)是不是有點(diǎn)熟悉,沒(méi)錯(cuò),Linux進(jìn)程串起來(lái)也是一顆樹(shù)的結(jié)構(gòu)。就像下面這樣:

在Linux中,為了創(chuàng)建一個(gè)子進(jìn)程,父進(jìn)程用系統(tǒng)調(diào)用fork來(lái)創(chuàng)建子進(jìn)程。fork()其實(shí)就是把父進(jìn)程復(fù)制了一份(子進(jìn)程有自己的特性,比如標(biāo)識(shí)、狀態(tài)、數(shù)據(jù)空間等;子進(jìn)程和父進(jìn)程共同使用程序代碼、共用時(shí)間片等)。

可以看下面這段代碼:

  1. #include<stdio.h> 
  2. #include<unistd.h> 
  3.  
  4. int main() 
  5.     int p_num = 0; 
  6.     int c_num = 0; 
  7.     int pid = fork(); 
  8.     if(pid == 0) //返回的pid為0為子進(jìn)程 
  9.     { 
  10.         c_num++; 
  11.     } 
  12.     else 
  13.     { 
  14.         p_num++; //返回的pid大于0為父進(jìn)程 
  15.     } 
  16.     printf("p_num=%d, c_num=%d\n",p_num,c_num); 
  17.     printf("pid=%d\n",pid); 
  18.     return 0; 
  19. //運(yùn)行結(jié)果如下所示 
  20. p_num=1, c_num=0 
  21. pid=36101 
  22. p_num=0, c_num=1 
  23. pid=0 

大家看,代碼中調(diào)用了fork以后,之后的程序被執(zhí)行了兩遍。子進(jìn)程和父進(jìn)程各自的變量互相沒(méi)有受到干擾。不過(guò)子進(jìn)程和父進(jìn)程執(zhí)行的是相同的代碼,子進(jìn)程和父進(jìn)程資源占用情況如下圖所示:

大家可以看出,通過(guò)fork后,子進(jìn)程并沒(méi)有和父進(jìn)程獨(dú)立開(kāi),用的是相同的代碼。另外還有一個(gè)問(wèn)題時(shí),這個(gè)時(shí)候子進(jìn)程的時(shí)間片是和父進(jìn)程一分為二來(lái)共享的。這樣我創(chuàng)建子進(jìn)程還有什么意義?為了徹底將父進(jìn)程和子進(jìn)程分離開(kāi)來(lái),就要用到一個(gè)系統(tǒng)調(diào)用 execv()。

看下面這段代碼:

  1. //process.c 
  2. #include<stdio.h> 
  3. #include<unistd.h> 
  4.  
  5. int main() 
  6.     int pid = fork(); 
  7.     if(pid == 0) 
  8.     { 
  9.         execv("./test.o",NULL);  //test.o是一個(gè)經(jīng)過(guò)編譯的c語(yǔ)言文件,這里記得要放test.o的絕對(duì)路徑 
  10.     } 
  11.     printf("This is parent process\n"); 
  12.     return 0; 
  13.  
  14. //test.c 
  15. #include<stdio.h> 
  16. int main() 
  17.     printf("This is child process"); 
  18.     return 0; 
  19.  
  20. //運(yùn)行結(jié)果如下所示 
  21. This is parent process 
  22. This is child process 

通過(guò)上面的代碼可以看出,從系統(tǒng)調(diào)用 execv() 后,子進(jìn)程直接走自己的代碼了,沒(méi)有像前一段代碼一樣把后面的代碼執(zhí)行了兩次。通過(guò)調(diào)用 execv(),子進(jìn)程和父進(jìn)程就基本分離開(kāi)了。

結(jié)合系統(tǒng)繼續(xù)看Linux的進(jìn)程樹(shù)是什么樣的

好了,通過(guò)上面的介紹,大家應(yīng)該對(duì)進(jìn)程是怎么創(chuàng)建的有一定的了解。想繼續(xù)學(xué)習(xí)的我們來(lái)接著上強(qiáng)度。

我們?cè)?Linux 系統(tǒng)上通過(guò) ps - ef 命令查看系統(tǒng)目前的進(jìn)程:

  1. /[root@localhost lucas]# ps -ef 
  2. UID          PID    PPID  C STIME TTY          TIME CMD 
  3. root           1       0  3 21:41 ?        00:02:38 /usr/lib/systemd/systemd --s 
  4. root           2       0  0 21:41 ?        00:00:07 [kthreadd] 
  5. root           3       2  0 21:41 ?        00:00:00 [rcu_gp] 
  6. root           4       2  0 21:41 ?        00:00:00 [rcu_par_gp] 
  7. ... 
  8. rtkit       1151       1  0 21:41 ?        00:00:14 /usr/libexec/rtkit-daemon 
  9. root        1152       1  0 21:41 ?        00:00:00 /usr/sbin/ModemManager 
  10. avahi       1155       1  0 21:41 ?        00:00:06 avahi-daemon: running [linux 
  11. root        1159       1  0 21:41 ?        00:00:02 /usr/lib/systemd/systemd-mac 

我來(lái)解釋上表是什么意思。

首先,每一個(gè)進(jìn)程都要所屬一個(gè)用戶(hù),UID 就是用戶(hù)的標(biāo)識(shí)符(通過(guò) root 用戶(hù)創(chuàng)建的進(jìn)程 UID 就是 root,如果我自己創(chuàng)建的話(huà)就應(yīng)該是我的用戶(hù)名,比如我的名字 "dabai")。

其次每一個(gè)進(jìn)程都要有一個(gè) ID 來(lái)表示這個(gè)進(jìn)程,PID 就表示的是當(dāng)前進(jìn)程的 id。

最后,上文提到除了 0 號(hào)進(jìn)程,每一個(gè)進(jìn)程都是由他的父進(jìn)程創(chuàng)建的,PPID 就表示當(dāng)前進(jìn)程的父進(jìn)程 id。

通過(guò) 0 號(hào)進(jìn)程創(chuàng)建 1 號(hào)進(jìn)程和 2 號(hào)進(jìn)程,然后通過(guò) 1 號(hào)進(jìn)程去創(chuàng)建用戶(hù)態(tài)進(jìn)程,再通過(guò) 2 號(hào)進(jìn)程創(chuàng)建內(nèi)核態(tài)進(jìn)程,就生成了 Linux 進(jìn)程樹(shù)。

「什么是0號(hào)進(jìn)程、1號(hào)進(jìn)程以及2號(hào)進(jìn)程?」。

0號(hào)進(jìn)程:在內(nèi)核初始化的過(guò)程中,會(huì)先通過(guò)指令 struct task_struct init_task = INIT_TASK(init_task) 創(chuàng)建 0 號(hào)進(jìn)程。這是唯一一個(gè)沒(méi)有通過(guò) fork 或者 kernel_thread 產(chǎn)生的進(jìn)程。是進(jìn)程列表的第一個(gè)。但是這個(gè)進(jìn)程不是實(shí)際意義上的進(jìn)程,類(lèi)似與鏈表頭。所以雖然 0 號(hào)進(jìn)程是在內(nèi)核態(tài)創(chuàng)建的,但不能說(shuō) 0 號(hào)進(jìn)程是內(nèi)核態(tài)的第一個(gè)進(jìn)程,反而要說(shuō) 2 號(hào)進(jìn)程是內(nèi)核態(tài)的第一個(gè)進(jìn)程。

1號(hào)進(jìn)程:通過(guò)調(diào)用指令 kernel_thread(kernel_init, NULL, CLONE_FS) 從內(nèi)核態(tài)切換到用戶(hù)態(tài)來(lái)創(chuàng)建的,1號(hào)進(jìn)程是所有用戶(hù)態(tài)的祖先。

2號(hào)進(jìn)程:通過(guò)調(diào)用指令 kernel_thread(kthreadd, NULL, ClONE_FS | CLONE_FILES) 來(lái)創(chuàng)建,2號(hào)進(jìn)程負(fù)責(zé)所有內(nèi)核態(tài)的進(jìn)程的調(diào)度和管理,是內(nèi)核態(tài)所有進(jìn)程的祖先。(注意,內(nèi)核態(tài)不區(qū)分線程和進(jìn)程,所以說(shuō)進(jìn)程和線程都可以,都是任務(wù))

「為什么要先創(chuàng)建 0 號(hào)進(jìn)程,而不直接創(chuàng)建 1 號(hào)進(jìn)程?」

現(xiàn)在對(duì)于為什么要先創(chuàng)建 0 號(hào)進(jìn)程而不直接創(chuàng)建1號(hào)和2號(hào)進(jìn)程有許多討論。我認(rèn)為...算了,我不認(rèn)為了,一展開(kāi)講這篇文章又收不了尾了,以后可以專(zhuān)門(mén)寫(xiě)一篇文章來(lái)論述這里。簡(jiǎn)單來(lái)說(shuō)就是Linux 的第一個(gè)進(jìn)程不適合是一個(gè)真進(jìn)程,需要一個(gè)沒(méi)有數(shù)據(jù)之類(lèi)東西的假進(jìn)程。

「為什么要區(qū)分用戶(hù)態(tài)和內(nèi)核態(tài)?」

因?yàn)橛辛硕鄠€(gè)進(jìn)程,對(duì)于關(guān)鍵資源來(lái)說(shuō),就會(huì)產(chǎn)生爭(zhēng)用以及誤操作破壞資源等情況。這時(shí)就需要對(duì)資源的訪問(wèn)權(quán)限進(jìn)行一定的限制。x86 提供了分層的權(quán)限機(jī)制,內(nèi)核態(tài)具有最高的訪問(wèn)權(quán)限,而用戶(hù)態(tài)訪問(wèn)核心資源時(shí)必須要切換到內(nèi)核態(tài)才可以訪問(wèn)。

好了,我看了下字?jǐn)?shù),這篇文章已經(jīng)不少了,接下來(lái)我還會(huì)繼續(xù)去分享進(jìn)程和線程的更多細(xì)節(jié),也會(huì)根據(jù)讀者的反饋在已完成的文章上不斷完善,歡迎大家持續(xù)關(guān)注呀!

參考資料:

【1】Linux進(jìn)程的創(chuàng)建與管理:https://blog.csdn.net/qq_38410730/article/details/81193118

【2】極客時(shí)間:《趣談Linux操作系統(tǒng)》

 

責(zé)任編輯:武曉燕 來(lái)源: CS指南
相關(guān)推薦

2022-07-18 13:59:43

Redis單線程進(jìn)程

2021-12-02 08:19:06

MVCC面試數(shù)據(jù)庫(kù)

2023-02-16 07:30:38

引用計(jì)數(shù)算法

2020-03-10 08:01:05

Java堆內(nèi)存線程共享

2024-09-03 07:58:46

2020-07-02 07:52:11

RedisHash映射

2020-11-10 13:47:29

String源碼長(zhǎng)度限制

2022-07-26 08:40:42

Java并發(fā)工具類(lèi)

2022-08-02 06:31:32

Java并發(fā)工具類(lèi)

2020-12-23 13:29:15

微服務(wù)架構(gòu)面試官

2020-02-25 16:56:02

面試官有話(huà)想說(shuō)

2021-12-13 09:10:48

equalshashCodeJava

2022-06-30 08:14:05

Java阻塞隊(duì)列

2021-12-03 06:59:23

HashCodeEquals面試

2022-07-11 10:47:46

容器JAVA

2022-05-23 08:43:02

BigIntJavaScript內(nèi)置對(duì)象

2021-06-28 17:26:15

歸并排序建模

2015-08-13 10:29:12

面試面試官

2021-03-24 10:25:24

優(yōu)化VUE性能

2021-09-28 13:42:55

Chrome Devwebsocket網(wǎng)絡(luò)協(xié)議
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)