日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > linux >内容正文

linux

linux wait 子孙进程,Linux-进程基础

發(fā)布時(shí)間:2025/3/15 linux 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux wait 子孙进程,Linux-进程基础 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

知識(shí)點(diǎn)比較雜,需要注意邏輯聯(lián)系

1、程序與進(jìn)程的區(qū)別

程序是靜態(tài)的,存放在磁盤(pán)上,是指令的集合。

進(jìn)程是程序運(yùn)行的實(shí)例,一個(gè)程序運(yùn)行產(chǎn)生一次產(chǎn)生一個(gè)進(jìn)程。

關(guān)于進(jìn)程,每個(gè)進(jìn)程都有自己的pid,都有自己的PCB,PCB(進(jìn)程控制塊)記錄了進(jìn)程使用到的資源。

進(jìn)程是資源分配的基本的單位,但是不是執(zhí)行的基本單位。

在Linux操作系統(tǒng)下,進(jìn)程之間的關(guān)系是父子關(guān)系或者兄弟關(guān)系,所有的用戶級(jí)的進(jìn)程形成了一棵樹(shù)。可以使用pstree查看。

pstree命令以樹(shù)狀圖顯示進(jìn)程間的關(guān)系(display a tree of processes)。ps命令可以顯示當(dāng)前正在運(yùn)行的那些進(jìn)程的信息,但是對(duì)于它們之間的關(guān)系卻顯示得不夠清晰。在Linux系統(tǒng)中,系統(tǒng)調(diào)用fork可以創(chuàng)建子進(jìn)程,通過(guò)子shell也可以創(chuàng)建子進(jìn)程,Linux系統(tǒng)中進(jìn)程之間的關(guān)系天生就是一棵樹(shù),樹(shù)的根就是進(jìn)程PID為1的init進(jìn)程。

常用參數(shù)

格式:pstree

以樹(shù)狀圖顯示進(jìn)程,只顯示進(jìn)程的名字,且相同進(jìn)程合并顯示。

格式:pstree -p

以樹(shù)狀圖顯示進(jìn)程,還顯示進(jìn)程PID。

格式:pstree

格式:pstree -p

以樹(shù)狀圖顯示進(jìn)程PID為的進(jìn)程以及子孫進(jìn)程,如果有-p參數(shù)則同時(shí)顯示每個(gè)進(jìn)程的PID。

格式:pstree -a

以樹(shù)狀圖顯示進(jìn)程,相同名稱的進(jìn)程不合并顯示,并且會(huì)顯示命令行參數(shù),如果有-p參數(shù)則同時(shí)顯示每個(gè)進(jìn)程的PID。

因?yàn)閜stree輸出的信息可能比較多,所以最好與more/less配合使用。

init是這棵樹(shù)的樹(shù)根,也是1好進(jìn)程。是用戶進(jìn)程的第一個(gè)進(jìn)程。環(huán)用戶自定義變量不能被子進(jìn)程繼承,環(huán)境變量可以被子進(jìn)程繼承。

2、創(chuàng)建新進(jìn)程

使用fork(2)創(chuàng)建新進(jìn)程

#include

pid_t fork(void);

功能:

參數(shù):

返回值:

失敗:在父進(jìn)程-1被返回,子進(jìn)程不被創(chuàng)建,errno被設(shè)置

成功:在父進(jìn)程里返回子進(jìn)程的PID,子進(jìn)程得到0的返回值

注意:這里不是一個(gè)函數(shù)返回兩個(gè)值,而是已經(jīng)存在了兩個(gè)進(jìn)程,是兩個(gè)fork的返回值

可以使用ps -aux命令查看進(jìn)程信息

使用pstree查看進(jìn)程樹(shù),Linux下的三個(gè)特殊進(jìn)程:idle進(jìn)程(PID=0),init進(jìn)程(PID=1),和kthreadd(PID=2)

idle進(jìn)程由系統(tǒng)自動(dòng)創(chuàng)建,運(yùn)行在內(nèi)核態(tài)

idle進(jìn)程其pid=0,其前身是系統(tǒng)創(chuàng)建的第一個(gè)進(jìn)程,也是唯一一個(gè)沒(méi)有通過(guò)fork或者kernel_thread產(chǎn)生的進(jìn)程。完成加載系統(tǒng)后,演變?yōu)檫M(jìn)程調(diào)度、交換。

