在 Linux 中,进程控制有四种状态:创建、退出、等待、替换。
为 验证 或 应用 以上四种进程状态,所以有了下面 minishell
的实现。
注:Linux
中的 shell
,是指一个面向用户的命令接口,表现形式就是一个可以由用户录入的交互界面,其相当于 Windows
上 cmd
命令行。而下述程序为 shell
程序的简易版,只是简单实现了其中的一部分功能。
实现简单的 minishell(命令行解释器)步骤:
1.捕捉用户键盘输入
如sprintf,fgets,scanf(默认以空格为间隔),所以使用fgets,直接获取一行程序
2.解析输入信息:得到命令名称,运行参数
3.创建子进程,在子进程中通过命令名称进行程序替换(让子进程运行命令)
4.进程等待,等待子进程退出,防止出现僵尸进程
循环以上进程
程序如下:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<sys/wait.h> // 使用wait()和waitpid()函数时所需的头文件
#include<ctype.h> // 处理字符
int main(int argc,char *argv[]) //argc 参数个数,argv 全部参数
{
while(1)
{
printf("[user@host path]$ ");
fflush(stdout); //刷新缓冲区
char cmd[1024]; //用于保存输入指令
fgets(cmd,1023,stdin);
cmd[strlen(cmd)-1]='\0';//换行
// 解析指令
char *ptr=cmd;
char *arg[32]={NULL}; // 程序运行参数
int ac=0;
while(*ptr!='\0') // 将输入指令保存至 arg 中
{
if(!isspace(*ptr)) //isspace() 是测试参数是否是空格、制表符或换行符的函数
{
arg[ac]=ptr;
ac++;
while(*ptr!='\0' && !isspace(*ptr)) ptr++;
*ptr='\0';
}
ptr++;
}
arg[ac]=NULL; // 在 exec 函数族中的函数,其参数列表中的程序运行参数最后一个应为 NULL
if(strcmp(arg[0],"cd")==0) //判断输入指令是否为 cd ,若是则需改变路径至新目录下
{
chdir(arg[1]);//改变路径到新目录下
continue;
}
pid_t pid = fork(); // 创建子进程,成功父进程则返回子进程的 pid ,且子进程会返回 0;若失败则返回 -1
if(pid<0)
{
continue;
}
else if(pid == 0)
{
execvp(arg[0],arg); // 子进程执行输入命令
exit(-1);
}
wait(NULL);
}
return 0;
}
上述程序是在 Linux
中进行编译的,且其编译后的执行文件为 shell
。调用 shell
执行文件后,其实现的结果如下:
上图中,可发现在 shell
文件 还未执行前 ls
实现的结果与 shell
文件 执行后 ls
的结果一致。简单总结就是上述 minishell
的实现程序没有问题!