一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

進(jìn)程和環(huán)境變量的相關(guān)概念

 灞河之濱 2020-05-29

一,進(jìn)程

1. 進(jìn)程的概念

       簡單的說,一個執(zhí)行中的程序就是一個進(jìn)程。具體說, 進(jìn)程是一個分配系統(tǒng)資源的活動實體,它包含以下兩點:

(1)實體,每個進(jìn)程都有一段地址空間,在這段空間中,用于存放程序的代碼,數(shù)據(jù),指令的地址等靜態(tài)的事物;

(2)程序運行的過程,是一個動態(tài)的概念,即需不斷申請占用系統(tǒng)資源的當(dāng)前的活動過程。

總之,進(jìn)程不僅包含有關(guān)程序的一些靜態(tài)事物,還有需不斷申請系統(tǒng)資源的動態(tài)的過程。

2. 進(jìn)程的創(chuàng)建過程

進(jìn)程形成的方法:

(1)一個程序要運行起來,首先要被加載到內(nèi)存上,這時,就形成了進(jìn)程。該進(jìn)程的父進(jìn)程是bush。

(2)通過系統(tǒng)調(diào)用來創(chuàng)建,在一個進(jìn)程中利用fork,vfork函數(shù)創(chuàng)建子進(jìn)程,該子進(jìn)程的父進(jìn)程就是創(chuàng)建它的的進(jìn)程。(關(guān)于fork,vfork的使用,在后文中有詳細(xì)說明)

形成之后:

        操作系統(tǒng)要對該進(jìn)程進(jìn)行管理,但并不和該進(jìn)程的程序代碼等直接接觸。而是:

(1)描述:將該進(jìn)程的相關(guān)屬性信息描述起來,放在一個叫進(jìn)程控制塊的數(shù)據(jù)結(jié)構(gòu)中,將進(jìn)程控制塊統(tǒng)稱為PCB,在Linux中稱PCB為task_struct,task_struct由操作系統(tǒng)創(chuàng)建。

(2)組織:操作系統(tǒng)將各進(jìn)程的PCB利用鏈表的形式組織起來,放在內(nèi)核中。這樣,操作系統(tǒng)就可以對各進(jìn)程進(jìn)行統(tǒng)一管理了。

(3)為各進(jìn)程分別創(chuàng)建一個虛擬地址空間(也是一個結(jié)構(gòu)體:mm_struct),頁表,映射關(guān)系。

        各進(jìn)程的相關(guān)代碼和數(shù)據(jù)都存放在物理內(nèi)存中,但操作系統(tǒng)并不直接對物理內(nèi)存進(jìn)行操作,而是將虛擬地址通過頁表映射到物理內(nèi)存地址上,從而對其進(jìn)行操作。該虛擬地址空間由上述的PCB中的指針指向,這樣,操作系統(tǒng)便可管理該進(jìn)程了。

        總之,一個進(jìn)程的創(chuàng)建,操作系統(tǒng)需:

(1)描述并創(chuàng)建PCB,并將其鏈入鏈表組織起來放入內(nèi)核

(2)創(chuàng)建虛擬地址空間,頁表,映射關(guān)系

3. task_struct的內(nèi)容

標(biāo)識符PID:描述本進(jìn)程的唯一標(biāo)識符,用于區(qū)別其他進(jìn)程,類似于學(xué)生的學(xué)號,人的身份證號。

狀態(tài):包括任務(wù)狀態(tài),退出代碼,退出信號等。

優(yōu)先級:一個CPU一次只能運行一個進(jìn)程,運行哪個進(jìn)程要根據(jù)其優(yōu)先級來判斷

程序計數(shù)器:存放程序中即將被執(zhí)行的下一條指令的地址,類似于寄存器PC的存在

內(nèi)存指針:包含程序代碼和進(jìn)程數(shù)據(jù)相關(guān)的指針,還有和其他進(jìn)程共享的內(nèi)存塊的指針

上下文數(shù)據(jù):進(jìn)程執(zhí)行時處理器的寄存器中的數(shù)據(jù)

I/O狀態(tài)信息:包括顯示的I/O請求,分配給進(jìn)程的I/O設(shè)備,被進(jìn)程使用的文件列表

記賬信息:包括進(jìn)程存在的時間總和等。

其中:

