最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Linux進(jìn)程等待和進(jìn)程替換詳解

 更新時(shí)間:2024年12月10日 11:40:59   作者:無(wú)空念  
本文介紹了Linux系統(tǒng)中進(jìn)程等待的重要性,包括防止內(nèi)存泄露和獲取子進(jìn)程狀態(tài),詳細(xì)講解了wait()和waitpid()函數(shù)的使用,接著,探討了進(jìn)程替換的概念,通過(guò)exec系列函數(shù)實(shí)現(xiàn)程序替換,講解了不同函數(shù)的用法和參數(shù)含義,需要的朋友可以參考下

進(jìn)程等待

前面我們了解了如果父進(jìn)程沒(méi)有回收子進(jìn)程, 那么當(dāng)子進(jìn)程接收后, 就會(huì)一直處于僵尸狀態(tài), 導(dǎo)致內(nèi)存泄漏, 那么我們?nèi)绾巫尭高M(jìn)程來(lái)回收子進(jìn)程的資源.

waitpid

我們可以通過(guò) Linux 提供的系統(tǒng)調(diào)用函數(shù) wait 系列函數(shù)來(lái)等待子進(jìn)程死亡, 并回收資源.

wait函數(shù)用于等待任何一個(gè)子進(jìn)程結(jié)束, 并回收其資源. 

  • status:指向整數(shù)的指針, 用于存儲(chǔ)子進(jìn)程的退出狀態(tài). 如果不需要這個(gè)信息, 可以傳遞NULL.
  • 成功時(shí)返回被等待的子進(jìn)程的PID, 失敗時(shí)返回 -1, 并設(shè)置 errno.

waitpid函數(shù)允許父進(jìn)程等待特定的子進(jìn)程結(jié)束

  • pid:子進(jìn)程的PID. 如果為 -1, 則等待任何一個(gè)子進(jìn)程。
  • status:同wait函數(shù).
  • options:等待選項(xiàng), 常用的有 WNOHANG (非阻塞等待). 
  • 成功時(shí)返回被等待的子進(jìn)程的PID. 失敗時(shí)返回-1,并設(shè)置errno。

一般來(lái)說(shuō), 用 waitpid 多一點(diǎn), 因?yàn)?waitpid 提供的更為細(xì)致的操作.

int main()    
{    
    pid_t id = fork();    
    if(id<0)    
    {    
        perror("fork");    
        exit(1);    
    }    
    if(id==0)//子進(jìn)程代碼    
    {    
        int count = 5;    
        while(count)    
        {    
            printf("[%d]我是子進(jìn)程,我的pid是: %d\n",count,getpid());    
            sleep(1);    
            count--;    
        }    
        exit(0);//子進(jìn)程執(zhí)行完代碼后退出, exit 會(huì)直接終止本進(jìn)程                                                                        
    }                                                                                                    
    //父進(jìn)程代碼                                                                                         
    waitpid(id,NULL,0);                                                                                  
    printf("等待子進(jìn)程成功!\n");                                                                         
    return 0;     
}

可以觀察到, 在等待子進(jìn)程結(jié)束之前, 父進(jìn)程卡在了 waitpid(), 直到子進(jìn)程都被等待成功, 父進(jìn)程才會(huì)繼續(xù)向后執(zhí)行.

status 參數(shù)

在 wait 和 waitpid 函數(shù)中都存在一個(gè) status 的參數(shù).
在 status 中存儲(chǔ)著子進(jìn)程的退出碼和退出信號(hào).
如果父進(jìn)程想要了解子進(jìn)程的退出信息, 可以通過(guò) status 來(lái)了解.

status 是一個(gè) int 類型的變量, 一共有 32 個(gè)bit, 我們主要看它的低 16 位bit.

那么如何獲取退出狀態(tài) (退出碼) 和 信號(hào)

