1. 程式人生 > >程序的建立、回收和終止

程序的建立、回收和終止

一、程序的建立:       //核心裡面只有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檔案