進(jìn)程的狀態(tài)包含:

(1)R:運行狀態(tài),處于該狀態(tài)的進(jìn)程要么在運行要么處于運行隊列中

(2)S:淺度睡眠狀態(tài),可以被中斷,可以用kill命令殺死

(3)D:深度睡眠狀態(tài),不可被中斷,不可被殺死,一般在I/O時發(fā)生,要結(jié)束該狀態(tài)的進(jìn)程,要么等I/O結(jié)束,要么關(guān)機

(4)T:停止?fàn)顟B(tài)

(5)Z:僵尸狀態(tài):進(jìn)程退出后一直維持該狀態(tài),直到該進(jìn)程的父進(jìn)程讀取了他的退出信息后,將其釋放。

狀態(tài)的優(yōu)先級:CPU根據(jù)優(yōu)先級來決定運行進(jìn)程的先后順序

        可以通過ps -l命令來查看優(yōu)先級,其中:

PRI:表示進(jìn)程的優(yōu)先級,此值越小優(yōu)先級越高

NI:優(yōu)先級的修正數(shù)值

所以,PRI=PRI(80)+NI(-20~19)

可以通過命令來修改NI:

(1)renice:修改已存在進(jìn)程的優(yōu)先級:renice    NI的值   -p    要修改進(jìn)程PID

(2)nice:修改啟動前的進(jìn)程的優(yōu)先級:nice  -n   NI的值    可執(zhí)行程序路徑

        運行如下進(jìn)程:

  1. #include<stdio.h>
  2. int main()
  3. {
  4. while(1)
  5. {
  6. sleep(1);
  7. }
  8. return 0;
  9. }

        執(zhí)行如下命令:


        或者,在進(jìn)程啟動前,輸入以下命令:


4. 查看進(jìn)程

        在一個進(jìn)程運行過程中,需要知道如何查看該進(jìn)程是否被創(chuàng)建成功。

(1)Linux下輸入命令:

ls /proc

        該命令用于顯示進(jìn)程目錄/proc中所有當(dāng)前正在運行的進(jìn)程


        這些數(shù)字即為正在運行進(jìn)程的PID。

(2)通過命令ps或top獲取進(jìn)程信息。

(3)利用系統(tǒng)調(diào)用獲取進(jìn)程標(biāo)識符

  1. pid_t getpid();//獲取當(dāng)前進(jìn)程的PID
  2. pid_t getppid();//獲取當(dāng)前進(jìn)程的父進(jìn)程的PID

這兩個函數(shù)均需引用頭文件<sys/types.h>和<unistd.h>

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

         在了解了進(jìn)程的相關(guān)信息后,接下來,我們來創(chuàng)建一個進(jìn)程。

(1)通過運行程序來創(chuàng)建

        注意:進(jìn)程是一個動態(tài)的過程,程序在運行期間,進(jìn)程被創(chuàng)建,一旦程序運行結(jié)束,進(jìn)程也就退出了。

        那么,程序在一瞬間就運行結(jié)束,我們?nèi)绾沃肋M(jìn)程是否被創(chuàng)建呢?

        編寫如下代碼,使程序一直運行:

  1. #include<stdio.h>
  2. int main()
  3. {
  4. while(1)
  5. {
  6. sleep(1);
  7. }
  8. return 0;
  9. }

        編譯鏈接運行該程序:


        我們發(fā)現(xiàn)該程序一直在運行,也就是該進(jìn)程一直存在,但怎么獲取該進(jìn)程相關(guān)的信息呢?

        這時,需要該進(jìn)程在后臺運行,從而獲取其相關(guān)信息,輸入以下指令:


        輸出的數(shù)字為該進(jìn)程的PID,這時,查看/proc目錄,可以看到該進(jìn)程的PID在該目錄中。說明該進(jìn)程已經(jīng)被創(chuàng)建成功,當(dāng)輸入:

kill -9 7856(進(jìn)程的PID)

        可通過該命令殺死該進(jìn)程,此時,在查看/proc目錄時,已經(jīng)沒有該進(jìn)程的PID了。說明該進(jìn)程已經(jīng)結(jié)束。

