Linux進(jìn)程原語(yǔ)及功能:
- fork:創(chuàng)建一個(gè)新的子進(jìn)程;
- exec族(execl聋袋、execlp、execle穴吹、execv幽勒、execvp、execve):
執(zhí)行一個(gè)文件港令;
用fork創(chuàng)建子進(jìn)程后執(zhí)行的是和父進(jìn)程相同的程序(但有可能執(zhí)行不同的代碼分支),子進(jìn)程往往要調(diào)用一種exec函數(shù)以執(zhí)行另一個(gè)程序啥容。
當(dāng)進(jìn)程調(diào)用一種exec函數(shù)時(shí),該進(jìn)程的用戶空間代碼和數(shù)據(jù)完全被新程序替換,從新程序的啟動(dòng)例程開(kāi)始執(zhí)行。
調(diào)用exec并不創(chuàng)建新進(jìn)程,所以調(diào)用exec前后該進(jìn)程的pid并未改變顷霹。
- wait族(wait咪惠、wait3、wait4淋淀、waitpid):等待子進(jìn)程終結(jié)遥昧,以使父進(jìn)程回收其子進(jìn)程.
進(jìn)程從創(chuàng)建到最終被回收過(guò)程的簡(jiǎn)易圖示:
進(jìn)程創(chuàng)建與消亡流程
父進(jìn)程調(diào)用fork系統(tǒng)調(diào)用創(chuàng)建子進(jìn)程 ;
-> 子進(jìn)程調(diào)用exec系統(tǒng)調(diào)用來(lái)執(zhí)行其他代碼 ;
-> 子進(jìn)程執(zhí)行完代碼后退出,等待父進(jìn)程回收,此時(shí)的子進(jìn)程處于僵死狀態(tài)(使用ps命令依然可以查看得到炭臭,但是已經(jīng)不能運(yùn)行);
-> 父進(jìn)程調(diào)用wait函數(shù)回收子進(jìn)程永脓,但是如果父進(jìn)程在子進(jìn)程結(jié)束前就結(jié)束了,則子進(jìn)程在結(jié)束運(yùn)行后將成為孤兒進(jìn)程鞋仍,并最終被init進(jìn)程認(rèn)領(lǐng)并回收常摧。
代碼示例 process.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
pid_t pid;
pid = fork();
if (pid > 0) { /* in parent */
printf("I am parent\n");
exit(0);
}
else if (pid == 0) { /* in child */
printf("I am child\n");
execl("/home/slot/print_args", "print_args", "haha", NULL);
}
else {
perror("fork error");
exit(-1);
}
printf("Hello world\n");
return 0;
}
其中 print_args.c
的功能是打印命令行參數(shù),代碼如下:
#include <stdio.h>
int main(int argc, char const *argv[])
{
int i = 0;
while (i < argc)
printf("%s\n", argv[i++]);
/* 此處故意將返回值設(shè)置為233以便于觀察區(qū)別 */
return 233;
}
執(zhí)行結(jié)果
$ gcc print_args.c -o print_args
$ gcc process.c -o process
$
$ ./process
I am parent
I am child
print_args
haha