kthreadd進(jìn)程由idle通過(guò)kernel_thread創(chuàng)建,并始終運(yùn)行在內(nèi)核空間,負(fù)責(zé)所有內(nèi)核進(jìn)程的調(diào)度和管理。

它的任務(wù)就是管理和調(diào)度其他內(nèi)核線程kernel_thread, 會(huì)循環(huán)執(zhí)行一個(gè)kthread的函數(shù),該函數(shù)的作用就是運(yùn)行kthread_create_list全局鏈表中維護(hù)的kthread, 當(dāng)我們調(diào)用kernel_thread創(chuàng)建的內(nèi)核線程會(huì)被加入到此鏈表中,因此所有的內(nèi)核線程都是直接或者間接的以kthreadd為父進(jìn)程 。

init進(jìn)程由idle通過(guò)kernel_thread創(chuàng)建,在內(nèi)核空間完成初始化后,加載init程序

在這里我們就主要講解下init進(jìn)程,init進(jìn)程由0進(jìn)程創(chuàng)建,完成系統(tǒng)的初始化,是系統(tǒng)中所有其他用戶進(jìn)程的祖先進(jìn)程

Linux中的所有進(jìn)程都是由init進(jìn)程創(chuàng)建并運(yùn)行的。首先Linux內(nèi)核啟動(dòng),然后在用戶空間中啟動(dòng)init進(jìn)程,再啟動(dòng)其他系統(tǒng)進(jìn)程。在系統(tǒng)啟動(dòng)完成后,init將變成為守護(hù)進(jìn)程監(jiān)視系統(tǒng)其他進(jìn)程。

所以說(shuō)init進(jìn)程是Linux系統(tǒng)操作中不可缺少的程序之一,如果內(nèi)核找不到init進(jìn)程就會(huì)試著運(yùn)行/bin/sh,如果運(yùn)行失敗,系統(tǒng)的啟動(dòng)也會(huì)失敗。

3、終止進(jìn)程

exit(3)和return的區(qū)別,return是函數(shù)的返回(可以使用echo $?查看最近一次返回結(jié)果),exit是進(jìn)程的結(jié)束

exit(3)

#include

void exit(int status)

功能:

終止一個(gè)正常進(jìn)程,status&0377的值返回給父進(jìn)程

參數(shù):

status:狀態(tài)碼

返回值:

不返回

進(jìn)程退出之前,需要調(diào)用一些處理函數(shù)進(jìn)行資源清理,這些函數(shù)需要進(jìn)行注冊(cè)

atexit(3)

atexit函數(shù)是一個(gè)特殊的函數(shù),它是在正常程序退出時(shí)調(diào)用的函數(shù),我們把他叫為登記函數(shù)

#include

int atexit(void (*func)(void))

功能

C 庫(kù)函數(shù)?int atexit(void (*func)(void))?當(dāng)程序正常終止時(shí),調(diào)用指定的函數(shù)?func。您可以在任何地方注冊(cè)你的終止函數(shù),但它會(huì)在程序終止的時(shí)候被調(diào)用。

參數(shù)

func?- 在程序終止時(shí)被調(diào)用的函數(shù)。

返回值

如果函數(shù)成功注冊(cè),則該函數(shù)返回零,否則返回一個(gè)非零值。

實(shí)例

下面的實(shí)例演示了 atexit() 函數(shù)的用法。

#include

#include

void functionA ()

{

printf("這是函數(shù)A\n");

}

int main ()

{

/* 注冊(cè)終止函數(shù) */

atexit(functionA );

printf("啟動(dòng)主程序...\n");

printf("退出主程序...\n");

return(0);

}

在一個(gè)程序中最多可以用atexit()注冊(cè)32個(gè)處理函數(shù),這些處理函數(shù)的調(diào)用順序與其注冊(cè)的順序相反,也即最先注冊(cè)的最后調(diào)用,最后注冊(cè)的最先調(diào)用。

執(zhí)行結(jié)果:

執(zhí)行

before exit()!

on_exit(3)

相關(guān)函數(shù) _exit,atexit,exit

函數(shù)原型

#include

int on_exit(void (* function)(int,void*),void *arg);

返回值 如果執(zhí)行成功則返回0,否則返回-1,失敗原因存于errno中。