(2)利用fork函數(shù)創(chuàng)建子進(jìn)程

        fork創(chuàng)建子進(jìn)程后,子,父進(jìn)程對fork語句之后的代碼和沒有修改的數(shù)據(jù)進(jìn)行共享,如果數(shù)據(jù)被父或子進(jìn)程修改,則在父,子進(jìn)程中會各自開辟存放該數(shù)據(jù)的內(nèi)存,采取寫實拷貝。

        fork函數(shù)的返回值情況:

1)若子進(jìn)程創(chuàng)建成功,向父進(jìn)程返回子進(jìn)程的PID,向子進(jìn)程返回0;

2)若子進(jìn)程創(chuàng)建失敗,則返回-1。

    運行如下程序:

  1. #include<stdio.h>
  2. #include<sys/types.h>
  3. #include<unistd.h>
  4. int main()
  5. {
  6. int ret=fork();
  7. if(ret<0)
  8. {
  9. printf("fork error!\n");
  10. return 1;
  11. }
  12. else if(ret == 0)//子進(jìn)程
  13. {
  14. printf("child:pid=%d,ppid=%d,ret=%d\n",getpid(),getppid(),ret);
  15. }
  16. else//父進(jìn)程
  17. {
  18. printf("farther:pid=%d,ppid=%d,ret=%d\n",getpid(),getppid(),ret);
  19. }
  20. sleep(1);
  21. return 0;
  22. }

        運行結(jié)果:


        可以看到,在子進(jìn)程創(chuàng)建后,先運行父進(jìn)程,在運行子進(jìn)程,返回值情況確實滿足上述兩點。

注意:fork創(chuàng)建子進(jìn)程后,誰先運行是不確定的。

(3)利用vfork創(chuàng)建子進(jìn)程

        vfork的用法與fork相同,只是,有下列區(qū)別:

1)vfork創(chuàng)建子進(jìn)程后,子,父進(jìn)程共享代碼和數(shù)據(jù)

2)先運行子進(jìn)程,子進(jìn)程只有通過調(diào)用exit或exec結(jié)束后,父進(jìn)程才開始運行

6. 僵尸進(jìn)程

        就是處于僵尸狀態(tài)的進(jìn)程,當(dāng)子進(jìn)程退出,父進(jìn)程沒有讀取子進(jìn)程的退出信息時,子進(jìn)程就一直處于僵尸狀態(tài)。

        運行以下程序來創(chuàng)建僵尸進(jìn)程:

  1. #include<stdio.h>
  2. #include<sys/types.h>
  3. #include<unistd.h>
  4. #include<stdlib.h>
  5. int main()
  6. {
  7. int ret=fork();
  8. if(ret<0)
  9. {
  10. printf("fork error!\n");
  11. return 1;
  12. }
  13. else if(ret>0)//父進(jìn)程
  14. {
  15. printf("farther:pid=%d,ppid=%d,ret=%d\n",getpid(),getppid(),ret);
  16. sleep(30);//30s后父進(jìn)程退出
  17. }
  18. else//子進(jìn)程
  19. {
  20. printf("child:pid=%d,ppid=%d,ret=%d\n",getpid(),getppid(),ret);
  21. sleep(5);//5s后子進(jìn)程退出
  22. exit(1);
  23. }
  24. return 0;
  25. }

        在該程序運行5s內(nèi),子,父進(jìn)程都在運行。5s后,子進(jìn)程運行結(jié)束,此時,父進(jìn)程還在運行,還沒來得及獲取子進(jìn)程的退出信息,所以,5s后子進(jìn)程變?yōu)榻┦M(jìn)程;30s后父進(jìn)程運行結(jié)束,子父進(jìn)程均退出。

        輸入以下命令,觀察處于僵尸狀態(tài)的子進(jìn)程:

        進(jìn)程開始運行后5s內(nèi):


        5s后:


        30s后:


