蚊章汇 - Hello World
type: channel
link: https://linuxcn.bwsl.wang/tag/Hello+World/
items: Linux 下“Hello World”的幕后发生了什么

Linux 下“Hello World”的幕后发生了什么
type: item
date: 2023-08-29T22:36:53+08:00
description: 今天我在想 —— 当你在 Linux 上运行一个简单的 “Hello World” Python 程序时，发生了什么，就像下面这个？print("hello world") 这就是在命令行下的情况：$ python3 hello.py hello world 但是在幕后，实际上有更多的事情在发生。我将描述一些发生的情况，并且（更重要的是）解释一些你可以用来查看幕后情况的工具。我们将用 readelf、strace、ldd、debugfs、/proc、ltrace、dd 和 stat。我不会讨论任何只针对 Python 的部分 —— 只研究一下当你运行任何动态链接的可执行文件时发生的事情。0、在执行 execve 之前要启动 Python 解释器，很多步骤都需要先行完成。那么，我们究竟在运行哪一个可执行文件呢？它在何处呢？1、解析 python3 hello.pyShell 将 python3 hello.py 解析成一条命令和一组参数：python3 和 ['hello.py']。在此过程中，可能会进行一些如全局扩展等操作。举例来说，如果你执行 python3 *.py ，Shell 会将其扩展到 python3 hello.py。2、确认 python3 的完整路径现在，我们了解到需要执行 python3。但是，这个二进制文件的完整路径是什么呢？解决办法是使用一个名为 PATH 的特殊环境变量。自行验证：在你的 Shell 中执行 echo $PATH。对我来说，它的输出如下：$ echo $PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin 当执行一个命令时，Shell 将会依序在 PATH 列表中的每个目录里搜索匹配的文件。对于 fish（我的 Shell），你可以在 这里 查看路径解析的逻辑。它使用 stat 系统调用去检验是否存在文件。自行验证：执行 strace -e stat bash，然后运行像 python3 这样的命令。你应该会看到如下输出：stat("/usr/local/sbin/python3", 0x7ffcdd871f40) = -1 ENOENT (No such file or directory) stat("/usr/local/bin/python3", 0x7ffcdd871f40) = -1 ENOENT (No such file or directory) stat("/usr/sbin/python3", 0x7ffcdd871f40) = -1 ENOENT (No such file or directory) stat("/usr/bin/python3", {st_mode=S_IFREG|0755, st_size=5479736, ...}) = 0 你可以观察到，一旦在 /usr/bin/python3 找到了二进制文件，搜索就会立即终止：它不会继续去 /sbin 或 /bin 中查找。对 execvp 的补充说明如果你想要不用自己重新实现，而运行和 Shell 同样的 PATH 搜索逻辑，你可以使用 libc 函数 execvp（或其它一些函数名中含有 p 的 exec* 函数）。3、stat 的背后运作机制你可能在思考，Julia，stat 到底做了什么？当你的操作系统要打开一个文件时，主要分为两个步骤：它将 文件名 映射到一个包含该文件元数据的 inode它利用这个 inode 来获取文件的实际内容stat 系统调用只是返回文件的 inode 内容 —— 它并不读取任何的文件内容。好处在于这样做速度非常快。接下来让我们一起来快速了解一下 inode。（在 Dmitry Mazin 的这篇精彩文章 《磁盘就是一堆比特》中有更多的详细内容）$ stat /usr/bin/python3 File: /usr/bin/python3 -> python3.9 Size: 9 Blocks: 0 IO Block: 4096 symbolic link Device: fe01h/65025d Inode: 6206 Links: 1 Access: (0777/lrwxrwxrwx) Uid: ( 0/ root) Gid: ( 0/ root) Access: 2023-08-03 14:17:28.890364214 +0000 Modify: 2021-04-05 12:00:48.000000000 +0000 Change: 2021-06-22 04:22:50.936969560 +0000 Birth: 2021-06-22 04:22:50.924969237 +00…