从命令行到Shell Lab

简单的Linux命令

安装好ubuntu桌面版的虚拟机以后,现在让我们打开Linux终端 :

现在开始敲命令吧(由gpt生成)

  1. pwd - 显示当前工作目录的路径。这可以帮助你确定你当前在哪个目录下工作。

    pwd
  2. ls - 列出当前目录下的文件和子目录。

    ls
  3. cd - 切换目录。你可以使用cd命令进入其他目录。

    cd /path/to/directory
  4. mkdir - 创建新目录。

    mkdir new_directory
  5. touch - 创建新文件。

    touch new_file.txt
  6. rm - 删除文件或目录。请谨慎使用,因为这是一个有风险的命令。

    rm file.txt
  7. cp - 复制文件或目录。

    cp file.txt /path/to/destination
  8. mv - 移动文件或目录,也可用于重命名文件。

    mv file.txt new_name.txt

以上的内容是最基本的命令行,我现在再看一个我们之后会使用的命令

  1. echo- 输出输入的参数

    echo ICS

此外你可以查看面试常考的Linux命令


从命令行到Shell Lab

我们敲命令的这个终端运行的其实就是一个shell程序,什么是shell呢?我们不妨回到前面这张图

先并不给出明确的shell的定义,但可以综合前面的内容看到一些shell的特性

  1. 首先shell接受命令的输入,执行程序,实现某些功能。

  2. 其次shell是运行在OS上的程序,shell会调用OS提供的syscall。

echo命令为例子

  1. shell会解释用户输入的命令,分析出命令名称(echo)和参数(ICS

  2. shell通过syscall向OS发出请求,以执行echo(echo也是一个运行在OS上的应用程序)。

  3. 执行echo程序,echo 调用syscall,然后OS会负责将指定的文本输出到终端。

Definition 3 shell syscall

写一个最简单的shell

现在让我们在Linux的命令行用C语言写一个最简单的支持echoexit 命令的shell

1. 建议先学习C语言或者阅读下小节必要的C语言

2. 如果你是Mac或者Win的WSL的使用者,可以直接命令行完成下面的步骤

  1. 在终端,创建shell.c

    vim shell.c
  2. 在vim里写(复制)下面的代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

#define MAX_COMMAND_LENGTH 100

int main() {
    char command[MAX_COMMAND_LENGTH];
    while (1) {
        printf("$ ");
        fgets(command, sizeof(command), stdin);
        // 去除命令末尾的换行符
        command[strcspn(command, "\n")] = '\0';

        if (strcmp(command, "exit") == 0) {
            // 如果用户输入的是"exit"命令,退出shell
            break;
        } else if (strncmp(command, "echo ", 5) == 0) {
            // 如果用户输入的是"echo"命令
            // 创建子进程执行命令
            pid_t child_pid = fork();
            if (child_pid == 0) {
                // 子进程中执行echo命令
                execl("/bin/echo", "echo", command + 5, NULL);
                // 如果execl执行失败,打印错误消息
                perror("exec");
                exit(1);
            } else if (child_pid > 0) {
                // 等待子进程结束
                wait(NULL);
            } else {
                perror("fork");
            }
        } else {
            // 对于其他不支持的命令,打印错误消息
            printf("Unsupported command: %s\n", command);
        }
    }

    return 0;
}
  1. 退出vim,终端gcc编译shell.c

gcc -o shell shell.c

​ 这个命令的含义是:

  • gcc:这是GNU编译器的命令。

  • -o shell:这部分指定了输出文件的名称,即编译后生成的可执行文件的名称将是 shell

  • shell.c:这是要编译的源文件的名称,C程序文件名为 shell.c

  1. 终端执行shell程序

./shell

让我们来看看最终的效果

好的,这个shell实现echoexit这两个功能,如果我不使用 exit 命令,这个小shell将一直执行下去。虽然

  1. 你可能还不能完全看懂上面shell.c的逻辑

  2. 还不了解forkexecl这些syscall函数的使用

  3. 还不太了解Linux的文件路径,比如execl("/bin/echo", "echo", command + 5, NULL);这里面echo的执行文件在/bin/echo

但是现在的你已经开始了系统编程(system programming) !

在这学期,你将更深入地学习系统知识,并最终在Shell Lab写出一个支持许多命令并考虑到许多问题(如并发)的Unix Shell!

Last updated