退出狀態(tài) (退出碼):
(status >> 8) & 0xFF
退出信號(hào):
status & 0x7F
int main()    
{    
    pid_t id = fork();    
    if(id<0)    
    {    
        perror("fork");    
        exit(1);    
    }    
    
    if(id==0)//子進(jìn)程代碼    
    {    
        int count = 5;    
        while(count)    
        {    
            printf("[%d]我是子進(jìn)程,我的pid是: %d\n",count,getpid());    
            sleep(1);    
            count--;    
        }    
        exit(55);//子進(jìn)程執(zhí)行完代碼后退出                                                                                                                               
    }    
    //父進(jìn)程代碼    
    int status = 0;    
    waitpid(id,&status,0);    
    printf("等待子進(jìn)程成功!\n");    
    printf("進(jìn)程退出碼: %d,進(jìn)程退出信號(hào): %d\n",(status >> 8) & 0xFF,status & 0x7F);    
    return 0;    
}  

當(dāng)子進(jìn)程在運(yùn)行時(shí), 使用 kill -9 617714命令, 來(lái)終止子進(jìn)程, 那么也就能觀察到, 退出信號(hào)為 9.

option

在前面的參數(shù)解釋中說(shuō)到, 這是一個(gè)等待選項(xiàng).
父進(jìn)程可以選擇一直阻塞下去, 直到等到子進(jìn)程的死亡,
或者當(dāng)子進(jìn)程還沒(méi)死亡時(shí), 父進(jìn)程去執(zhí)行其他的代碼. 等一會(huì)再來(lái)查看子進(jìn)程是否死亡.

waitpid(pid,&status,WNOHANG); // 非阻塞等待
waitpid(pid,&status,0); // 阻塞等待
 
int main()
{
    pid_t id = fork();
    if(id<0)
    {
        perror("fork");
        exit(1);
    }
 
    if(id==0)//子進(jìn)程代碼
    {
        int count = 5;
        while(count)
        {
            printf("[%d]我是子進(jìn)程,我的pid是: %d\n",count,getpid());
            sleep(1);
            count--;
        }
        exit(55);//子進(jìn)程執(zhí)行完代碼后退出
    }
    //父進(jìn)程代碼
    while(1)//循環(huán)訪問(wèn)子進(jìn)程退出情況
    {
        int wait = waitpid(id,NULL,WNOHANG);
        if(wait>0)//子進(jìn)程退出成功
        {
            printf("子進(jìn)程退出成功,子進(jìn)程pid: %d\n",wait);
            break;
        }
        else if(wait==0)//子進(jìn)程還沒(méi)退出,父進(jìn)程干自己的事情
        {
            //此處簡(jiǎn)單模擬父進(jìn)程干的事情
            printf("我是父進(jìn)程\n");
        }
        else //等待子進(jìn)程退出失敗
        {
            perror("waitpid");
            exit(1);
        }
        sleep(1);
    }
    return 0;
}

執(zhí)行上面的代碼就能觀察到, 在子進(jìn)程結(jié)束前, 父進(jìn)程還在向頻幕上打印文字.

進(jìn)程替換

創(chuàng)建子進(jìn)程是為了完成一些工作, 但是子進(jìn)程的代碼和父進(jìn)程是一樣的,
有可能子進(jìn)程并不需要執(zhí)行父進(jìn)程的代碼, 而是執(zhí)行一些其他代碼.
這種場(chǎng)景下, 就可以使用進(jìn)程替換.

我們?yōu)槭裁床恢苯訉⒆舆M(jìn)程要執(zhí)行的代碼寫(xiě)在父進(jìn)程中呢, 還要去使用進(jìn)程替換?

1. 如果所有的代碼都放在父進(jìn)程中, 那么父進(jìn)程的代碼會(huì)有多么的龐大,

這會(huì)提高代碼編寫(xiě)和維護(hù)的成本. 

2. 進(jìn)程所執(zhí)行的一定是我們的C/C++程序嗎? 進(jìn)程也可以執(zhí)行其他的非 C/C++ 程序,

那對(duì)于那些非 C/C++ 程序 (java程序), 我們無(wú)法將他們和我們所寫(xiě)的 C/C++ 代碼整合在一起, java 和 C/C++ 的運(yùn)行環(huán)境都不同.

exec 系列函數(shù)

如果想要?jiǎng)?chuàng)建出來(lái)的子進(jìn)程執(zhí)行全新的程序, 可以使用 exec 系列函數(shù)進(jìn)行程序替換.

一共有6個(gè)函數(shù), 其中主要分為兩類
1. execl 系列
2. execv 系列

execl

