计算机壳层——shell
shell
在计算机科学中,Shell俗称壳(用来区别于核),是指“提供使用者使用界面”的软件(命令解析器)。它接收用户命令,然后调用相应的应用程序。
同时它又是一种程序设计语言。作为命令语言,它交互式解释和执行用户输入的命令或者自动地解释和执行预先设定好的一连串的命令;作为程序设计语言,它定义了各种变量和参数,并提供了许多在高级语言中才具有的控制结构,包括循环和分支。
shell 的工作步骤:
(1)获取命令行
(2)解析命令行
(3)建立一个子进程 (fork)
(4)替换子进程 (exec)
(5)父进程等待子进程退出 (wait )
shell的实现
#include<unistd.h>
#include<string.h>
#include<sys/wait.h>
#include<ctype.h>
#include<stdlib.h>
#include<stdio.h>
int argc = 0;
char* argv[8] = {};
//解析并获取命令行
void do_parse(char* buf)
{
argc = 0;
int i=0;
int status = 0;
for(i=0;buf[i] != 0 ; i++){
if((! isspace(buf[i])) && (status == 0)){ //读取字符,直到空格停止
argv[argc++] = buf + i;
status = 1;
}
else if(isspace(buf[i])){
buf[i] = 0;
status = 0;
}
}
}
//建立,替换,回收子进程
void do_shell()
{
pid_t pid = fork();
if(pid == -1)
{
perror("fork");
return;
}
else if(pid > 0)
{
wait(NULL); //回收子进程
}
else //对子进程进行替换
{
if(execvp(argv[0],argv)==-1)
perror("execvp"),exit(1);
}
}
int main()
{
char buf[1024] = {};
while(1){
memset(buf,0X00,sizeof(buf)); //清空buf
printf("shell > ");
scanf("%[^\n]",buf);
scanf("%*c");
if(strcmp(buf,"exit") == 0)
break;
do_parse(buf);
do_shell();
}
}
运行结果
注释: execvp
定义函数:
int execvp(const char file ,char const argv []);
函数说明:
execvp()会从PATH 环境变量所指的目录中查找符合参数file 的文件名,找到后便执行该文件,然后将第二个参数argv传给该欲执行的文件。
返回值:
如果执行成功则函数不会返回,执行失败则直接返回-1,失败原因存于errno中。
封装fork/wait,自主编写process_create函数
刚刚我们了解了一下execvp这个函数,下面我们再来玩一把
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/wait.h>
int process_create(int (*func)(),const char* file, char*argv[])
{
int ret = 0;
pid_t pid = fork();
if(pid == -1)
{
perror("fork");
return -1;
}
else if( pid == 0)
{
ret = func(file,argv);
if(ret == -1)
perror("func"),exit(1);
}
else
{
int null;
pid_t ret = wait(&null);
if(ret == -1)
perror("wait"),exit(1);
}
return 0;
}
int main()
{
char* argv1[] = {"ls"};
char* argv2[] = {"ls","-al","/etc/passwd",0};
process_create(execvp,*argv1,argv2);
return 0;
}
运行结果: