本文重点:
shell中处理外部命令是通过创建子进程后程序替换完成功能;还有一部分是内建命令,也是shell自身实现的功能;
shell运行的原理:
shell起来之后先运行一个终端,然后假设scanf 将要获取需要输入的数据;用户假设输入一个ls -a,则scanf将获取到这个用户输入,并进行解析,此时将此解析为ls 和 a;然后认为ls 就是要运行的程序,a就是参数;然后创建子进程fork(),由子进程创建了另一个进程;在另一个程序中第一步就是execl(ls,-a)进行程序替换;然后创建的这个进程运行完了就退出,此时fork()创建的进程需要进行wait()等待子进程退出;
实现流程:
1.获取一个字符串;
2.对字符串进行解析;
3.获取到程序名称和参数;
4.创建进程完成替换;
具体操作代码如下:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <ctype.h>
int main(){
while(1){
//获取一个字符串;
printf("[jone@localhost pcontrol]$");
fflush(stdout);
char tmp[1024]={0};
scanf("%[^\n]%*c",tmp);
printf("%s\n",tmp);
//%[^\n]:从标准输入缓冲区去取数据直到遇到\n截止;
//%*c:将缓冲区中的剩下的\n取出否则造成死循环;
//将整体的字符串解析出:程序名+参数;
char* ptr=tmp;
int argc=0;
while(*ptr!='\0'){
if(!isspace(*ptr)){
argv[argc]=ptr;
argc++;
while(!isspace(*ptr) && *ptr!='\0') ptr++;
*ptr='\0';
ptr++;
continue;
}
ptr++;
}
int i=0;
for(;i<argc;++i){
printf("argv[%d]=[%s]\n",i,argv[i]);
}
argv[argc]=NULL;
if(!strcmp(argv[0],"cd")){
//改变当前工作路径;
chdir(argv[1]);
continue;
}
int pid=fork();
if(pid==0){
execvp(argv[0],argv);
//若子进程程序替换失败,则直接退出,因为终端不需要多个shell;
exit(0);
}
wait(NULL); //等待子进程退出,避免僵尸进程;
}
return 0;
}
输出结果如下: