標籤:使用 os 檔案 資料 io for
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,….);第一個參數:替換的程式第二個參數…..:命令列 命令列格式:命令名 選項參數 命令列結尾必須Null 字元串結尾 案例: 使用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”); }}