7. 孤兒進(jìn)程

        如果父進(jìn)程先退出,而子進(jìn)程還在進(jìn)行,此時,子進(jìn)程就會變成孤兒進(jìn)程。 孤兒進(jìn)程會被1號進(jìn)程領(lǐng)養(yǎng),該孤兒進(jìn)程退出后,就會被1還進(jìn)程回收。

        下面,演示一個孤兒進(jìn)程的例子:

  1. #include<stdio.h>
  2. #include<sys/types.h>
  3. #include<unistd.h>
  4. #include<stdlib.h>
  5. int main()
  6. {
  7. int ret = fork();
  8. if(ret == -1)
  9. {
  10. perror("fork error\n");
  11. return 1;
  12. }
  13. else if(ret > 0)//父進(jìn)程,先結(jié)束
  14. {
  15. printf("pid = %d,ppid = %d ret = %d\n",getpid(),getppid(),ret);
  16. }
  17. else//子進(jìn)程,30s后再結(jié)束
  18. {
  19. printf("pid = %d,ppid = %d ret = %d\n",getpid(),getppid(),ret);
  20. sleep(30);
  21. }
  22. return 0;
  23. }

        在該例中,父進(jìn)程執(zhí)行完畢后,即退出,而子進(jìn)程30s后才退出,所以,來觀察下子進(jìn)程的父進(jìn)程的PID來驗證它是否被1號進(jìn)程領(lǐng)養(yǎng)。

        結(jié)果如下:


二,環(huán)境變量

        環(huán)境變量是操作系統(tǒng)中指定程序運行環(huán)境的一些變量,比如,在鏈接庫文件時,這些庫文件在哪里,去哪里找,這些信息都存放在環(huán)境變量中。

        環(huán)境變量通常具有某些特殊用途,在系統(tǒng)中通常具有全局特性。

1. 常見環(huán)境變量

(1)PATH:存放系統(tǒng)常用命令的搜索路徑的變量

        查看該變量的內(nèi)容,輸入命令:

echo $PATH

        輸出結(jié)果:

/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/admin/bin

        每個路徑用分號相隔。比如,常用的命令ls,我們在運行它的時候,并沒有加上的路徑,并不知道該命令的可執(zhí)行程序放在哪里,這時,操作系統(tǒng),就會根據(jù)PATH中提供的路徑,一條路徑一條路徑的找,直到找到為止。

        我們自己編寫形成的可執(zhí)行程序a.out在運行時,必須加上路徑,如:./a.out,表示運行當(dāng)前路徑下的a.out。那如何能像運行l(wèi)s一樣不加路徑呢,有如下兩種方法:

1)將可執(zhí)行程序a.out放在PATH指定的路徑下,那么在運行時,就會根據(jù)PATH中的路徑去找a.out所在的位置。

如:cp  ./a.out  /bin

2)將a.out的路徑放入到PATH變量中。這時,需要先明白a.out的路徑,再進(jìn)行存放,輸入命令:


        $PATH表示原有的內(nèi)容,即上述查看PATH時輸出的內(nèi)容。 :/home/admin/bit_code/Linux表示在原有PATH的基礎(chǔ)上追加該路徑;然后把原有PATH的內(nèi)容和追加后的路徑一起賦給變量PATH;export是導(dǎo)出變量PATH,即更新PATH。

        再次進(jìn)行查看時,便可看到a.out的路徑已經(jīng)在變量PATH中:


        若要刪除新存放的路徑,只需要關(guān)閉終端,再次打開即可。

        如果不想關(guān)閉終端來刪除新追加的路徑,只需輸入以下命令即可:

export PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/admin/bin

(2)HOME:指定用戶的主工作目錄(可以用echo命令來進(jìn)行查看)

(3)HISTSIZE:系統(tǒng)中默認(rèn)保存的歷史命令的條數(shù),一般是1000。(以同樣的方法可查看)

        若要查看歷史命令,只需輸入命令:history

(4)SHELL:查看當(dāng)前使用的shell

2. 常用的有關(guān)環(huán)境變量的命令

(1)echo:查看環(huán)境變量的內(nèi)容,上述已經(jīng)說明

(2)export:設(shè)置一個新的環(huán)境變量

        1)更新原有環(huán)境變量的值,(這里不加export也可以,因為該變量已經(jīng)是環(huán)境變量,但最好加上)上述已經(jīng)驗證

        2)將本地變量變成環(huán)境變量。

        將MYENV設(shè)置為環(huán)境變量,在終端運行以下命令:

MYENY="hello world"

        用echo查看時,沒有結(jié)果,說明該環(huán)境變量沒有設(shè)置成功,他只是一個本地變量。

        再在終端運行以下命令:

