IT袋

当前位置:主页 > 经验教程 > 系统教程 >

Linux

Linux 下“Hello World”的幕后发生了什么(9)

时间:2023-09-17 20:02:06 来源:IT袋 作者:苏晓敏
导读:Linux,strace 不同,我总是不完全确定 ltrace 是否准确地报告了库调用。但在这个情况下,它似乎有效。并且,如果我们查阅cpython 的源代码,它似乎在一些地方确

Linux

strace不同,我总是不完全确定ltrace是否准确地报告了库调用。但在这个情况下,它似乎有效。并且,如果我们查阅cpython 的源代码,它似乎在一些地方确实调用了write函数,所以我倾向于相信这个结果。

什么是 libc?

我们刚刚提到,Python 调用了 libc 中的write函数。那么,libc 是什么呢?它是 C 的标准库,负责许多基本操作,例如:

  • malloc分配内存
  • 文件 I/O(打开/关闭文件)
  • 执行程序(像我们之前提到的execvp
  • 使用getaddrinfo查找 DNS 记录
  • 使用pthread管理线程

在 Linux 上,程序不一定需要使用 libc(例如 Go 就广为人知地未使用它,而是直接调用了 Linux 系统调用),但是我常用的大多数其他编程语言(如 node、Python、Ruby、Rust)都使用了 libc。我不确定 Java 是否也使用了。

你能通过在你的二进制文件上执行ldd命令,检查你是否正在使用 libc:如果你看到了libc.so.6这样的信息,那么你就在使用 libc。

为什么 libc 重要?

你也许在思考 —— 为何重要的是 Python 调用 libc 的write函数,然后 libc 再调用write系统调用?为何我要着重提及libc是调用过程的一环?

我认为,在这个案例中,这并不真的很重要(根据我所知,libc 的write函数与write系统调用的映射相当直接)。

然而,存在不同的 libc 实现,有时它们的行为会有所不同。两个主要的实现是 glibc(GNU libc)和 musl libc。

例如,直到最近,musl 的getaddrinfo并不支持 TCP DNS,这是一篇关于这个问题引发的错误的博客文章。

关于 stdout 和终端的小插曲

在我们的程序中,stdout(1文件描述符)是一个终端。你可以在终端上做一些有趣的事情!例如:

  1. 在终端中运行ls -l /proc/self/fd/1。我得到了/dev/pts/2的结果。
  2. 在另一个终端窗口中,运行echo hello > /dev/pts/2
  3. 返回到原始终端窗口。你应会看到hello被打印出来了!

暂时就到这儿吧!

希望通过上文,你对hello world是如何打印出来的有了更深的了解!我暂时不再添加更多的细节,因为这篇文章已经足够长了,但显然还有更多的细节可以探讨,如果大家能提供更多的细节,我可能会添加更多的内容。如果你有关于我在这里没提到的程序内部调用过程的任何工具推荐,我会特别高兴。

我很期待看到一份 Mac 版的解析

相关阅读