从零开始写 OS 内核 - 运行 shell

navi -
从零开始写 OS 内核 - 运行 shell
系列目录序篇准备工作BIOS 启动到实模式GDT 与保护模式虚拟内存初探加载并进入 kernel显示与打印全局描述符表 GDT中断处理虚拟内存完善实现堆和 malloc第一个内核线程多线程运行与切换锁与多线程同步进入用户态进程的实现系统调用简单的文件系统加载可执行程序键盘驱动运行 shellshell 命令行

这是本系列最后一篇了,为这个 OS 加一个用户界面 shell,这算是 Linux 编程中最入门的经典教科书项目了,网上也可以找到很多小教程。这里也不多浪费时间,仅展示一下它的核心部分:

void print_shell() {
  printf("bash> ");
}
while (1) {
  print_shell();
  while (1) {
    int32 c = read_char();
    if (c == '\n') {
      run_program();
      break;
    } else if (c < 128) {
      printf(c);
    }
}

shell 本质上只是一个壳,正如它的名字,它提供一个和用户交互的命令行界面,不停地等待用户输入字符并反馈打印出来;一旦用户按下了回车键,那么表示需要运行之前输入的命令行,这在 run_program 函数里实现:

void run_program() {
  // Parse cmd and get program and args.
  // ..
  
  // (fork + exec) new prgoram.
  int32 pid = fork();
  if (pid < 0) {
    printf("fork failed");
  } else if (pid > 0) {
    // parent
    int32 status;
    wait(pid, &status);
  } else {
    // child
    int32 ret = exec(program, args_index, (char**)args);
    exit(ret);
  }
}

这里首先 parse 用户刚才敲回车之前输入的命令行字符串,解析出可执行程序名,以及参数。然后就是经典的 fork + exec 组合,运行这个程序。程序名和参数都会被传递到 exec 系统调用的处理函数 process_exec,那里会从磁盘上读取该用户可执行文件并执行。这里命令行输入的程序名都很简单,也没有什么路径的概念,因为我们使用的 naive_fs 只有一层结构,所有文件全在顶层,所以直接用文件名就可以了。

fork 后的 parent 进程会调用 wait 系统调用阻塞等待 child 结束。关于 wait 和 exit 这组系统调用,我没有在这个系列里详细展开,读者可以自行阅读源码。

kernel 启动任务

我们来看一下这个 kernel 启动的过程,后台开启了哪些任务,以及如何最终进入 shell 界面。本节代码在 src/task/scheduler.c 中。

首先启动 kernel main 进程/线程,它是最原始的祖先进程,会做这几件事情:

创建 kernel 资源清理线程 kernel_clean_thread,这是一个后台线程,我用它专门做 process/thread 的资源最终回收工作,平时它是睡眠的,只有当有 process/thread 消亡需要清理时会唤醒;创建 init 进程以及线程 kernel_init_thread,它会成为第一个用户进程,运行用户程序 init;在 init 程序里,我创建了 shell 进程,然后 init 进程就进入阻塞;在实际的 Linux 系统中,真实的 init 进程应该还需要作为一个后台任务,专门负责等待接管回收所有的孤儿进程(Orphan Process),我这里就不实现了,感兴趣的同学可以查资料学习一下;上述两项工作完成后,这个原始线程就变成了 cpu_idle 线程,所谓 cpu idle 就是一条指令 hlt,它是在系统真的没有任何任务需要运行的情况才会被运行,它会使 CPU 进入一个低功耗运转的状态;

当然以上只是我个人启动 kernel 任务的实现方式,和 Linux 有点像但并不完全一致;这其实很随意的,这毕竟只是我们自己写的一个玩具 OS 而已,Linux 的方式也并非标准答案,只需要让系统各个重要的任务成功运行并调度起来就可以了。

特别申明:本文内容来源网络,版权归原作者所有,如有侵权请立即与我们联系(cy198701067573@163.com),我们将及时处理。
上一篇: Linux之wc命令

Tags 标签

操作系统cshell进程linux

扩展阅读

加个好友,技术交流

1628738909466805.jpg