程序的建立、回收和終止
阿新 • • 發佈:2019-02-04
一、程序的建立: //核心裡面只有fork 和exec兩種可以建立程序。其他方式都是使用的這兩種方式,如system()封裝了exec。system()fork()exec()popen()二、程序的回收:孤兒程序殭屍程序wait()三、程序的終止:main函式的自熱返回;呼叫exit函式;呼叫_exit函式;呼叫abort函式;接收能導致程序終止的訊號Ctrl +c SSIGINT ctrl+\ SIGQUIT----------------------------------------------------------------------------------------------------------------------------------------------------------------一、程序建立 1.system函式:不常用#include <stdlib.h>int main(){ system("ls -l"); //建立了一個ls -l的程序。system("clear")表示清屏。}2.fork() 複製出一份。各自是各自的。每個程序都有一個檔案表項。其實就是為了比如說雙胞胎,出生之後完全一樣。一個身上有什麼東西,另一個人相同的地方就有什麼東西。父程序先返回子程序的pid(),第二次子程序返回0.例子1:pid_t pid;pid=fork(); //fork不需要傳遞引數。 if(pid==0){ //這裡寫子程序接下來做的事 printf("%d%d",getpid(),getppid()); while(1);}else{ //這裡寫父程序接下來做的事 printf("%d",pid); }例子2:int i=3;pid_t pid;pid=fork(); if(pid==0){ i++; //在這裡改變i的值 printf("%d%d",getpid(),getppid()); while(1);}else{ sleep(10); //寫sleep()是為了確保子程序先執行,執行了i++這條指令。 printf("%d",i); //列印i,發現i的值還是3.這是因為子程序和父程序各有自己的虛擬記憶體空間,雖然記憶體都相同,但是各自是 各自的,建立完了之後,各自就開始操作各自的了。 printf("%d",pid); }3.exec系列(工作中用的太少了)一個程序建立另一個程序,會直接用新程序覆蓋原有程序的程式碼段。exec系列有6個函式:execl()、execlp()、execle()、execv()、execvp()、execvpe()例:add.cint main(int argc,char *argv[]){ int i=atoi(argv[0]); int j=atoi(argv[1]); return i+j;}execl.c#include <unistd.h>#include <stdio.h>int main(){ excel("./add","add","1","2",NULL); //./可執行檔案 argv[0] argv[1] argv[2].......NULL 。引數一定要從argv[0]開始寫,最後寫NULL printf("hello\n"); printf("hello\n");及以下的都不會再執行了,因為從excel走進了另一個世界 。 ....}4.popen見《程序間通訊IPC》中的管道部分----------------------------------------------------------------------------------------------------------------------------------------------------------------二、程序回收 孤兒程序:老爹死了你還沒死! 如果父程序先於子程序退出,則子程序成為孤兒程序,此時將自動被PID為1的程序(即init)接管。孤兒程序退出後,它的清理工作有祖先程序init自動處理。init清理沒那麼及時,畢竟不是親爹。 子程序退出時,應當由父程序回收資源。應當避免父程序退出了,子程序還在的情況。即,應當避免孤兒程序。所以父程序要等子程序執行完了再退出。例:孤兒程序 pid_t pid = fork(); if( pid == 0) { while(1) ; //父程序退出了,之後子程序還在執行。通過ps -elf 可以看到程序的ppid變成了1. }else{ exit(0); } 殭屍程序:你死了沒人給你收屍! 如果子程序先退出,系統不會自動清理掉子程序的環境,而必須由父程序呼叫wait或waitpid函式來完成清理工作,如果父程序不做清理工作,則已經退出的子程序將成為殭屍程序(defunct),在系統中如果存在的殭屍(zombie)程序過多,將會影響系統的效能,所以必須對殭屍程序進行處理。例:殭屍程序 pid_t pid=fork(); if(pid == 0){ exit(0); }else{ while(1); //子程序都已經退出了,但是父程序沒有回收。ps-elf 可以看到殭屍程序。 }避免殭屍程序(wait函式): #include <sys/types.h> #include <sys/wait.h> pid_t wait(int *status); pid_t waitpid(pid_t pid, int *status, int options); //opeions若為WNOHANG,則父程序執行到這,看看有殭屍就回收,沒殭屍就直接走 了,往下執行,不等了。例1: pid_t pid; pid=fork(); if(pid == 0){ sleep(5); exit(0); }else{ wait(NULL); //子程序sleep(5)期間,可以看到父程序的狀態時阻塞(sleep),等待子程序結束。等子程序結束之後回收資源。 exit(0); wait(NULL)表示等待所有程序。 }例2: pid_t pid; pid=fork(); if(pid == 0){ sleep(5); exit(0); }else{ waitpid(pid,NULL,0); //等待指定pid的子程序。 exit(0); }}例3: pid_t pid; pid=fork(); if(pid == 0){ while(1); exit(2); //如果程序正常結束,返回2。如果不正常的話(比如,ctrl+c),返回0. }else{ int status; //status存放子程序的退出狀態,status含有很多資訊,其中就包括返回值。 wait(&status); printf("I am wake\n"); if(WIFEXITED(status)){ //這個巨集用來獲取狀態資訊。如果程序正常結束,則結果非零。 printf("the exit value=%d\n",WEXITSTATUS(status)); //這個巨集返回子程序的退出碼。這個例子中是2. }else{ printf("the child abort\n"); //如果WIFEXITED(status)==0,說明不是正常退出。 } exit(0); }----------------------------------------------------------------------------------------------------------------------------------------------------------------程序終止程序終止有5種方式:main函式的自熱返回;呼叫exit函式;呼叫_exit函式;呼叫abort函式;接收能導致程序終止的訊號Ctrl +c SSIGINT ctrl+\ SIGQUITmain函式的自然返回return 一級一級返回。呼叫exit函式exit直接退出程序。例子:int main(){ pid_t pid; pid=fork(); if(pid == 0){ exit(0); }else{ printf("child pid=%d\n",pid); exit(0); }}呼叫_exit函式(幾乎不用) printf("helloworld");exit(); //會清理緩衝區,所以能正常打印出來。printf("helloworld");_exit(); //printf()只是把"helloworld"放進去,沒有重新整理,就直接退出了。所以沒有打印出來。abort()函式(用的很少) 自己給自己發一個自殺訊號。比如,發現傳參錯誤。kill -l 可以看到訊號都有哪些。abort和最後一個發訊號可以理解為是一樣的,都是發訊號。abort會產生core檔案