int main()    
{    
    printf("進(jìn)行程序替換了\n");    
    int n = execl("/usr/bin/ls","ls","-a","-l",NULL);                                                                                                                   
    if(n==-1)    
    {    
        perror("execl");    
    }    
    printf("程序替換完畢!\n");    
    return 0;    
}    

execl參數(shù): 第一個(gè)是要執(zhí)行程序的路徑 (/usr/bin/ls),
第二個(gè)參數(shù)是要執(zhí)行的程序的名稱 (ls),

后面的參數(shù)到 NULL 之前, 都是要替換的程序參數(shù) (-a, -l, 都是 ls 程序的參數(shù)).

execl 中 l, 表示如何將參數(shù)傳遞要替換的程序. l 表示通過(guò)一個(gè)列表的方式,
即向上面的 "-l", "-a"..., 一個(gè)列表的形式.

execlp 和 execle 兩個(gè)函數(shù)則分別多了 p 和 e.

p 則代表要執(zhí)行的程序可以從環(huán)境變量 PATH 中找到, 所以不用寫(xiě)執(zhí)行程序的路徑.

e 則表示, 可以傳入用戶自己定義的環(huán)境變量 (_env[]) 給程序使用.

int main()    
{    
    printf("我要進(jìn)行程序替換了...\n");    
    int n = execlp("ls","-l",NULL);                                                                                                                                     
    if(n==-1)    
    {    
        perror("execl");    
    }    
    printf("程序替換完畢!\n");    
    return 0;    
} 
 
int main()    
{    
    const char* _env[]={"MY_ENV=666",NULL};    
    printf("我要進(jìn)行程序替換了...\n");    
    int n = execle("/usr/bin/ls","ls","-l",NULL,_env);//自己定義一個(gè)環(huán)境變量MY_ENV=666傳遞給要去執(zhí)行的程序                                                              
    if(n==-1)    
    {    
        perror("execl");    
    }    
    printf("程序替換完畢!\n");    
    return 0;    
}  

execv 

上面的 execl 中的 l, 代表傳參使用列表的形式.
那么 v 很容易就想到了是vector.
所以 execv 函數(shù)在給替換的程序傳參時(shí), 是通過(guò)一個(gè) vector 來(lái)傳參的.

int main()    
  {    
	  char* const set[]={"ls","-a","-l",NULL};  
      printf("我要進(jìn)行程序替換了...\n");    
      int n = execv("/usr/bin/ls",set);                                                                             
      if(n==-1)    
      {    
          perror("execl");    
      }    
      printf("程序替換完畢!\n");    
      return 0;    
  } 

那么剩下的 execvp 和 execvpe 和之前的 execl 系列中的一樣.
p 代表在環(huán)境變量 PATH 中查找, e 可以傳入自己定義的環(huán)境變量.

  • l (list): 傳參的方式為使用列表來(lái)傳遞
  • v (vector): 使用數(shù)組來(lái)傳遞參數(shù)
  • p (path): 會(huì)在環(huán)境變量 PATH 中查找程序
  • e (env): 可以傳遞自己定義的環(huán)境變量

