欧美free性护士vide0shd,老熟女,一区二区三区,久久久久夜夜夜精品国产,久久久久久综合网天天,欧美成人护士h版

首頁綜合 正文
目錄

柚子快報激活碼778899分享:初識Linux下進(jìn)程

柚子快報激活碼778899分享:初識Linux下進(jìn)程

http://yzkb.51969.com/

?初識Linux下進(jìn)程(下)

文章目錄:

初識Linux下進(jìn)程

????獲取進(jìn)程pid的系統(tǒng)調(diào)用

????進(jìn)程中的路徑信息

????創(chuàng)建進(jìn)程

??????fork的返回值 ??????子進(jìn)程的用處 ??????再談fork返回值

????總結(jié)

前言:

??上回我們簡單介紹了一下進(jìn)程的概念以及讓大家見到了運行中的進(jìn)程,今天我們來了解更多進(jìn)程相關(guān)知識,話不多說,開啟我們今天的話題!

?系統(tǒng)調(diào)用獲得父子進(jìn)程id

??上次我們說,pid是每個進(jìn)程特有的一個編號,每個進(jìn)程都有自己的pid,這也是進(jìn)程的一個屬性信息,屬于 操作系統(tǒng)內(nèi)核數(shù)據(jù)結(jié)構(gòu), 我們知道,內(nèi)核數(shù)據(jù)結(jié)構(gòu)是不能被用戶直接拿來使用的,而是需要通過 系統(tǒng)調(diào)用 的方式來獲取屬性信息:

??而 獲取進(jìn)程pid 的系統(tǒng)調(diào)用接口就是 getpid,為了了解這個接口,我們可以使用:

man getpid#man手冊查看系統(tǒng)調(diào)用接口

??我們可以看到,一個程序想要調(diào)用系統(tǒng)調(diào)用接口getpid,就必須包含 頭文件。

??具體的用法是:

??我們運行程序就可以得到這個進(jìn)程的pid了:

??我們發(fā)現(xiàn),我們運行三次,每一次進(jìn)程的 pid 都是不一樣的,其實這是因為:

??進(jìn)程的pid是系統(tǒng)中一個重要且有限的資源,當(dāng)程序終止運行時,pid就會被bash回收,而再次運行時,bash會隨機(jī)分配給你空閑的pid使用。

??我們可以使用一個監(jiān)控腳本,用來持續(xù)控制輸出的進(jìn)程信息:

while :; do ps ajx | head -1 && ps ajx | grep myprocess | grep -v grep; sleep 1; done#控制進(jìn)程每隔一秒輸出進(jìn)程信息

??當(dāng)進(jìn)程被終止的時候,進(jìn)程信息也會被bash回收,在進(jìn)程終止之前,我們看到了進(jìn)程除了有pid,還有它的ppid,也就是父進(jìn)程id,那么我們是否可以通過系統(tǒng)調(diào)用的方式來獲得父進(jìn)程的pid呢?當(dāng)然是可以的:

??程序保存退出,將原來的可執(zhí)行程序make clean 一下,再make一下得到新的可執(zhí)行程序,然后運行該程序:

??我們可以看到,該進(jìn)程的id為6331,父進(jìn)程id為5506,我們知道,如果我們進(jìn)程重新啟動,那么我們進(jìn)程的pid就有很大概率會被改變,那么我們父進(jìn)程是否也是如此呢?

??我們可以看到,每一次重新啟動進(jìn)程,進(jìn)程的id都會改變,但是每次啟動進(jìn)程的時候,進(jìn)程的ppid確是不會改變的,其實我們查看該父進(jìn)程:

??我們看到,該進(jìn)程的父進(jìn)程就是bash,所以 每次啟動時進(jìn)程的父進(jìn)程不會改變。

?進(jìn)程信息中的路徑信息

??我們查看一個普通進(jìn)程的進(jìn)程信息時,會發(fā)現(xiàn) exe 和 cwd 兩項信息,我們可以使用如下命令進(jìn)行查看:

ls /proc/進(jìn)程標(biāo)識符/ -l#進(jìn)程標(biāo)識符為進(jìn)程的id

??這里我們需要關(guān)注到兩個重要信息,cwd 和 exe, exe就不用多說了,就是 可執(zhí)行程序,cwd全稱叫做(current working directory),表示 當(dāng)前工作目錄。

??其實我們還學(xué)過于此相關(guān)的一個芝士,我們在C語言文件操作那里,有這樣一個函數(shù):

fopen("file.txt", "w");

