具体知识点参考《进程控制》
目录
代码截图:
运行效果
代码如下
#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/wait.h>
#include<sys/types.h>
#define NUM 1024
#define SIZE 32
//保存打散之后的命令行字符串
char *g_argv[SIZE];
//保存完整的命令行字符串
char cmd_line[NUM];
//shell运行原理:通过让子进程执行命令,父进程等待&&解析命令
int main()
{
//0. 命令行解释器,一定是一个常驻内存的进程,不退出,所以while循环
while(1)
{
//1. 打印出提示信息
printf("[root@localhost myshell]# ");
fflush(stdout);//刷新缓冲,使printf语句显示,不用'\n'刷新是不想换行
memset(cmd_line,'\0',sizeof cmd_line);
//2. 获取用户的键盘输入[输入的是各种指令和选项:"ls -a -l"]
if(fgets(cmd_line, sizeof cmd_line, stdin) == NULL)
{
//获取失败
continue;
}
cmd_line[strlen(cmd_line)-1] = '\0';//输入时\n也在字符串里,需把\n换掉
//3. 命令行字符串:"ls -a -l" -> "ls" "-a" "-l"
g_argv[0] = strtok(cmd_line," ");//第一次调用,要传入原始字符串
int index = 1;
if(strcmp(g_argv[0],"ls") == 0)//设置颜色
{
g_argv[index++] = "--color=auto";
}
if(strcmp(g_argv[0],"ll") == 0)
{
g_argv[0] = "ls";
g_argv[index++] = "-l";
g_argv[index++] = "--color=auto";
}
while(g_argv[index++] = strtok(NULL," "));//第二次,如果还要解析原始字符串,传入NULL
//4. TODO 内置命令:让父进程自己执行的命令,也叫内建命令
//内建命令本质其实就是shell中的一个函数调用
if(strcmp(g_argv[0],"cd") == 0)//not child execute,father execute
{
//cd 命令不需要子进程执行
if(g_argv[1] != NULL) chdir(g_argv[1]);
continue;
}
//5. fork()
pid_t id = fork();
if(id == 0)//child
{
//printf("下面功能让子进程执行的\n");
execvp(g_argv[0],g_argv);// "ls" "ls -a -l"
exit(1);
}
//father
int status = 0;
pid_t ret = waitpid(id,&status,0);//阻塞式等待
}
}