首页
/
每日頭條
/
生活
/
linux 進程用法
linux 進程用法
更新时间:2024-12-21 23:38:01

程序:死的,隻占用磁盤空間

進程:活的,運行起來的程序,占用系統資源(CPU,内存等)

單道程序設計:所有進程一個一個執行,A執行完了才能執行B

多道程序設計:進程相互穿插執行,并行執行

linux 進程用法(Linux進程基礎知識)1

虛拟内存與物理内存映射

MMU:内存管理單元,完成虛拟地址到物理地址映射

linux 進程用法(Linux進程基礎知識)2

linux 進程用法(Linux進程基礎知識)3

不同進程用戶空間内存映射到不同物理内存區域,而内核空間内存映射到同一塊物理内存區域,因為操作系統就一個,在這個物理内存區域包括了不同進程的PCB(結構體)。

在用戶空間分配一個數組(虛拟内存空間中數組地址是連續的),如果數組長度很長,在映射到物理内存上時,其在物理内存上的地址其實是不連續的,但不影響,反正我們平常取得地址都是虛拟内存地址。

MMU還可以修改程序訪問内存級别,普通程序訪問級别為0,操作系統為3,執行系統調用時,MMU修改了程序訪問内存的訪問級别,這個速度比較慢。

PCB進程控制塊

linux 進程用法(Linux進程基礎知識)4

進程狀态

linux 進程用法(Linux進程基礎知識)5

進程挂起的時候會釋放CPU,例如sleep函數會挂起進程。

常用的幾個環境變量

PATH:可執行文件搜索路徑

SHELL:當前使用shell類型

TERM:當前終端類型,在圖形界面終端下它的值通常是xterm,終端類型決定了一些程序的輸出顯示方式,比如圖形界面終端可以顯示漢字,而字符終端一般不行。

LANG:語言和字符編碼方式

HOME:家目錄路徑

linux 進程用法(Linux進程基礎知識)6

fork()

pid_t fork(void); pid_t getpid(void);//獲取進程号 pid_t getppid(void);//獲取父進程号 uid_t getuid(void);//returns the real user ID of the calling process. uid_t geteuid(void);//returns the effective user ID of the calling process. gid_t getgid(void);//returns the real group ID of the calling process. gid_t getegid(void);//returns the effective group ID of the calling process.

成功:父進程返回子進程進程号pid,子進程返回0;

失敗:父進程返回-1,設置errno,不創建子進程;

linux 進程用法(Linux進程基礎知識)7

子進程把父進程的數據複制一份

fork一般判斷方式:

pid_t pid; pid = fork(); if(pid==-1) { perror("fork error"); } else if(!pid) { //... } else { //... }

循環創建多個子進程

#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <errno.h> #include <string.h> /* int main(int argc, char const *argv[]) { for(int i=0;i<5;i ) { if(fork()==0) { printf("--I am the %d child process.\n", i 1); break; } } return 0; } */ int main(int argc, char const *argv[]) { int i = 0; for(i=0;i<5;i ) { if(fork()==0) { //printf("--I am the %d child process.\n", i 1); break; } sleep(1);//讓後面打打印依序打印 } if(i==5) { printf("--I am the parent process.\n"); } else { printf("--I am the %d child process.\n", i 1); } return 0; }

linux 進程用法(Linux進程基礎知識)8

父子進程共享哪些内容?

linux 進程用法(Linux進程基礎知識)9

子進程把父進程的數據複制一份,父子進程間遵循讀時共享寫時複制原則。

fork之後先執行父進程還是子進程是不确定的,取決于内核的調度算法。

gdb調試

使用gdb調試時,gdb隻能跟蹤一個進程,可以在fork函數調用之前,通過指令設置gdb調試跟蹤父進程還是子進程,默認跟蹤父進程。

set follow-fork-mode child:設置gdb在fork之後跟蹤子進程

se follow-fork-mode parent:設置gdb在fork之後跟蹤父進程

注意:一定要在fork函數之前設置才有效。

linux 進程用法(Linux進程基礎知識)10

不管跟蹤父進程還是子進程,程序運行結果都是一樣的。隻是單步調試的時候,走的語句不一樣。

exec函數族

fork創建子進程後執行的是和父進程相同的程序,子進程往往要調用一種exec函數去執行另一個程序,當進程調用一種exec函數時,該進程的用戶空間代碼和數據完全被新程序替換,從新程序開始處開始執行,調用exec并不創建新進程,exec前後進程的id不變

将當前進程的.text,.data替換成要加載的程序的.text,.data。

int execl(const char *path, const char *arg, .../* (char *) NULL */); int execlp(const char *file, const char *arg, .../* (char *) NULL */); int execle(const char *path, const char *arg, .../*, (char *) NULL, char * const envp[] */); int execv(const char *path, char *const argv[]); int execvp(const char *file, char *const argv[]); int execvpe(const char *file, char *const argv[],char *const envp[]); int execve(const char *filename, char *const argv[], char *const envp[]);

l:表示參數以列表方式提供

v:表示參數以數組方式提供

p:表示在環境變量path路徑下查找可執行文件。

e:使用環境變量數組,不實用進程原有的環境變量,設置新加載程序的環境變量

事實上,隻有execve是真正的系統調用,其他的幾個函數最終都是調用它,execve在man第二節,其他在第三節。

linux 進程用法(Linux進程基礎知識)11

參數:

path:完整可執行程序路徑 文件名

file:在環境變量path路徑下查找可執行程序文件,隻指定文件名即可

arg:傳遞給新進程的參數,必須以NULL結尾,其中arg[0]一般存程序名,

返回值:通常情況下,exec函數不會返回,調用成功,跳轉到新的程序入口處;錯誤時,返回-1,并設置errno。

execlp:通常用來調用系統程序,如ls、data、cp、cat等。其實,execlp也會在當前目錄下查找可執行程序。

#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <errno.h> #include <string.h> int main(int argc, char const *argv[]) { pid_t pid; pid = fork(); if(pid==-1) { perror("fork error"); exit(1); } else if(!pid) { execlp("ls","ls","-l","-a","-h",NULL); //execlp("ls","ls","-alh",NULL);//這裡這樣寫效果一樣 perror("execlp error");//execlp出錯才返回執行 exit(1); } else { sleep(1); printf("--parent process---\n"); } return 0; }

linux 進程用法(Linux進程基礎知識)12

execl:一般用于執行自己的程序

#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <errno.h> #include <string.h> int main(int argc, char const *argv[]) { pid_t pid; pid = fork(); if(pid==-1) { perror("fork error"); exit(1); } else if(!pid) { execl("./printf_hello","./printf_hello",NULL);//main函數命令行參數 //execlp("./printf_hello","./printf_hello",NULL);//這裡也可以execlp,它也會查找當前路徑 perror("execl error");//execl出錯才返回執行 exit(1); } else { sleep(1); printf("--parent process---\n"); } return 0; } #include <stdio.h> int main(int argc, char const *argv[]) { printf("hello world\n"); return 0; }

linux 進程用法(Linux進程基礎知識)13

execvp:

char *arg[] = {"ls","-a","-l","-h",NULL};

execvp("ls",arg);

孤兒進程:

父進程先于子進程結束,子進程變為孤兒進程,systemd進程會成為孤兒進程的父進程

ps ajx

#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <errno.h> #include <string.h> int main(int argc, char const *argv[]) { pid_t pid; pid = fork(); if(pid==-1) { perror("fork error"); exit(1); } else if(!pid) { while(1) { printf("--child process--pid=%d--ppid=%d--\n",getpid(),getppid()); sleep(1); } } else { printf("--parent processs--pid=%d--\n",getpid()); sleep(9); } return 0; }

linux 進程用法(Linux進程基礎知識)14

linux 進程用法(Linux進程基礎知識)15

linux 進程用法(Linux進程基礎知識)16

kill -9 殺掉子進程

僵屍進程:

進程終止,父進程尚未回收。子進程殘留資源(PCB)存放于内核中,變成僵屍(Zombie)進程。

僵屍進程是不能用kill命令清除掉的,因為kill命令是用來終止進程的,而僵屍進程已經終止,可以kill掉僵屍進程父進程,來讓系統進行回收。

#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <errno.h> #include <string.h> int main(int argc, char const *argv[]) { pid_t pid; pid = fork(); if(pid==-1) { perror("fork error"); exit(1); } else if(!pid) { printf("--child process--pid=%d--ppid=%d--\n",getpid(),getppid()); sleep(9); } else { while(1) { printf("--parent processs--pid=%d--\n",getpid()); sleep(1); } } return 0; }

linux 進程用法(Linux進程基礎知識)17

子進程結束前:

linux 進程用法(Linux進程基礎知識)18

子進程結束後:

linux 進程用法(Linux進程基礎知識)19

defunct:死者

wait函數

阻塞回收任意一個子進程

一個進程在終止時會關閉掉所有的文件描述符,釋放在用戶空間分配的内存,但它的PCB還保留着,内核在其中保存了一些信息;如果是正常終止,則保存着退出狀态,如果是異常終止,則保存着導緻該進程終止的信号是哪個。這個進程的父進程可以調用wait或者waitpid獲取這些信息,然後徹底清除掉這個進程。我們知道一個進程的退出狀态可以在shell中用特殊變量$?查看,是因為shell是它的父進程,當它終止時,shell調用wait或者waitpid得到它的退出狀态,同時徹底清除掉這個進程。

父進程調用wait回收子進程終止信息,wait函數包括三個功能:

1. 阻塞等待子進程退出

2. 回收子進程殘留資源

3. 獲取子進程結束狀态(退出原因,正常退出->退出值,異常終止->終止信号)

pid_t wait(int *stat_loc);

stat_loc:傳出參數,保存子進程的退出狀态

成功:返回回收的子進程的pid,

失敗:返回-1

判斷進程退出狀态的幾個宏:

WIFEXITED(stat_val)//判斷進程是否正常終止 WEXITSTATUS(stat_val)//取退出值 WIFSIGNALED(stat_val)//判斷進行是否被信号終止 WTERMSIG(stat_val)//取信号值 WIFSTOPPED(stat_val) WSTOPSIG(stat_val) WIFCONTINUED(stat_val)

#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <sys/wait.h> int main(int argc, char const *argv[]) { pid_t pid; pid_t wpid; int status; pid = fork(); if(pid==-1) { perror("fork error"); exit(1); } else if(!pid) { printf("--child process--pid=%d--ppid=%d--\n",getpid(),getppid()); sleep(10); return 100;//查看退出狀态是否為100 } else { int wpid = wait(&status); if(wpid==-1) { perror("wait error"); exit(1); } printf("--wpid=%d----\n",wpid); if(WIFEXITED(status))//為真,說明子進程正常終止 { printf("--child process exit with %d\n--",WEXITSTATUS(status)); } if(WIFSIGNALED(status))//為真,說明子進程是被信号終止 { printf("--child process killed with %d\n--",WTERMSIG(status)); } } return 0; }

正常退出:

linux 進程用法(Linux進程基礎知識)20

使用信号殺死:

linux 進程用法(Linux進程基礎知識)21

linux 進程用法(Linux進程基礎知識)22

當父進程不關心子進程的退出狀态時,wpid=wait(NULL);

waitpid函數

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

返回值:

>0:表示成功回收的子進程pid

0:函數調用時,options設置為WNOHANG,并且,沒有子進程結束。WNOHANG--wait no hang。hang:挂起

-1:失敗,設置errno。

參數:

options:設置為WNOHANG時,指定回收方式為非阻塞。默認為0,阻塞。

WNOHANG return immediately if no child has exited.

pid:

>0:回收指定id的子進程

-1:回收任意子進程(相當于wait)

0:回收和當前調用watipid在一個組的所有子進程

<-1:回收指定進程組内的任意子進程

stat_loc:子進程退出狀态,和wait函數中參數含義一樣。

waitpid(-1,NULL,0);等價于wait(NULL);

waitpid示例:

#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <sys/wait.h> int main(int argc, char const *argv[]) { int i = 0; int pid,pid_waitfor,wpid; for(i=0;i<5;i ) { pid = fork(); if(!pid) { break; } if(i==2) { pid_waitfor = pid;//指定回收第三個子進程,父進程中保存第三個子進程pid } //sleep(1); } if(i==5) { wpid = waitpid(pid_waitfor,NULL,0);//阻塞等待回收第三個子進程 //wpid = waitpid(-1,NULL,WNOHANG);//不阻塞回收任意一個子進程,沒有結束的子進程,返回值為0。 //wpid = waitpid(-1,NULL,0);//阻塞回收任意一個子進程。 if(wpid==-1) { perror("wait error"); exit(1); } printf("--parent process--waitfor %d--\n",wpid); } else { sleep(1); printf("--child process--pid=%d--\n", getpid()); } return 0; }

linux 進程用法(Linux進程基礎知識)23

wait、waitpid函數一次隻能回收一個子進程,要回收多個子進行需要循環。

循環回收多個子進程

#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <sys/wait.h> int main(int argc, char const *argv[]) { int i = 0; int pid,wpid; for(i=0;i<5;i ) { pid = fork(); if(!pid) { break; } } if(i==5) { /* while((wpid=waitpid(-1,NULL,0))!=-1)//注意最後返回-1 { printf("--wait child--%d\n",wpid); sleep(1); } */ while((wpid=waitpid(-1,NULL,WNOHANG))!=-1) { if(wpid>0) { printf("--wait child--%d\n",wpid); } else if(wpid==0) { sleep(1); } } } else { sleep(1); printf("--child process--pid=%d--\n", getpid()); } return 0; }

linux 進程用法(Linux進程基礎知識)24

發現waitpid沒有子進程可回收後返回-1。

#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <sys/wait.h> int main(int argc, char const *argv[]) { int wpid; //wpid=waitpid(-1,NULL,0); wpid=waitpid(-1,NULL,WNOHANG); //兩種結果一樣,不管有沒有設置阻塞,沒有子進程可回收後返回-1 if(wpid==-1) { printf("沒有子進程,返回-1\n"); } if(wpid==0) { printf("沒有子進程,返回0\n"); } return 0; }

linux 進程用法(Linux進程基礎知識)25

,
Comments
Welcome to tft每日頭條 comments! Please keep conversations courteous and on-topic. To fosterproductive and respectful conversations, you may see comments from our Community Managers.
Sign up to post
Sort by
Show More Comments
推荐阅读
黑胡椒煎蛋怎麼做
黑胡椒煎蛋怎麼做
1、鹽一小勺尖放碗裡。2、黑胡椒一小勺尖放碗裡。3、醬油一勺放碗裡。4、醋一勺放碗裡。5、将鹽黑胡椒醬油醋攪勻備用。6、鍋裡熱油,不必放太多。7、把蛋放鍋裡小火慢慢剪。8、煎制金黃色澆入黑椒汁,出鍋開吃。
2024-12-21
怎麼開啟京東小金庫
怎麼開啟京東小金庫
第一、京東小金庫是京東金融裡的一個選項,相當于錢包,我們可以把錢轉入京東小金庫裡,既安全又可以賺取收益。首先,下載京東金融APP。第二、下載了APP以後,用自己的電話号碼就可以注冊賬号了,這個比較簡單就不講解了。第三、在京東金融APP的首頁,就有一個京東小金庫,然後點擊進去。就可以填寫自己的真實名字...
2024-12-21
京東如何實名認證
京東如何實名認證
第一、打開手機,找到京東,進入首頁面。第二、進入之後,點擊右下角的我的,進入該頁面。第三、點擊右上角的設置,進入設置界面,如圖所示。第四、進入之後,找到實名認證,點擊并進入。第五、進入之後,填寫個人信息,填寫完成後,點擊下一步進入下一頁面。第六、填寫銀行卡号和預留手機号,填寫完成之後,點擊下一步,如...
2024-12-21
軍訓口号
軍訓口号
軍訓空号有:1、團結互助,自律自強。2、團結進取,奮力拼搏;齊心協力,共鑄輝煌!3、團結奮進,自律自強;愈挫愈勇,為國争光!4、刻苦訓練,自強不息;團結互助,勇争第一!5、團結一緻,奮力拼搏;争創一流,展我雄風!6、激情飛揚,超越夢想;挑戰極限,鑄就輝煌!7、努力學習,刻苦訓練;團結互助,争創佳績!8、軍中驕子,校園精英;勇往直前,誰與争鋒!9、服從命令,聽從指揮;團結互助,揚我班威!10、政治合
2024-12-21
保險公司不理賠怎麼辦
保險公司不理賠怎麼辦
1、如果保險公司懷疑你騙保而不理賠的話,可以投訴到他們的上一級、一直到省、甚至到國家,上面就會重視您的問題,很快就會得到解決。如果超過一個月您還沒能得到解決,就直接可以通過民事訴訟起訴保險公司了。2、保險公司不理賠,可以向當地保監局投訴,或者仲裁,如果都不能解決的話,可以起訴。3、向銀保監會投訴,可...
2024-12-21
Copyright 2023-2024 - www.tftnews.com All Rights Reserved