??我們都知道,如果在當(dāng)前路徑下沒有這個文件,就會在當(dāng)前路徑下創(chuàng)建這個文件,其實就是在cwd路徑下創(chuàng)建,當(dāng)系統(tǒng)在執(zhí)行C語言代碼時,執(zhí)行到當(dāng)前這行就會拿到進(jìn)程的cwd。

??注意:進(jìn)程只有 運行起來的程序 才可以查看進(jìn)程,所以要查看進(jìn)程,進(jìn)程必須要保證在查看的那一刻進(jìn)程是在運行的。

??但是如果進(jìn)程是在 運行時被干掉 的,此時我們依然可以查看該進(jìn)程的信息狀態(tài):

??這個時候我們就可以發(fā)現(xiàn),我們的exe狀態(tài)欄會閃紅,并且在最后會提示該進(jìn)程已經(jīng)刪除。

??但是這里有個疑問:為什么我們把進(jìn)程刪除了還能繼續(xù)運行?

??實際上,我們運行的本質(zhì)就是 把磁盤中的數(shù)據(jù)拷貝一份到內(nèi)存中 來,我們把磁盤中的數(shù)據(jù)刪除了,但是我們內(nèi)存中的數(shù)據(jù)還在,所以還是可以運行的。

??我們上面說,fopen函數(shù)在執(zhí)行到改行的時候會 拿到進(jìn)程的 cwd 然后創(chuàng)建文件,我們不妨做個測試:

1 #include

2 #include

3 #include

4

5 int main()

6 {

7 printf("myself id: %d\n", getpid());

8 FILE *fp = fopen("./test.txt", "w");//當(dāng)前目錄下創(chuàng)建一個文件,

9 if(fp == NULL) return -1;

10

11 fclose(fp);

12

13 sleep(5);//休眠5秒看到結(jié)果

14

15 return 0;

16 }

??通過實驗我們可以看到,確實是在當(dāng)前路徑下創(chuàng)建的文件,但是我們?nèi)绻⒉幌朐诋?dāng)前路徑下創(chuàng)建文件,想要按照自己指定的路徑下來創(chuàng)建文件,我們可以使用 chdir 接口:

??這里的 const char* 表示字符串信息,這個字符串信息是 指定的工作目錄,我們不妨做個實驗:

1 #include

2 #include

3 #include

4

5 int main()

6 {

7 printf("myself id: %d\n", getpid());

8 printf("更改當(dāng)前工作目錄之前\n");

9 sleep(5);

10

11 chdir("home/xzy");//將工作目錄更改為家目錄

12 printf("更改工作目錄之后\n");

13 sleep(5);

14

15 FILE *fp = fopen("./test.txt", "w");

16

17 if(fp == NULL) return -1;

18 fclose(fp);

19 sleep(5);

20

21 return 0;

22 }

??我們使用 chdir 來更改工作目錄,以至于達(dá)成想要的效果。

??更改工作目錄之前:

??更改工作目錄之后:

??由此,也能證明我們經(jīng)常使用的fopen函數(shù)是從進(jìn)程的cwd獲取路徑的。

?創(chuàng)建進(jìn)程

??創(chuàng)建一個進(jìn)程需要使用到 fork 函數(shù)接口:

??fork函數(shù)是用來創(chuàng)建子進(jìn)程的接口,至于到底該如何使用該接口,我們看下面這個例子:

#include

2 #include

3 #include

4

5 int main()

6 {

7 printf("before fork, pid=%d, ppid=%d\n",getpid(),getppid());

8

9

10 fork();

11

12 printf("after fork, pid=%d, ppid=%d\n",getpid(),getppid());

13 return 0;

14 }

??我們在Shell上運行起來可以觀察到:

??運行起來之后,我們發(fā)現(xiàn),fork之前的打印只執(zhí)行了一次,而fork之后的打印卻執(zhí)行了兩次,多次運行都是這個結(jié)果,說明并不是偶然現(xiàn)象。

??其實,fork()之后是創(chuàng)建了子進(jìn)程,執(zhí)行下面的代碼,這樣就有兩個進(jìn)程,并且都會執(zhí)行fork之后的代碼。但是fork之前的代碼只有父進(jìn)程執(zhí)行。

??證明:fork之后,進(jìn)程ppid(父進(jìn)程id)就是fork之前進(jìn)程的pid。

??fork的返回值

??fork可以創(chuàng)建子進(jìn)程,而要控制子進(jìn)程,就與fork的返回值有關(guān)了。

??fork的返回值是pid_t的一種特殊類型,返回值為0時返回到子進(jìn)程,返回值為子進(jìn)程pid時,返回到父進(jìn)程,如果返回值小于0表示錯誤。也就是說,fork其實有兩個返回值。

?&emps;我們不妨做個實驗驗證一下:

#include

2 #include

3 #include

4

5 int main()

6 {

7 pid_t id = fork();

8 if(id == 0)

9 {

10 printf("this is child process, pid=%d, ppid=%d, forkid = %d\n",getpid(),getppid(),id);

11 }

12 printf("this is parent process, pid=%d, ppid=%d, forkid = %d\n",getpid(),getppid(),id);

13 return 0;

14 }

??根據(jù)實驗結(jié)果來看,fork之后的返回值確實有兩個,返回給父進(jìn)程子進(jìn)程的pid,返回0給子進(jìn)程。至于為什么有兩個返回值,這里我們說不清,現(xiàn)在只需要記住即可,后面我們會詳談。

??子進(jìn)程的用處

??fork創(chuàng)建子進(jìn)程,創(chuàng)建子進(jìn)程的目的一定是為了能夠給我們做更多的事情,做父進(jìn)程以外的事情.

1 #include

2 #include

3 #include

4

5 int main()

6 {

7 printf("before fork, porcess pid=%d, ppid=%d\n",getpid(), getppid());//進(jìn)程創(chuàng)建之前的pid和ppid

8 sleep(3);

9 printf("start fork!\n");

10 sleep(1);

11

12 pid_t id = fork();//開始fork

13

14 if(id < 0)

15 {

16 perror("fork fail!\n");

17 return -1;

18 }

19

20 if(id == 0) {

21 //子進(jìn)程

22 while(1)

23 {

24 printf("after fork, process pid=%d, ppid=%d\n", getpid(), getppid());

25 sleep(1);

26 }

27 }

28 else {

29 //父進(jìn)程

30 while(1)

31 {

32 printf("after fork, process pid=%d, ppid=%d\n", getpid(), getppid());

33 sleep(1);

34 }

35 }

36

37 sleep(1);

38 return 0;

39 }

??這里我們在父子進(jìn)程當(dāng)中都有一個死循環(huán),我們運行程序:

??不難觀察到子進(jìn)程和父進(jìn)程是在同時運行的,這也驗證了,fork之后創(chuàng)建了一個新的進(jìn)程——子進(jìn)程,與父進(jìn)程同時執(zhí)行。

??我們前面說過,進(jìn)程 = 內(nèi)核數(shù)據(jù)結(jié)構(gòu) + 可執(zhí)行程序的代碼和數(shù)據(jù),而子進(jìn)程能夠執(zhí)行父進(jìn)程代碼的原因,是因為 子進(jìn)程被創(chuàng)建時,是以父進(jìn)程為模版的。子進(jìn)程復(fù)制拷貝了父進(jìn)程屬性字段的大部分屬性。

注意:子進(jìn)程雖然繼承父進(jìn)程的一些屬性信息,但是像進(jìn)程標(biāo)識符(pid)等信息并不會復(fù)制父進(jìn)程。并且代碼只有一份,所以父子進(jìn)程共享代碼。

??再談fork返回值

??前面我們說,fork之后的返回值有兩個,通過上面的實驗我們也可說明fork之后確實同時存在兩個返回值。一個為0,一個為子進(jìn)程pid。

??但是為什么給子進(jìn)程返回0,父進(jìn)程返回pid呢?

??一個父親,可以有多個孩子,而每個孩子,都只有唯一的父親。如果孩子去上學(xué),生活費不夠了,可以向同一個父親要,而父親也會準(zhǔn)確的給缺錢的兒子發(fā)生活費。 ??進(jìn)程也是如此,因為子進(jìn)程有多個,要想父進(jìn)程準(zhǔn)確無誤的找到子進(jìn)程就需要子進(jìn)程的pid,而子進(jìn)程只有一個父親,并不需要返回特殊值。

??為什么fork會返回兩次呢?

??我們從man手冊里也查過了,fork是個函數(shù),這個毋庸置疑,既然是函數(shù),并且有類型,那么就有返回值,類似于:

pid_t fork()

{

//...

//...

return id;

}

??我們在系統(tǒng)中執(zhí)行程序,可執(zhí)行程序變?yōu)檫M(jìn)程,進(jìn)程調(diào)用fork函數(shù)從而創(chuàng)建子進(jìn)程,而fork函數(shù)內(nèi)部,在return 之前,我們的子進(jìn)程就已經(jīng)創(chuàng)建完畢,最后return的只是id值。

??也就是說 在return返回之前,子進(jìn)程已經(jīng)創(chuàng)建出來了,并且和父進(jìn)程同時在執(zhí)行,兩個進(jìn)程返回不同的id值也就能說的過去了!

??為什么接收fork的返回值的變量id既等于0,又大于0呢?

??我們之前說過,電腦里啟動的一個個應(yīng)用軟件就是一個個進(jìn)程,比如你再電腦登陸QQ、打開VS等應(yīng)用,都是進(jìn)程,那么如果你的QQ卡死了,會影響其他軟件嗎?并不會,所以在這里我們可以得到的結(jié)論是:每個進(jìn)程都具有獨立性,互不干擾!

??所以,如果一個進(jìn)程創(chuàng)建了子進(jìn)程,那么 隨意殺掉一個進(jìn)程,是不會影響另外一個進(jìn)程的。我們不妨做一個實驗:

1 #include

2 #include

3 #include

4

5 int main()

6 {

7 printf("before fork, porcess pid=%d, ppid=%d\n",getpid(), getppid());//進(jìn)程創(chuàng)建之前的pid和ppid

8 sleep(3);

9 printf("start fork!\n");

10 sleep(1);

11

12 pid_t id = fork();//開始fork

13

14 if(id < 0)

15 {

16 perror("fork fail!\n");

17 return -1;

18 }

19

20 if(id == 0) {

21 //子進(jìn)程

22 while(1)

23 {

24 printf("after fork, process pid=%d, ppid=%d\n", getpid(), getppid());

25 sleep(1);

26 }

27 }

28 else {

29 //父進(jìn)程

30 while(1)

31 {

32 printf("after fork, process pid=%d, ppid=%d\n", getpid(), getppid());

33 sleep(1);

34 }

35 }

36

37 sleep(1);

38 return 0;

39 }

使用命令:

kill -9 進(jìn)程標(biāo)識符#殺死進(jìn)程的信號

??從運行的結(jié)果來看,殺死一個進(jìn)程確實不會影響另一個進(jìn)程,就算是親如父子的進(jìn)程。

??而我想說明的是,既然父子進(jìn)程各自獨立,而他們又共享代碼區(qū)數(shù)據(jù)區(qū),那么如果一個進(jìn)程需要更改數(shù)據(jù)時這不就間接影響了另一個進(jìn)程嗎?

??進(jìn)程之間相互獨立沒有問題,當(dāng)兩個進(jìn)程有一個需要修改原始數(shù)據(jù)時,子進(jìn)程就會發(fā)生 寫時拷貝( Copy-On-Write ,以后會詳談),子進(jìn)程將父進(jìn)程的原始數(shù)據(jù)段復(fù)制下來,這樣兩個進(jìn)程修改數(shù)據(jù)就不會影響彼此了。

??那么我們再考慮那個問題,fork為什么既可以是0又可以是別的數(shù),fork在返回時返回的操作,就是在對變量進(jìn)行寫入,所以子進(jìn)程會發(fā)生寫時拷貝。

??雖然他們的id(接收fork返回值的變量)都是同一個,但是數(shù)據(jù)卻是不一樣(這里有 虛擬地址 的知識,我們以后會講),所以fork能既可以是0又可以是其他數(shù)就解釋的通了。

???總結(jié)

??通過 系統(tǒng)調(diào)用接口 來獲取父子進(jìn)程的pid。??運行起來的程序是 通過進(jìn)程屬性信息中的 cwd 來獲取路徑信息 的。??創(chuàng)建子進(jìn)程需要使用 fork函數(shù)接口,子進(jìn)程會 繼承父進(jìn)程的部分屬性字段,并且和父進(jìn)程 共享代碼段。??fork能返回兩個不同的數(shù)給同一個變量靠的是 寫時拷貝技術(shù) 和虛擬地址空間。

??創(chuàng)作不易,如果能幫到你的話,還望能留下一個小小的三連呀~~

柚子快報激活碼778899分享:初識Linux下進(jìn)程

http://yzkb.51969.com/

相關(guān)閱讀

評論可見,查看隱藏內(nèi)容

本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。

轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。

本文鏈接:http://gantiao.com.cn/post/19546003.html

發(fā)布評論

您暫未設(shè)置收款碼

請在主題配置——文章設(shè)置里上傳

掃描二維碼手機(jī)訪問

文章目錄