Shell如何执行程序?


11

如果我使用gcc编译程序,并尝试从bash shell执行该程序,那么bash执行该程序的确切顺序是什么?

我知道fork()execve()loaderdynamic linker(和其他东西)都参与,但也有人给的步骤的确切顺序和一些适合阅读的参考?

编辑:

从答案看,这个问题似乎暗示了许多可能性。我想缩小到一个简单的情况:

(test.c只是打印hello world)

$ gcc test.c -o test
$ ./test

在上述情况(./test)中将采取哪些步骤,特别是将bash启动程序与某个子进程相关联,进行加载,链接等?


4
我邀请您阅读lwn.net/Articles/630727
cuonglm

3
为什么不尝试`strace bash -c'test'?
Sergiy Kolodyazhnyy 2015年

2
对于OP来说,像样的操作系统教科书似乎是不错的资源。试图通过问像这样的单个问题来学习操作系统的工作方式,可能不太会有生产效率。
Barmar

看到一个最小的外壳示例会很有用:brennan.io/2015/01/16/write-a-shell-in-c
jinawee

Answers:


5

好的,确切的顺序可能会有所不同,因为可能会有一个shell别名或函数,在实际程序执行之前先对其进行扩展/解释,然后再对合格文件名(/usr/libexec/foo)和将在所有目录中查找的东西进行区别的PATH环境变量(仅foo)。此外,执行的细节可能使问题复杂化,因为foo | bar | zot需要壳更多的工作(一些号码fork(2)dup(2)以及,当然pipe(2),其他系统调用中),而像exec foo作为外壳仅仅用替换本身要少得多的工作新程序(即,不是fork)。进程组(尤其是前台进程组,其所有PID都吃掉)也很重要SIGINT当某人开始在Ctrl+上进行混搭时C,以及该作业是否将在后台运行,在监视下(foo &)或在后台运行(被忽略foo & disown)。I / O重定向详细信息也会改变情况,例如,如果标准输入被shell(foo <&-)关闭,或者文件是否以stdin(foo < blah)打开。

strace或类似内容将有助于您了解在此过程中进行的特定系统调用,并且每个调用都应有手册页。适当的系统级阅读将是史蒂文斯的“ UNIX环境中的高级编程”中的任何章节,而一本Shell书籍(例如,“从Bash到Z Shell”)将更详细地介绍事物的外壳方面。


我编辑了问题,以缩小为一个简单的案例
杰克

1

假设已经运行了一个教科书示例外壳程序(为了代码清晰)(因此完成了动态链接器),那么您提到的命令将要求外壳程序进行以下系统调用:

  • 读取:在这种情况下,获取下一个命令gcc
  • fork:需要两个过程,我们假设父级为pid 500,子级为例。
  • 父级将调用wait(501),而子级将调用exec。此时,shell不再在pid 501上运行。gcc进行了许多系统调用,包括至少打开,关闭,读取,写入,chmod,fork,exec,wait和exit。
  • 当gcc调用退出时,等待将返回,调用write以显示提示,并且该过程将重复。

当然,更复杂的命令会使此基本序列更加复杂。基本并发症的两个简单示例是基本io重定向,其中在fork与exec和后台进程之间插入了一个打开,关闭,重复的序列,跳过了等待(并将另一个等待添加到了sigchld处理程序)。


小添加:问题询问有关加载和动态链接。所有静态链接的代码(即实际上包含在程序文件中的代码)在启动程序之前由内核完成。动态加载的库(即单独的文件)在启动main()之前由程序本身处理。此代码由gcc自动添加。
斯蒂格·海默

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.