函數(shù)說(shuō)明 on_exit()用來(lái)設(shè)置一個(gè)程序正常結(jié)束前調(diào)用的函數(shù)。當(dāng)程序通過(guò)調(diào)用exit()

或從main中返回時(shí),參數(shù)function所指定的函數(shù)會(huì)先被調(diào)用,然后才真正由exit()結(jié)束

程序。參數(shù)arg指針會(huì)傳給參數(shù)function函數(shù),詳細(xì)情況請(qǐng)見(jiàn)范例。

#include

void my_exit(int status,void *arg)

{

printf(“before exit()!\n”);

printf(“exit (%d)\n”,status);

printf(“arg = %s\n”,(char*)arg);

}

main()

{

char * str=”test”;

on_exit(my_exit,(void *)str);

exit(1234);

}

執(zhí)行結(jié)果:

執(zhí)行 before exit()!

exit (1234)

arg = test

4、子進(jìn)程回收

進(jìn)程結(jié)束后,父進(jìn)程會(huì)回收子進(jìn)程資源,wait(2)、waitpid(2)系統(tǒng)調(diào)用可以回收子進(jìn)程資源。

如果父進(jìn)程先于子進(jìn)程結(jié)束,那么子進(jìn)程的父進(jìn)程將變?yōu)閕nit進(jìn)程。

wait(2)

#include

#include

功能:

這些系統(tǒng)調(diào)用用于獲取子進(jìn)程狀態(tài)變化和狀態(tài)信息。狀態(tài)的變化可以認(rèn)為是:(1)子進(jìn)程終止;(2)子進(jìn)程被信號(hào)中止;子進(jìn)程被信號(hào)喚醒。

參數(shù):

參數(shù)status如果不是一個(gè)空指針,則終止進(jìn)程的終止?fàn)顟B(tài)就存放在statloc所指向的單元。

參數(shù)status如果是一個(gè)空指針,則表示父進(jìn)程不關(guān)心子進(jìn)程的終止?fàn)顟B(tài)

子進(jìn)程的的退出狀態(tài)存放在這塊地址中,可以使用宏檢測(cè)退出原因。

WIFEXITED(status):如果子進(jìn)程正常結(jié)束則為非0 值.

WEXITSTATUS(status):取得子進(jìn)程exit()返回的結(jié)束代碼, 一般會(huì)先用WIFEXITED 來(lái)判斷是否正常結(jié)束才能使用此宏.

WIFSIGNALED(status):如果子進(jìn)程是因?yàn)樾盘?hào)而結(jié)束則此宏值為真

WTERMSIG(status):取得子進(jìn)程因信號(hào)而中止的信號(hào)代碼, 一般會(huì)先用WIFSIGNALED 來(lái)判斷后才使用此宏.

WIFSTOPPED(status):如果子進(jìn)程處于暫停執(zhí)行情況則此宏值為真. 一般只有使用WUNTRACED時(shí)才會(huì)有此情況.

WSTOPSIG(status):取得引發(fā)子進(jìn)程暫停的信號(hào)代碼, 一般會(huì)先用WIFSTOPPED 來(lái)判斷后才使用此宏.

kill命令用于刪除執(zhí)行中的程序或工作。

kill可將指定的信息送至程序。預(yù)設(shè)的信息為SIGTERM(15),可將指定程序終止。若仍無(wú)法終止該程序,可使用SIGKILL(9)信息嘗試強(qiáng)制刪除程序。程序或工作的編號(hào)可利用ps指令或jobs指令查看。

返回值:

是一個(gè)阻塞函數(shù),如果沒(méi)有可以回收的子進(jìn)程,則為阻塞狀態(tài)

如果無(wú)子進(jìn)程,則返回-1

如果回收成功,則返回子進(jìn)程的pid

1 #include

2 #include

3 #include

4 #include

5 #include

6 #include

7 #include

8 /***********************************************************

9

10

11

12 ***********************************************************/

13 void waitprocess();

14

15

16 int main(int argc, char * argv[])

17 {

18 waitprocess();

19

20 }

21

22 void waitprocess()

