【问题标题】:Writing my own shell in C, how do I run Unix executables?用 C 编写自己的 shell,如何运行 Unix 可执行文件?
【发布时间】:2012-02-15 13:08:00
【问题描述】:

在我的一门课程中,我们正在编写自己的 shell(基本上是从零开始)。

我们已经编写了一个词法分析器和一个解析器来将输入划分为更容易处理的漂亮“命令”结构。同样,我有一个函数read_command(),它会一次读取一个命令并确定它是什么类型的命令(管道/和/或/简单/等)。

我现在正在尝试编写execute_command(struct command cmd) 函数,它实际上接受命令并运行它。我正在为如何开始实际编写这个函数而苦苦挣扎。

假设我只是得到一个非常简单的cat foo.txt 作为命令。我的命令结构会将它整齐地划分,所以我有一个包含两个单词的单词数组。

现在我想运行带有参数foo.txtcat 可执行文件。我意识到我应该使用$PATH 变量来尝试查找可执行文件,然后使用此参数运行它。

我正在努力解决几个主要问题:

  1. 如何实际搜索命令cat?请记住,该程序使用 C。我可以使用哪些函数来搜索目录?如何使用 PATH 执行此操作?
  2. 当我找到命令cat 时,如何以foo.txt 作为参数运行它?这如何在 C 中完成?

【问题讨论】:

    标签: c shell unix path


    【解决方案1】:

    您将命令字符串拆分为单独的字符串(命令名称、参数),并将它们存储在以空字符结尾的字符指针数组中。然后,您分叉并将命令名称和命令 + 参数传递给execvp(),除非这是禁止的。您最终也将不得不担心管道和 I/O 重定向,但基本思想保持不变。

    char *args[MAXARGS];
    
    args[0] = "cat";
    args[1] = "foo.txt";
    args[2] = 0;
    
    if ((pid = fork()) == 0)
    {
        execvp(args[0], args);
        ...print error...
        exit(1);
        /* execvp() does not return unless there's an error */
    }
    else if (pid < 0)
        ...fork failed...
    else
        ...wait for child to finish - or start other commands, or ...
    

    您可以在真实的 shell 中动态分配 args。如果您必须为执行的程序提供自定义环境,它会变得更加棘手。基本上,您将组装环境的副本,然后在分叉后,将全局 environ 设置为新值 - 但如果新环境包含 PATH 的新值,则会影响通过 @ 搜索命令987654325@。因此,您最终可能会因此编写自己的 execvp() 变体。如果是这样,请从 BSD (MacOS X) 书籍中学习;有一个函数execvP()

     int execvP(const char *file, const char *search_path, char *const argv[]);
    

    它允许您指定要使用的搜索路径,即使您已经修复了环境。最基本的电话是execve();这是execvp() 在幕后使用的(可能通过execv())。

    【讨论】:

      【解决方案2】:
      1. 查看getenv(3) 及其亲属。您可能实际上不需要直接对目录进行任何操作,但如果您这样做,您可以使用opendir(3)readdir(3)closedir(3) 等。
      2. 使用fork(2)execl(3) 或其亲属之一(execve(2) 是基础级 API)。

      手册页本身或简单的谷歌搜索任何这些功能都会出现大量示例来帮助您。

      【讨论】:

      • 您不需要自己处理PATHexecvp 会为你做的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-12-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-11
      • 2011-06-27
      • 1970-01-01
      相关资源
      最近更新 更多