exec函數(shù)族
exec系統(tǒng)調(diào)用:可以把當(dāng)前進(jìn)程替換為一個(gè)新進(jìn)程,并轉(zhuǎn)換到調(diào)用進(jìn)程的內(nèi)存空間
execl、execlp
舉例子:
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
int main(int argc,char *argv[]){
pid_t ret;
ret = fork();
if(ret == 0 ){
// execlp("ls","ls","-l","-h",NULL);
execl("../demo1025/sys-fork","./sys-fork",NULL);
perror("execlp error");
printf("i am child");
}
if(ret >0){
sleep(2);
printf("i am parent");}
if(-1 == ret ){
perror("error");
}
}
小問題:
my_execlp.c: 在函數(shù)‘main’中:
my_execlp.c:14: 警告:隱式聲明與內(nèi)建函數(shù)‘exit’不兼容
my_execlp.c:22: 警告:隱式聲明與內(nèi)建函數(shù)‘exit’不兼容
解決方式:手動(dòng)添加函數(shù)聲明void exit(int);
默認(rèn)的隱式聲明int exit(int);
孤兒進(jìn)程
父進(jìn)程結(jié)束了肥哎,而子進(jìn)程依然存在葫笼,那么子進(jìn)程成為了孤兒進(jìn)程,由init進(jìn)程接收础废。
僵尸進(jìn)程
當(dāng)一個(gè)子進(jìn)程結(jié)束運(yùn)行的時(shí)候汛骂,它與其父進(jìn)程之間的關(guān)聯(lián)還會(huì)保持到父進(jìn)程也正常地結(jié)束運(yùn)行或者父進(jìn)程調(diào)用了wait才告終止,稱之為僵尸進(jìn)程评腺。
回收子進(jìn)程
wait
1帘瞭、使父進(jìn)程阻塞等待
2、返回結(jié)束的子進(jìn)程的pid
3蒿讥、通過status能夠獲取子進(jìn)程結(jié)束的狀態(tài)蝶念。
waitpid
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
int main(int argc,char *agrv[]){
pid_t pid_ret1,pid_ret2;
int i=0;
int status;
for(;i<5;i++){
pid_ret1 = fork();
if(pid_ret1 == 0){
printf("times = %d pid = %d\n",i,getpid());
break;
}
//pid_ret2 = wait(&status);
pid_ret2 = waitpid(-1,&status,WNOHANG);
printf("waitpid = %d\n",pid_ret2);
if(WIFEXITED(status)){
printf("returns the exit status of the child\n");
}
}
}
進(jìn)程間通信IPC
四種:
管道pipe、fifo
特點(diǎn):偽文件芋绸,內(nèi)核當(dāng)中的一個(gè)緩沖區(qū)
應(yīng)用在有血緣關(guān)系的進(jìn)程間媒殉。
本質(zhì)上是一個(gè)隊(duì)列,循環(huán)隊(duì)列摔敛。
局限性:
1廷蓉、一端充當(dāng)讀端,一端充當(dāng)?shù)膶懚?br>
2马昙、不能反復(fù)讀取
3苦酱、雙向半雙工
pipe讀和寫的特點(diǎn)
寫端:
1售貌、所有讀端全部關(guān)閉,異常終止
2、有讀端疫萤,
管道已滿 阻塞等待
未滿颂跨,返回實(shí)際的字節(jié)數(shù)。
讀端:
1扯饶、管道有數(shù)據(jù)恒削,返回實(shí)際讀到的字節(jié)數(shù)
2、管道無數(shù)據(jù)尾序,
無寫端 返回0
有寫端 阻塞
練習(xí):
子進(jìn)程中實(shí)現(xiàn)ls 父進(jìn)程中實(shí)現(xiàn)wc -l
#include <stdio.h>
#include <unistd.h>
void exit(int);
int main(int argc,char *agrv[]){
pid_t pid_ret1;
int i=0;
int fd[2];
char buff[]="hello";
char buff1[6];
int ret = pipe(fd);
if(-1 == ret)
{
perror("pipe failed");
exit(1);
}
pid_ret1 = fork();
if(-1 == pid_ret1){
perror("fork failed!");
exit(1);
}
//寫端 ls
if(0 == pid_ret1){
close(fd[0]);
dup2(fd[1],STDOUT_FILENO);
//execlp
execlp("ls","ls",NULL);
close(fd[1]);
printf("child\n");
}
//讀段 wc -l
if(pid_ret1 >0)
{
close(fd[1]);
sleep(1);
dup2(fd[0],STDIN_FILENO);
//重定向钓丰,將原本對(duì)標(biāo)準(zhǔn)輸入操作重定向?yàn)閒d[0]
printf("************");
execlp("wc","wc","-l",NULL);
//執(zhí)行wc -l的功能,不再從標(biāo)準(zhǔn)輸入讀取每币,而是從fd[0]讀取了
//注意:dup2必須先于execlp執(zhí)行携丁,否則沒有重定向的時(shí)機(jī)了。
close(fd[0]);
printf("parent\n");
}
}
練習(xí):
2個(gè)兄弟進(jìn)程間實(shí)現(xiàn)ls |wc -l
父進(jìn)程回收子進(jìn)程ID