23 {

24

25 int count = 0;

26

27 pid_t pid = fork();

28 int status = -1;

29

30 if(pid<0)

31 {

32 printf("fork error for %m\n",errno );

33 }else if(pid>0)

34 {

35 printf("this is parent ,pid = %d\n",getpid() );

36 wait(&status);//父進(jìn)程執(zhí)行到此,馬上阻塞自己,直到有子進(jìn)程結(jié)束。當(dāng)發(fā)現(xiàn)有子進(jìn)程結(jié)束時(shí),就會(huì)回收它的資源。

37

38 }else

39 {

40 printf("this is child , pid = %d , ppid = %d\n",getpid(),getppid() );

41 int i;

42

43 for (i = 0; i < 10; i++) {

44 count++;

45 sleep(1);

46

47 printf("count = %d\n", count) ;

48

49 }

50

51 exit(5);

52

53 }

54 printf("child exit status is %d\n", WEXITSTATUS(status));//status是按位存儲(chǔ)的狀態(tài)信息,需要調(diào)用相應(yīng)的宏來(lái)還原一下

55

56 printf("end of program from pid = %d\n",getpid() );

57

58

59 }

執(zhí)行結(jié)果

通常利用如下代碼來(lái)判斷進(jìn)程的終止原因,和終止信號(hào)來(lái)源。

wait(&status);

...

//檢測(cè)進(jìn)程是否被信號(hào)終止

if(WIFSIGNALED(status)){

//輸出終止子進(jìn)程的信號(hào)編號(hào)

printf("signum:%d\n",WTERMSIG(s));

}

在命令行使用kill命令終止相關(guān)進(jìn)程,上述代碼即可輸出終止進(jìn)程的相關(guān)信息。

子進(jìn)程終止,但是父進(jìn)程并未回收子進(jìn)程的相關(guān)資源,這時(shí)候子進(jìn)程處于僵尸狀態(tài),成為僵尸進(jìn)程

waitpid(2)

pid_t waitpid(pid_t pid, int *status, int options);

功能:

等待進(jìn)程狀態(tài)改變。waitpid可以等待任意子進(jìn)程或者一組子進(jìn)程的終止;可以設(shè)置成阻塞狀態(tài),也可以設(shè)置成非阻塞狀態(tài)。

參數(shù):

pid:

pid>0只等待進(jìn)程ID等于pid的子進(jìn)程,不管其它已經(jīng)有多少子進(jìn)程運(yùn)行結(jié)束退出了,只要指定的子進(jìn)程還沒(méi)有結(jié)束,waitpid就會(huì)一直等下去。

pid=-1等待任何一個(gè)子進(jìn)程退出,沒(méi)有任何限制,此時(shí)waitpid和wait的作用一模一樣。

pid=0時(shí)等待同一個(gè)進(jìn)程組中的任何子進(jìn)程,如果子進(jìn)程已經(jīng)加入了別的進(jìn)程組,waitpid不會(huì)對(duì)它做任何理睬。

pid

status:

參數(shù)status如果不是一個(gè)空指針,則終止進(jìn)程的終止?fàn)顟B(tài)就存放在status所指向的單元。

參數(shù)status如果是一個(gè)空指針,則表示父進(jìn)程不關(guān)心子進(jìn)程的終止?fàn)顟B(tài)

option:

WNOHANG若由pid指定的子進(jìn)程未發(fā)生狀態(tài)改變(沒(méi)有結(jié)束),則waitpid()不阻塞,立即返回0

WUNTRACED返回終止子進(jìn)程信息和因信號(hào)停止的子進(jìn)程信息

WCONTINUED返回收到SIGCONT信號(hào)而恢復(fù)執(zhí)行的已停止子進(jìn)程狀態(tài)信息

0:阻塞

返回值:

成功成功結(jié)束運(yùn)行的子進(jìn)程的進(jìn)程號(hào)

失敗返回-1

WNOHANG被設(shè)置時(shí) 沒(méi)有子進(jìn)程退出返回0

wait(&status)等價(jià)于waitpid(-1,&status,0)

疑問(wèn):如果被設(shè)置為非阻塞,父進(jìn)程先于子進(jìn)程結(jié)束,子進(jìn)程變?yōu)楣逻M(jìn)程?由init調(diào)用wait回收?

筆記參考: https://www.cnblogs.com/king-77024128/articles/2684317.html

https://www.cnblogs.com/leijiangtao/p/4483009.html

標(biāo)簽:status,基礎(chǔ),void,pid,exit,Linux,進(jìn)程,include

來(lái)源: https://www.cnblogs.com/ptfe/p/10972475.html

總結(jié)

以上是生活随笔為你收集整理的linux wait 子孙进程,Linux-进程基础的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。