【Linux】shell的认识和模拟实现

本文介绍了如何编写一个minishell,详细讲解了shell的作用,即作为用户与Linux内核交互的接口,接收并执行用户命令。通过模拟实现一个mini的shell程序,包括打印提示符、获取用户输入、解析命令、创建子进程执行命令以及处理子进程退出。提供的代码示例展示了基本的shell循环和命令执行流程,但不支持复杂的shell特性,如管道和重定向。
摘要由CSDN通过智能技术生成

编写一个minishell

什么是shell

Shell是Linux系统的用户界面,提供了用户与内核进行交互操作的一种接口。它接收用户输入的命令并把它送入内核去执行。是在Linux内核与用户之间的解释器程序,现在Linux通常指/bin/bash解释器来负责向内核翻译以及传达用户/程序指令,shell相当于操作系统的“外壳”

shell都做了什么工作

当我们通过认证进入到Linux系统当中后,操作系统会帮我们运行一个进程-bash , 我们登录后看到的界面就是shell进程,shell会捕获用户的输入命令,并对这些命令进行解析,解析之后就会创建子进程去处理这些命令,执行完毕后shell会再次回到捕获命令的状态,等待用户的再次输入。

请添加图片描述

模拟实现一个mini的shell程序

  • 首先,我们要打印一个提示符一直处于一行的前面,显示当前用户名主机目录等信息,我们这里偷了个懒,直接打印字符串,显示到屏幕。
  • 接着就是获取用户的输入字符串,把输入的字符串保存到一个字符数组里。
  • 然后对这个字符数组进行解析,把命令用分隔符" "拆分开来,保存到指针数组里,完成字符串的解析
  • 接着创建一个子进程,对子进程进行程序替换,让子进程执行相应的命令。
  • 父进程的任务是等待子进程的退出,并判断子进程的退出状态信息,也就是指令的执行情况,并对子进程进行资源回收
  • 最后就是回到第一步再次循环捕获输入的命令。

完整代码实现

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<sys/wait.h>
#define SIZE 256
#define NUM 16
int main() {
    //命令字符串
    char cmd[SIZE];
    //提示符
    const char* cmd_line = "[minishell@CentOS]$";
    //shell循环读取命令执行
    while (1) {
        //初始化获取到的命令字符串
        cmd[0] = 0;
        //让提示符一直打印到前面
        printf("%s", cmd_line);
        //捕获输入的命令到cmd里
        fgets(cmd, SIZE, stdin);
        //获取到的命令字符串最后一个\n去掉
        cmd[strlen(cmd) - 1] = '\0';
        //定义指针数组用来保存解析后的字符串 
        char* args[NUM];
        /
        //解析命令字符串
        args[0] = strtok(cmd, " ");
        int i = 1;
        do {
            args[i] = strtok(NULL, " ");
            if (args[i] == NULL) {
                break;
            }
            ++i;
        } while (1);

        //
        //字符串解析完毕
        //
        //创建子进程并对命令进行处理
        pid_t id = fork();
        if (id < 0) {
            perror("fork error!\n");
            continue;
        }
        if (id == 0) {
            //child  
            //子进程内调用进程替换函数
            
            execvp(args[0], args);
            exit(1);
        }

        //父进程等待子进程处理
        int st;
        pid_t ret = waitpid(id, &st, 0);

        if (WIFEXITED(st) && ret == id) {
            if (WEXITSTATUS(st) == 1) {
                printf("-bash: %s: command not found\n", args[0]);
            }
        }
    }
    return 0;
}

通过对这个shell进行测试,可以运行很多常用的命令,但是和真实的shell还有很多差距,也有很多管道或者重定向等命令不能执行。

请添加图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xiaomage1213888

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值