函數做用:建立一個子進程ide
形式:pid_tfork(void);
函數
pid_t vfork(void);ui
說明:使用vfork創子進程時,不會進程父進程的上下文spa
返回值:[返回值=-1]子進程建立失敗3d
[返回值=0]子進程建立成功blog
[返回值>0]對父進程返回子進程PID進程
#include <stdio.h> #include <sys/stat.h> #include <unistd.h> int main() { pid_t id = fork(); if (id < 0) { perror("子進程建立失敗!"); } else { if (id == 0) { printf("子進程工做:PID=%d,PPID=%d\n", getpid(), getppid()); }else { printf("父進程工做:PID=%d,PPID=%d,子進程PID=%d\n", getpid(), getppid(),id); sleep(5) } } }
控制檯輸出ci
父進程工做:PID=3173,PPID=2432,子進程PID=3176資源
子進程工做:PID=3176,PPID=3173get
函數做用:終止發出調用的進程
形式:voidexit(int status);
說明
1. exit返回信息可由wait系統函數得到
2. 若是父進程先退出子進程的關係被轉到init進程下
#include <stdio.h> #include <sys/stat.h> #include <unistd.h> #include <stdlib.h> int main() { pid_t id = fork(); if (id < 0) { perror("子進程建立失敗!"); } else { if (id == 0) { printf("子進程工做:PID=%d,PPID=%d\n", getpid(), getppid()); sleep(20); printf("此時子進程:PID=%d,PPID=%d\n", getpid(), getppid()); }else { printf("父進程工做:PID=%d,PPID=%d,子進程PID=%d\n", getpid(), getppid(),id); sleep(5); exit(3); } } return 0; }
控制檯輸出
父進程工做:PID=3068,PPID=2432,子進程PID=3071
子進程工做:PID=3071,PPID=3068
此時子進程:PID=3071,PPID=1
函數做用:父進程與子進程同步,父進程調用後。進入睡眠狀態,直到子進程結束或者父進程在被其餘進程終止,
形式:pid_twait(int *status)
pid_t waitpid(pid_t pid ,int *status,int option)
參數:statusè exit是設置的代碼
pid è進程號
option: WNOHANG|WUNTRACED
WNOHANG:,即便沒有子進程退出,它也會當即返回,不會像wait那樣永遠等下去.
WUNTRACED:子進程進入暫停則立刻返回,但結束狀態不予以理會.
返回值:若是成功等待子進程結束,則返回子進程PID。後者爲-1
用來檢查子進程返回狀態的宏
WIFEXITED這個宏用來指出子進程是否爲正常退出的,若是是,它會返回一個非零值.
WEXITSTATUS當WIFEXITED返回非零值時,咱們能夠用這個宏來提取子進程的返回值
#include <sys/types.h> #include <sys/uio.h> #include <string.h> #include <fcntl.h> #include <unistd.h> #include <sys/wait.h> #include <stdio.h> #include <stdlib.h> int main() { pid_t cid; cid = fork(); if (cid < 0) { perror("子進程建立失敗!"); } else { if (cid == 0) { printf("子進程工做\n"); printf("子進程PID=%d,PPID=%d\n", getpid(),getppid()); //sleep(20); //1 } else { //wait(NULL);//2 //sleep(20);//3 printf("父進程工做\n"); printf("父進程PID=%d,PPID=%d\n", getpid(),getppid()); } } return 0; }
針對上述代碼做如下分析:
1. 當子進程退出時,若是父進程沒有wait進行回收資源,子進程就會一直變爲殭屍進程(Z)直到父進程退出
做法:
打開3處註釋後執行程序,查看進程狀態,以下
[root@localhostDebug]# ps -C Process -o pid,ppid,stat,cmd
PID PPID STAT CMD
12233 11563S /root/workspace/Process/Debug/Process
12238 12233Z [Process] <defunct>
=>能夠看到子進程此時的狀態時Z(殭屍進程)
控制檯輸出以下
子進程工做
子進程PID=12238,PPID=12233
(20S後…..)
父進程工做
父進程PID=12233,PPID=11563
2. 使用wait進行進程同步,父進程直到子進程退出,wait纔會結束等待
做法:
打開1,2處註釋後執行程序,查看進程狀態,以下
[root@ Debug8$] ps -C Process -o pid,ppid,stat,cmd
PID PPID STAT CMD
3425 2432 S /root/workspace/Process/Debug/Process
3430 3425 S /root/workspace/Process/Debug/Process
=>父進程與子進程都處於sleep狀態
控制檯輸出以下
子進程工做
子進程PID=3430,PPID=3425
(20S後…..)
父進程工做
父進程PID=3425,PPID=2432
3. 使用wait進行進程同步,子進程退出後,父進程結束wait等待,同時清空子進程信息,此時子進程再也不是殭屍進程
做法:
打開2,3處註釋後執行程序,查看進程狀態,以下
[root@localhostDebug]# ps -C Process -o pid,ppid,stat,cmd
PID PPID STAT CMD
1250611563 S /root/workspace/Process/Debug/Process
=>能夠看到此時只有父進程信息
控制檯輸出以下
子進程工做
子進程PID=12511,PPID=12506
(20S後…..)
父進程工做
父進程PID=12506,PPID=11563
#include <sys/types.h> #include <sys/uio.h> #include <fcntl.h> #include <unistd.h> #include <sys/wait.h> #include <stdio.h> #include <stdlib.h> int main() { pid_t cid; int pr, status; cid = fork(); if (cid < 0) { perror("子進程建立失敗!"); } else { if (cid == 0) { printf("子進程工做PID=%d,父進程PID=%d\n", getpid(),getppid()); sleep(20); exit(3); } else { pr = wait(&status); if (WIFEXITED(status)) { printf("父進程工做PID=%d\n", getpid()); printf("WAIT返回值=%d\n", pr); printf("子進程正常退出PID=%d\n", getpid()); printf("WIFEXITED(status)=%d\n", WIFEXITED(status)); printf("WEXITSTATUS(status)=%d\n", WEXITSTATUS(status)); } else { printf("子進程異常退出PID=%d,信號=%d\n", getpid(), status); printf("WAIT返回值=%d\n", pr); } } } return 0; }
基於上面代碼作出分析:
1. 子進程正常退出
控制檯輸出信息以下:
子進程工做PID=12070,父進程PID=12069
(20S後…..)
父進程工做PID=12069
WAIT返回值=12070
子進程正常退出PID=12069
WIFEXITED(status)=1
WEXITSTATUS(status)=3
2. 子進程異常退出
做法:
運行程序,在子進程SLEEP期間,殺死子進程
[root@localhost Debug]# kill -9 11990
控制檯臺輸出以下
子進程工做PID=11990,父進程PID=11985
(kill -9 PID 殺死子進程)
子進程異常退出PID=11985,信號=9
能夠看出子進程正常退出時,status返回值是exit的退出值,子進程異常退出時status返回值信號值
waitpid的參數說明
參數pid的值有如下幾種類型:
pid>0時,只等待進程ID等於pid的子進程,無論其它已經有多少子進程運行結束退出了,只要指定的子進程尚未結束,waitpid就會一直等下去.
pid=-1時,等待任何一個子進程退出,沒有任何限制,此時waitpid和wait的做用如出一轍.
pid=0時,等待同一個進程組中的任何子進程,若是子進程已經加入了別的進程組,waitpid不會對它作任何理睬.
pid<-1時,等待一個指定進程組中的任何子進程,這個進程組的ID等於pid的絕對值.
參數options的值有如下幾種類型:
若是使用了WNOHANG參數,即便沒有子進程退出,它也會當即返回,不會像wait那樣永遠等下去.
若是使用了WUNTRACED參數,則子進程進入暫停則立刻返回,但結束狀態不予以理會.
若是咱們不想使用它們,也能夠把options設爲0,如:ret=waitpid(-1,NULL,0);
#include <sys/types.h> #include <sys/uio.h> #include <fcntl.h> #include <unistd.h> #include <sys/wait.h> #include <stdio.h> #include <stdlib.h> int main() { pid_t cid; int pr, status; cid = fork(); if (cid < 0) { perror("子進程建立失敗!"); } else { if (cid == 0) { printf("子進程工做PID=%d\n", getpid()); sleep(5); exit(3); } else { do{ pr = waitpid(0,&status, WNOHANG); if(pr==0) { printf("沒有子進程退出,繼續執行..\n"); sleep(1); } }while(pr==0); printf("子進程正常退出PID=%d\n", pr); } } return 0; }
控制檯輸出:
沒有子進程退出,繼續執行..
子進程工做PID=3632
沒有子進程退出,繼續執行..
沒有子進程退出,繼續執行..
沒有子進程退出,繼續執行..
沒有子進程退出,繼續執行..
子進程正常退出PID=3632
#include <sys/types.h> #include <unistd.h> #include <sys/wait.h> #include <stdio.h> #include <stdlib.h> int main() { pid_t cid; int pr, status; cid = fork(); if (cid < 0) { perror("子進程建立失敗!"); } else { if (cid == 0) { printf("子進程工做PID=%d,PPID=%d\n", getpid(), getppid()); sleep(20); exit(3); } else { pr = waitpid(cid, &status, 0); printf("父進程正常退出PID=%d\n", pr); } } return 0; }
控制檯輸出
子進程工做PID=4257,PPID=4252
父進程正常退出PID=4257
#include <sys/types.h> #include <unistd.h> #include <sys/wait.h> #include <stdio.h> #include <stdlib.h> int main() { pid_t cid; int pr, status; cid = fork(); if (cid < 0) { perror("子進程建立失敗!"); } else { if (cid == 0) { printf("子進程工做PID=%d,PPID=%d\n", getpid(), getppid()); sleep(30); exit(3); } else { pr = waitpid(cid, &status, WUNTRACED); printf("父進程正常退出PID=%d,status=%d\n", pr,status); } } return 0; }
做法:在子進程SLEEP時,經過SHELL命令中止子進程
[root@ ~ 6$] kill -STOP PID
控制檯輸出
子進程工做PID=4110,PPID=4108
(SLEEP期間,中止子進程)
父進程正常退出PID=4110,status=4991
在查看進程狀態,發現此時父進程子進程都已經退出
[root@ Debug 13$] ps -C Process -opid,ppid,stat,cmd
PID PPID STAT CMD
函數做用:以新進程代替原有進程,但PID保持不變
形式:
int execl(const char *path, const char*arg, ...);
int execlp(const char *file, const char*arg, ...);
int execle(const char *path, const char*arg, ..., char * const envp[]);
int execv(const char *path, char *constargv[]);
int execvp(const char *file, char *constargv[]);
int execve(const char *path, char *constargv[], char *const envp[]);
舉例:
exec1.c #include <stdio.h> #include <unistd.h> int main() { printf("這是第一個進程PID=%d\n",getpid()); execv("e2",NULL); printf("asa"); return 0; } exec2.c #include <stdio.h> #include <unistd.h> int main() { printf("這是第二個進程PID=%d\n",getpid()); }
運行結果:
[root@ Process 9$] gcc -o e1 exec1.c
[root@ Process 10$] gcc -o e2 exec2.c
[root@ Process 11$] ./e1
這是第一個進程PID=3051
這是第二個進程PID=3051