export MYENY="hello world"

        用echo查看時,可以看到結(jié)果,說明該環(huán)境變量設(shè)置成功。

        所以,export的作用是設(shè)置環(huán)境變量。如果環(huán)境變量已經(jīng)存在,可以理解為更新環(huán)境變量的值(也可以不加);如果環(huán)境變量不存在,就必須用export設(shè)置環(huán)境變量。

        注意:使用export設(shè)置的環(huán)境變量在關(guān)閉中斷后即失效        

(3)env:查看系統(tǒng)中存在的所有環(huán)境變量及其值

(4)set:顯示所有本地定義的shell變量及環(huán)境變量和其相應(yīng)的值(注意與env的區(qū)別)

        運行以下命令:

MYENV="hello world"

        上述已經(jīng)說明,該變量不是環(huán)境變量(用env查看沒有結(jié)果),所以是本地變量,用set查看:

set | grep MYENV

        這時會顯示結(jié)果:

MYENV='hello world'

        說明,set可以顯示本地變量,同樣可以顯示環(huán)境變量,這里不再說明。

(5)unset:清除環(huán)境變量

        先用export設(shè)置環(huán)境變量MYENV,再用env查看是否創(chuàng)建成功,創(chuàng)建成功后,在用unset清除該環(huán)境變量,在用env查看是否清除成功。如下:


3. 環(huán)境變量的全局特性

        首先通過命令在終端設(shè)置本地變量:MYENV=“hello world”,然后通過以下程序(即子進(jìn)程,bash為父進(jìn)程)輸出該環(huán)境變量的值。

        下面先介紹一個系統(tǒng)調(diào)用getenv

  1. #include <stdlib.h>//需引用的頭文件
  2. char *getenv(const char *name);//函數(shù)原型,該函數(shù)用于獲取指定環(huán)境變量的值,參數(shù)是環(huán)境變量的名稱字符串

        再運行以下代碼,輸出環(huán)境變量的值:

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. int main()
  4. {
  5. char *env=getenv("MYENV");
  6. if(env)
  7. {
  8. printf("%s\n",env);
  9. }
  10. return 0;
  11. }

        當(dāng)運行該代碼時,出現(xiàn)如下結(jié)果:


       發(fā)現(xiàn)沒有結(jié)果,說明子進(jìn)程不能看到本地變量的值。

       通過export將MYENV設(shè)置為環(huán)境變量,在運行程序時,會輸出:hello world。說明,此時子進(jìn)程能夠看到環(huán)境變量的值。因為環(huán)境變量具有全局特性。

注意:本地變量沒有全局特性,只會被本shell看到,不會被子進(jìn)程看到。

          而環(huán)境變量具有全局特性,所以會被本shell及以下的所有子進(jìn)程看到,即被子進(jìn)程繼承下去。

 




    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    欧美二区视频在线观看| 日韩人妻中文字幕精品| 国产亚洲精品久久99| 亚洲伦理中文字幕在线观看| 我想看亚洲一级黄色录像| 日韩精品少妇人妻一区二区| 亚洲精品成人福利在线| 国产精品成人一区二区在线| 熟女体下毛荫荫黑森林自拍| 欧美日韩一级黄片免费观看 | 国产精品一区二区三区日韩av| 亚洲最新中文字幕在线视频 | 亚洲中文字幕在线视频频道| 日韩午夜福利高清在线观看| 91亚洲人人在字幕国产| 国产精品免费不卡视频| 国产精品一区日韩欧美| 国产免费一区二区不卡| 少妇人妻中出中文字幕| 亚洲香艳网久久五月婷婷| 欧美国产极品一区二区| 日韩毛片视频免费观看| 91日韩在线视频观看| 国产伦精品一区二区三区高清版| 欧美大粗爽一区二区三区| 激情中文字幕在线观看| 欧美日韩中黄片免费看| 亚洲欧美日韩精品永久| 国产不卡最新在线视频| 91欧美日韩精品在线| 女厕偷窥一区二区三区在线| 欧美色婷婷综合狠狠爱| 日本三区不卡高清更新二区| 国产又粗又黄又爽又硬的| 麻豆一区二区三区在线免费| 日韩精品一级片免费看 | 欧美人妻免费一区二区三区| 丰满少妇被猛烈撞击在线视频| 国产精品不卡一区二区三区四区| 久久热这里只有精品视频| 亚洲综合色在线视频香蕉视频|