基於fork(),execvp()和wait()實現類linux下的bash——mybash
預備知識
產品僞代碼
Step1:讀入用戶輸入的指令;
Step2:調用fork函數生成一個子進程,並將fork返回的pid值賦給fpid;
Step3:調用wait函數,傳入null;
Step4:判斷fpid是否爲零,若是爲零執行Step5;若是不爲零,執行Step6;
Step5:調用execvp函數,並把用戶輸入的指令傳進去;
Step6:返回Step1;
產品代碼
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#define MAXARGS 20
#define ARGLEN 100
int execute( char *arglist[] )
{
execvp(arglist[0], arglist);
perror("execvp failed");
exit(1);
}
char * makestring( char *buf )
{
char *cp;
buf[strlen(buf)-1] = '\0';
cp = malloc( strlen(buf)+1 );
if ( cp == NULL ){
fprintf(stderr,"no memory\n");
exit(1);
}
strcpy(cp, buf);
return cp;
}
int mybash(char *arglist[])
{
int flag=0;
flag=fork();
wait(NULL);
if(flag==0)
execute( arglist );
else return 1;
}
測試代碼
#include<stdio.h>
#include <string.h>
#include"head.h"
int mybash(char *arglist[]);
int test1()
{
char *test1[10],*test2[10],*test3[10],*test4[10],*test5[10],*test6[10];
test1[0]="ls";
test1[1]="-l";
test1[2]=0;
test2[0]="od";
test2[1]="-tc";
test2[2]="-tx1";
test2[3]="12.txt";
test2[4]=0;
test3[0]="mkdir";
test3[1]="success";
test3[2]=0;
test4[0]="git";
test4[1]="add";
test4[2]=".";
test4[3]=0;
test5[0]="git";
test5[1]="commit";
test5[2]="-m";
test5[3]="\"test11\"";
test5[4]=0;
test6[0]="git";
test6[1]="push";
test6[2]="origin";
test6[3]="master";
test6[4]=0;
int flag=0;
if(flag=mybash(test1)==1)printf("\n%s %s test Success!\n",test1[0],test1[1]);
flag=0;
if(flag=mybash(test2)==1)printf("\n%s %s %s %s test Success!\n",test2[0],test2[1],test2[2],test2[3]);
flag=0;
if(flag=mybash(test3)==1)printf("\n%s %s test Success!\n",test3[0],test3[1]);
flag=0;
if(flag=mybash(test4)==1)printf("\n%s %s %s test Success!\n",test4[0],test4[1],test4[2]);
flag=0;
if(flag=mybash(test5)==1)printf("\n%s %s %s %s test Success!\n",test5[0],test5[1],test5[2],test5[3]);
flag=0;
if(flag=mybash(test6)==1)printf("\n%s %s %s %s test Success!\n",test6[0],test6[1],test6[2],test6[3]);
return 0;
}
- 測試運行截圖
問題及解決方法
- 問題1:由於使用的是execvp函數是放在主函數裏的,每每都會直接終結掉父進程,這是主要問題;
- 問題1解決:調用fork函數生成一個子進程,而且只容許execvp運行在子進程中,這樣execvp終結掉的就只是子進程,而不會影響父進程,而對於fork函數完整複製父進程的子進程也會由於調用了execvp而及時終結掉,不會致使一個無謂的循環。
- 問題2:怎麼實現只讓execvp運行在子進程,而不去影響父進程
- 問題2解決:這是根本問題,解決了才能使得mybash正常的去運行去循環,由於fork函數的特性就是完整複製父進程,但子進程永遠都是從fork後面執行意思就是,fork前面的變量將保持初始化的值,而不受fork前面的代碼影響,因此,這裏可使用fpid來做爲flag判斷這是一個子進程仍是一個父進程,若是是一個子進程那麼就運行execvp,若是不是就返回繼續執行父進程;
運行截圖