【Linux】进程控制-五、制作一个简易的shell:

        shell就是一个命令解释器,它互动式地解释和执行用户输入的命令;当有命令要执行时,shell创建子进程让子进程去执行命令,而shell只需要等待子进程执行完退出即可。

具体步骤:

  1. 获取终端输入的命令
  2. 解析命令
  3. 创建子进程
  4. 对子进程进行程序替换
  5. 等待子进程执行完后退出
#include <stdio.h>
#include <pwd.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#define LEN 1024 // 设置命令最大长度
#define NUM 32   // 命令拆分后的最大个数
int main()
{
	char cmd[LEN];     // 存储命令
	char* myargv[NUM]; // 存储命令拆分后的结果
	char hostname[32]; // 主机名
	char pwd[128];     // 当前目录
	while (1) {
		//获取命令提示信息
		struct passwd* pass = getpwuid(getuid());
		gethostname(hostname, sizeof(hostname) - 1);
		getcwd(pwd, sizeof(pwd) - 1);
		int len = strlen(pwd);
		char* p = pwd + len - 1;
		while (*p != '/') {
			p--;
		}
		p++;
		
		// 打印命令提示信息
		printf("[%s@%s %s]$ ", pass->pw_name, hostname, p);
		
		// 读取命令
		fgets(cmd, LEN, stdin);
		cmd[strlen(cmd) - 1] = '\0';
		
		// 拆分命令
		myargv[0] = strtok(cmd, " ");
		int i = 1;
		while (myargv[i] = strtok(NULL, " ")) {
			i++;
		}
		pid_t child = fork(); // 创建子进程执行命令
		if (child == 0) {
			//child
			execvp(myargv[0], myargv); // 子进程进行程序替换
			exit(1); // 替换失败的退出码设置为1
		}
		// 父进程 / myshell
		int status = 0;
		pid_t myshell = waitpid(child, &status, 0); // shell等待子进程退出
		if (myshell > 0) {
			printf("exit code:%d\n", WEXITSTATUS(status)); // 打印子进程的退出码
		}
	}
	return 0;
}

补充:

  •         当自己的命令解释器(myshell)运行起来后,每次子进程执行完任务退出后都会打印退出码,可以以此来分辨自己写的和操作系统的命令解释器。
  •         我们自己手写的shell总体上是有一些缺陷的,在读取终端输入的时候会直接读取,方向键和删除键也是会被读进去的(因为方向键在终端中通常被表示为一系列的字节序列),如果想让其发挥功能就得要做对其进行特殊处理。
上一篇:linux系统中docker镜像创建、导入导出和执行


下一篇:Python从入门到精通秘籍十六