以上就是Linux進(jìn)程等待和進(jìn)程替換詳解的詳細(xì)內(nèi)容,更多關(guān)于Linux進(jìn)程等待和替換的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Linux如何配置本地yum源(光盤(pán)鏡像掛載)

    Linux如何配置本地yum源(光盤(pán)鏡像掛載)

    這篇文章主要介紹了Linux如何配置本地yum源(光盤(pán)鏡像掛載),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-05-05
  • Linux系統(tǒng)新增硬盤(pán)掛載全流程指南

    Linux系統(tǒng)新增硬盤(pán)掛載全流程指南

    這篇文章主要為大家詳細(xì)介紹了Linux系統(tǒng)新增硬盤(pán)掛載全流程指南,包括分區(qū)、格式化和掛載操作,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解下
    2026-02-02
  • 最新Linux下安裝tomcat8圖解過(guò)程

    最新Linux下安裝tomcat8圖解過(guò)程

    這篇文章主要介紹了最新的Linux下安裝tomcat8圖解過(guò)程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-08-08
  • Linux TC流控實(shí)現(xiàn)機(jī)制過(guò)程

    Linux TC流控實(shí)現(xiàn)機(jī)制過(guò)程

    Linux TC通過(guò)模塊化分層設(shè)計(jì)(Qdisc、Class、Filter、Policer、Action)實(shí)現(xiàn)靈活流量控制,支持從簡(jiǎn)單FIFO到復(fù)雜分層調(diào)度,其優(yōu)勢(shì)在于可擴(kuò)展性,但存在配置復(fù)雜、單核瓶頸及新技術(shù)整合等挑戰(zhàn)
    2025-09-09
  • Linux線程優(yōu)先級(jí)設(shè)置方式

    Linux線程優(yōu)先級(jí)設(shè)置方式

    Linux線程分普通(系統(tǒng)動(dòng)態(tài)調(diào)度)和實(shí)時(shí)(用戶顯式設(shè)置)兩類,實(shí)時(shí)線程采用SCHED_FIFO或SCHED_RR策略,調(diào)整優(yōu)先級(jí)可通過(guò)nice/renice命令或chrt工具、C代碼接口,需注意權(quán)限及對(duì)系統(tǒng)資源的影響
    2025-07-07
  • 2016年如何選擇Linux發(fā)行版

    2016年如何選擇Linux發(fā)行版

    這篇文章主要介紹了2016年選擇Linux發(fā)行版的標(biāo)準(zhǔn)和原則,挑選幾個(gè)將在2016 年里大放光彩的最佳發(fā)行版給大家介紹一下,感興趣的小伙伴們可以參考一下
    2016-02-02
  • Linux調(diào)整系統(tǒng)最大文件打開(kāi)數(shù)限制的實(shí)戰(zhàn)指南

    Linux調(diào)整系統(tǒng)最大文件打開(kāi)數(shù)限制的實(shí)戰(zhàn)指南

    在現(xiàn)代高并發(fā)服務(wù)架構(gòu)中,Linux系統(tǒng)的文件描述符(File Descriptor)管理能力直接決定了應(yīng)用的穩(wěn)定性和吞吐量,本文將帶你深入理解Linux文件描述符機(jī)制,手把手教你如何正確調(diào)整系統(tǒng)最大文件打開(kāi)數(shù)限制,并結(jié)合真實(shí)Java代碼示例,讓你的應(yīng)用穩(wěn)如泰山
    2026-04-04
  • Linux添加靜態(tài)路由兩種實(shí)現(xiàn)方法解析

    Linux添加靜態(tài)路由兩種實(shí)現(xiàn)方法解析

    這篇文章主要介紹了Linux添加靜態(tài)路由兩種實(shí)現(xiàn)方法解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-08-08
  • 限制 Apache日志文件大小的方法

    限制 Apache日志文件大小的方法

    access.log,件在 WEB 服務(wù)器運(yùn)行一段時(shí)間之后會(huì)達(dá)到幾十兆甚至上百兆,如果Apache運(yùn)行有錯(cuò)誤,error.log也會(huì)增大到幾十兆,我們知道系統(tǒng)讀寫(xiě)一個(gè)大的文本文件是非常耗內(nèi)存的,因此限定日志文件大小十分必要。
    2009-04-04
  • Linux文件操作實(shí)戰(zhàn)之壓縮,遠(yuǎn)程傳輸和終端計(jì)算速成

    Linux文件操作實(shí)戰(zhàn)之壓縮,遠(yuǎn)程傳輸和終端計(jì)算速成

    Linux終端操作是運(yùn)維、開(kāi)發(fā)必備基礎(chǔ),日常工作與面試均高頻涉及,本文以實(shí)操為核心,講解tar、scp、bc指令用法,補(bǔ)充面試題與熱鍵,結(jié)合故事拆解Shell與內(nèi)核交互邏輯,感興趣的小伙伴可以了解下
    2026-01-01

最新評(píng)論

方山县| 新乐市| 阳泉市| 兴宁市| 凌海市| 河西区| 永吉县| 孟州市| 临夏县| 汉沽区| 太保市| 滦平县| 和顺县| 遵化市| 景洪市| 合阳县| 和林格尔县| 怀安县| 静海县| 宝兴县| 沙坪坝区| 晋宁县| 康定县| 万宁市| 汝南县| 景德镇市| 石城县| 吉林省| 乃东县| 中江县| 福安市| 海城市| 华阴市| 建平县| 噶尔县| 大安市| 西峡县| 任丘市| 恩施市| 买车| 枣阳市|