💓博主CSDN主页:麻辣韭菜-CSDN博客💓
⏩专栏分类:http://t.csdnimg.cn/G90eI⏪
🚚代码仓库:Linux: Linux日常代码练习🚚
🌹关注我🫵带你学习更多Linux知识
🔝🔝
目录
一.命令行提示信息
二.获取用户输入的字符串
三.拆解用户输入的字符串
四.子进程程序替换
五.内建命令(内置命令)
想想Xshell的命令解释器,我们在命令行输入ls命令,他的父进程是谁?bash 。根据之前的讲的进程替换,根据这个原理父进程当个监工,让子进程去做一些其他事情。
一.命令行提示信息
我们在Linux在命令行输入各种指令是需要提示行的。如下图
而且这个提示行我们不输入他是一只存在的,那就说明了他是一个无限循环的程序->常驻的进程。
按照上面的这个代码 一直打印如下图,那肯定不行。
int main()
{while(1){//1. 打印出提示信息 [root@localhost myshell]# printf("[root@localhost myshell]# ");fflush(stdout);}return 0;
}
有了提示信息,我们就要获取用户输入指令,如何获取?用fgets获取 用户输入的指令 我们需要建立一个缓冲区来接受和保存。
二.获取用户输入的字符串
#define NUM 1024
//保存完整的命令行字符串
char cmd_line[NUM]; //用来保存用户输入的字符串
int main()
{while(1){//1. 打印出提示信息 [root@localhost myshell]# printf("[root@localhost myshell]# ");fflush(stdout);//初始化缓冲区数组memset(cmd_line, '\0', sizeof cmd_line);//2. 获取用户的键盘输入[输入的是各种指令和选项: "ls -a -l -i"]//如果用户输入错误重新开始if(fgets(cmd_line, sizeof cmd_line, stdin) == NULL){continue;}}return 0;
}
想一想我们在命令行输入各种指令,最后会输入一个回车键,那fgets这个函数也接收到回车键->"\n" 所以我们还需要将回车键设置成"\0"。
#define NUM 1024
//保存完整的命令行字符串
char cmd_line[NUM]; //用来保存用户输入的字符串
int main()
{while(1){//1. 打印出提示信息 [whb@localhost myshell]# printf("[root@localhost myshell]# ");fflush(stdout);//初始化缓冲区数组memset(cmd_line, '\0', sizeof cmd_line);//2. 获取用户的键盘输入[输入的是各种指令和选项: "ls -a -l -i"]//如果用户输入错误重新开始if(fgets(cmd_line, sizeof cmd_line, stdin) == NULL){continue;}cmd_line[strlen(cmd_line)-1] = '\0';}return 0;
}
三.拆解用户输入的字符串
#define NUM 1024
#define SEP " " //定义分割标识符
#define SIZE 64
//保存完整的命令行字符串
char cmd_line[NUM]; //用来保存用户输入的字符串
//保存被打散的字符串
char* g_argv[SIZE];
int main()
{while(1){//1. 打印出提示信息 [root@localhost myshell]# printf("[root@localhost myshell]# ");fflush(stdout);//初始化缓冲区数组memset(cmd_line, '\0', sizeof cmd_line);//2. 获取用户的键盘输入[输入的是各种指令和选项: "ls -a -l -i"]//如果用户输入错误重新开始if(fgets(cmd_line, sizeof cmd_line, stdin) == NULL){continue;}cmd_line[strlen(cmd_line)-1] = '\0';//3.命令行字符串解析g_argv[0] = strtok(cmd_line,SEP); //第一次调用,要传入原始字符串int index = 1;while(g_argv[index++] = strtok(NULL,SEP));}
四.子进程程序替换
#define NUM 1024
#define SEP " " //定义分割标识符
#define SIZE 64
//保存完整的命令行字符串
char cmd_line[NUM]; //用来保存用户输入的字符串
//保存被打散的字符串
char* g_argv[SIZE];
int main()
{while(1){//1. 打印出提示信息 [root@localhost myshell]# printf("[root@localhost myshell]# ");fflush(stdout);//初始化缓冲区数组memset(cmd_line, '\0', sizeof cmd_line);//2. 获取用户的键盘输入[输入的是各种指令和选项: "ls -a -l -i"]//如果用户输入错误重新开始if(fgets(cmd_line, sizeof cmd_line, stdin) == NULL){continue;}cmd_line[strlen(cmd_line)-1] = '\0';//3.命令行字符串解析g_argv[0] = strtok(cmd_line,SEP); //第一次调用,要传入原始字符串int index = 1;while(g_argv[index++] = strtok(NULL,SEP));//4.创建子进程pid_t id = fork();if(id <0) { perror("fork");exit(1);}if(id == 0){printf("下面功能让子进程进行的\n");execvp(g_argv[0], g_argv); // ls -a -l -iexit(1);}//fatherint status = 0;pid_t ret = waitpid(id, &status, 0);if(ret > 0) printf("exit code: %d\n", WEXITSTATUS(status));}}
运行没问题 这就完了吗?还没有 内建命令。
仔细看会发现 我们的cd命令没用啊,进入上级路径压根没有变化,那是因为子进程收到cd字这个字符串,是子进程的路径在发生变化运行完毕后了退出了,父进程压根就没有变还是当前路径。
五.内建命令(内置命令)
//5.内置命令, 让父进程(shell)自己执行的命令,我们叫做内置命令,内建命令//内建命令本质其实就是shell中的一个函数调用if(strcmp(g_argv[0], "cd") == 0) {if(g_argv[1] != NULL) chdir(g_argv[1]);//chdir 可以帮我们自动切换到指定路径continue;}
//这段代码放在字符串分割下面
为什么要程序替换,说简单点场景需要,举一个简单的例子:你在抖音上看直播,这个直播间在卖东西,上链接叫你赶紧拍,你在拍东西过程中,直播间你是没有退出的,但是你下单确认支付的那一瞬间,这时另一个进程就开始了 收你钱。