Linux c 進程管理: 1. 建立進程: system函數: int system(const char*filename); 創建獨立進程,擁有獨立的代碼空間,內存空間 等待新的進程執行完畢,system才返回.(阻塞) system:建立一個堵塞的新進程,新進程結束後,system才返回 案例: 使用system調用一個程序。 觀察進程ID。 觀察阻塞。 代碼: text.c #include<stdio.h> #include<unistd.h> void main() { printf(「%d\n」,getpid()); //打印當前進程id sleep(10); //進程睡眠10秒 } gcctext.c –o text system.c #include<stdio.h> #include<stdlib.h> #include<unistd.h> void main() { printf(「%d\n」,getpid()); int r=system(「./text」); printf(「%d\n」,r); } gccsystem.c –o main 結論: 新進程的返回值與system返回值有關係。 任何進程的返回值:不要超過255。一個字節。 system的返回值中8-15位存放返回碼(一個字節存放返回碼) 要想獲得返回碼,則不能直接用system的返回值,要取返回值的8-15位的內容。 Linux提供一個宏來獲取該值WEXITSTATUS(status)、包含在#include<sys/wait.h>中 代碼: text.c #include<stdio.h> #include<unistd.h> int main() { printf(「%d\n」,getpid()); //打印當前進程id sleep(10); //進程睡眠10秒 return 99; } gcctext.c –o text system.c #include<stdio.h> #include<stdlib.h> #include<unistd.h> void main() { printf(「%d\n」,getpid()); int r=system(「./text」); printf(「%d\n」,WEXITSTATUS(r)); } gccsystem.c –o main popen函數: #include<stdio.h> 函數原型: FILE * popen ( constchar * command , const char * type ); int pclose ( FILE * stream ); popen:建立子進程 在父子進程之間創建一個管道 command: 是一個指向以 NULL 結束的 shell 命令字符串的指針。這行命令將被傳到 bin/sh 並使用 -c 標誌,shell將執行這個命令。 type: 只能是讀或者寫中的一種,獲得的返回值(標準I/O 流)也具備和 type 相應的只讀或只寫類型。若是type 是 「r」 則文件指針鏈接到 command 的標準輸出;若是 type 是 「w」 則文件指針鏈接到command 的標準輸入。 返回值: 若是調用成功,則返回一個讀或者打開文件的指針,若是失敗,返回NULL,具體錯誤要根據errno判斷 int pclose (FILE*stream) 參數說明: stream:popen返回的文件指針 返回值: 若是調用失敗,返回 -1 案例: 使用popen調用ls -l,而且創建一個管道讀取輸出 #include<stdio.h> #include<unistd.h> void main() { char buf[1024]; FILE *f=popen(「ls - l」,」r」); int fd=fileno(f); int r; while((r=read(fd,buf,1024))>0) { buf[r]=0; printf(「%s」,buf); } close(fd); pclose(f); } execlexecle: 代替當前進程的代碼空間中的代碼數據,函數自己不建立新的進程。 excel函數: int execl(const char * path,const char*arg,….); 第一個參數:替換的程序 第二個參數…..:命令行 命令行格式:命令名 選項參數 命令行結尾必須空字符串結尾 案例: 使用exec執行一個程序。 體會:*是否建立新的進程?沒有 *體會execl的參數的命令行的格式 *體會execl與execlp的區別(execl只當前路徑)(不是當前路徑必須加絕對路徑) execlp使用系統的搜索路徑 *體會execl替換當前進程的代碼 代碼: text.c #include<stdio.h> #include<unistd.h> void main() { printf(「%d\n」,getpid()); //打印當前進程id sleep(10); //進程睡眠10秒 } gcctext.c –o text exec.c #include<stdio.h> #include<unistd.h> void main() { printf(「main::%d\n」,getpid()); int r=excel(「./text」,」text」,NULL); //int r=excel(「/bin/ls」,」ls」,」-l」,NULL); //int r=excelp(「ls」,」ls」,」-l」,NULL); printf(「結束:%d\n」,r); } 總結: 程序運行後,兩個打印進程id是同樣,則excel和execlp不建立新的進程。 最後的打印結束的語句不能執行,由於excel和excelp是將新的程序的代碼替換到該程序的代碼空間中了。 兩個函數的最後一個參數必須爲0或NULL 函數的第一個參數是可執行程序的路徑,第二個參數纔是執行的命令 fork函數: 函數原型: pid_t fork(); //1.建立進程 //2.新進程的代碼是什麼:克隆父進程的代碼 並且克隆了執行的位置.(從父進程複製過來的代碼,fork以前的代碼不會再子進程中執行,子進程只會執行從父進程複製過來的fork之後的代碼) //3.在子進程不調用fork因此返回值=0;(pid=0爲子進程的) //4.父子進程同時執行. 例子代碼: #include<stdio.h> #include<unistd.h> void main() { printf(「建立進程以前\n」); int pid=fork(); printf(「創進程以後%d\n」,pid); } 雖然子進程的代碼是克隆父進程的,但咱們也能夠把子進程要執行的代碼和父進程要執行的代碼分開。 例子: #include<stdio.h> #include<unistd.h> voidmain() { printf(「建立進程以前:\n」); int pid=fork(); if(pid==0) { printf(「子進程:\n」); } else { printf(「父進程:\n」); } }