南京大学 操作系统 (JYY) 学习笔记:可执行文件、链接器与 Shebang 的彩蛋
写在前面这是本系列的第十篇。我们已经知道进程从execve后的初始状态开始可以通过mmap改变自己的地址空间通过fork创建新的进程。有了系统调用和libc我们真的可以实现“任何程序”了。但在此之前我们一直默认了编译器工具链gcc/ld可以奇迹般地帮我们实现从高级语言到可执行文件的翻译。今天是时候“打开”这个黑盒了什么是可执行文件静态链接到底做了什么以及大名鼎鼎的#!(Shebang) 究竟藏着怎样的内核魔法课前小插曲Testkit 的修复与反思关于之前的 Testkit如果工程实现里有多个.c文件执行顺序和快照机制往往让人摸不着头脑。没听懂没关系以后有机会让豆包/Kimi 详细教一下怎么用。核心回顾操作系统的对象进程状态机。管理 API:fork,execve,exit。连续的内存段可以被看作一个能在进程间共享、或映射到文件的对象。管理 API:mmap,munmap,mprotect。什么是可执行文件学习操作系统前那个鼠标“双击可以弹出窗口的东西”。学习操作系统后它是一个操作系统中的对象文件。它是一个字节序列可以用十六进制编辑器直接编辑。它是一个描述了状态机初始状态的数据结构听起来开始让人头秃了。ELF (Executable and Linkable Format)在《计算机系统基础》中我们已经接触过 ELF可执行和可链接格式。这是一种标准的文件格式用于存储可执行文件、目标文件和共享库。我们常用binutils中的工具如readelf和objdump来查看其中的信息。如果想用更现代、更友好的工具可以尝试elfcat。无论工具怎么变可执行文件在底层永远只是一段字节序列。可执行文件进程初始状态的描述根据 AMD64 架构的圣经《System V ABI》规范操作系统只规定了部分寄存器和栈的初始状态而其他的状态主要是内存布局全权由可执行文件来指定。一个合格的可执行文件需要包含什么假设没有动态链接基本信息版本、体系结构。内存布局哪些段放代码.text哪些段放数据.data,.bss。其他信息调试信息、符号表等。极简主义可执行文件其实不需要那么复杂只要满足最基本的要求我们甚至可以手捏一个最小的可执行文件一个合法的头Magic Number7f 45 4c 46也就是\x7fELF。一段蹦床代码Trampoline Code。# 最小的 ELF 实验用 Python 打印字节流即可生成 a.outhex_data 457f 464c 0102 0001 0000 0000 0000 0000 0002 003e 0001 0000 0078 0040 0000 0000 0040 0000 0000 0000 0000 0000 0000 0000 0000 0000 0040 0038 0001 0000 0000 0000 0001 0000 0007 0000 0078 0000 0000 0000 0078 0040 0000 0000 0000 0000 0000 0000 0007 0000 0000 0000 0007 0000 0000 0000 1000 0000 0000 0000 3c6a 3158 0fff 0005 用strace运行它你会发现它确实能被execve成功加载然后下一秒直接exit(0)rootLAPTOP-GT06V0GS:/mnt/d/CSLab/osCourse/lec10/elf-play# strace ./a.outexecve(./a.out,[./a.out], 0x7fff138033d0 /*36vars */)0exit(0)? exited with0和 ELF 搏斗的每一年ELF 是一个经典且极其稳固的设计。E ExecutableL Linkable。它统一了工具链甚至连 Core Dump核心转储用的也是 ELF 格式。但是它也是折磨历届 CS 学生的元凶同学 A期末复习看吐了。老师 A第一次打开 PPT 真的有点吐血的感觉。老师 C (JYY 自己)太好了以后再也不用教了为什么 ELF 这么难懂反思一下ELF 根本不是一个“人类友好”的数据结构描述。为什么不用 JSON因为为了极致的加载性能和空间利用率ELF 彻底违背了可读性信息局部性原则。它到处都是 offset偏移量几乎是让你直接去大脑里人肉解析一棵内存里的树当你听到“程序头表”、“节头表”看到隐晦的R_X86_64_32标记和无尽的指针时人类的大脑是抗拒的。顺带一提Core Dump 的本质Segmentation fault (core dumped)—— 为什么叫“核心转储”地狱笑话今天的 core dump 就是一个 ELF 文件。它的本质是操作系统在程序崩溃的瞬间拍下的一张“状态快照” (内存 寄存器)。Everything is a state machine如果配合ulimit -c unlimited生成 Core Dump再用 GDB 挂载你可以精确查看到程序死前的遗言。想要不仅能看还能让状态机“后退”可以使用CRIU工具。在智能 Agent 时代这类工具可以完美实现复杂应用状态的冻结与恢复。重新设计Funny Little Executable (FLE)既然 ELF 不当人那我们就自己设计一个对人类直接可读的可执行文件格式FLE。核心设计思路越“平坦”越容易理解。所有需要的信息都立即可见不要用指针跳来跳去。回归链接和加载的核心概念代码、符号、重定位。FLE 的三要素代码 (emoji1)符号 (emoji2)重定位 (emoji3)凑齐这三要素我们就可以完成链接到加载的全流程这就是 DSL (Domain Specific Language领域特定语言) 的魅力。做了减法去掉了不必要的复杂特性反而能让人更专注底层的本质。rootLAPTOP-GT06V0GS:/mnt/d/CSLab/osCourse/lec10/fle/demo# make# 编译阶段将 .c 编译成自定义的 .fle (目标文件)./cc-Wall-g-Osfoo.c-ofoo.o...# 链接阶段自定义的 ld 将多个 .fle 合并成最终的 hello 可执行文件./ld foo.fle libc.fle main.fle-ohello rootLAPTOP-GT06V0GS:/mnt/d/CSLab/osCourse/lec10/fle/demo# ./helloMessage: Hello World!... rootLAPTOP-GT06V0GS:/mnt/d/CSLab/osCourse/lec10/fle/demo# echo $?42从源码到加载全流程拆解1. 预编译 - 编译 (.c-.s)预处理:处理#include(其实就是无情的 Ctrl-C Ctrl-V) 和宏替换。编译:将“高级状态机” (C语言) 翻译成“低级状态机” (汇编)最终生成带标注的指令序列。2. 汇编 (.s-.o)将汇编指令打包成 sections (.text,.data,.bss等)。为每个 section 记录核心三要素代码字节序列、符号标记当前位置、重定位暂时不能确定的地址留给链接器填空。3. 静态链接 (.o-a.out)合并所有目标文件的 sections。把代码“平铺”成一整块字节序列。确定所有全局符号的绝对物理地址。解析全部重定位填空最终得到一个可以直接运行的可执行文件。4. 加载 (Loader)把生成的“字节序列”用mmap搬到内存。设置好寄存器和 PC开始运行# 极简版加载器伪代码memmmap.mmap(fileno-1,lengthlen(bs),protmmap.PROT_READ|mmap.PROT_WRITE|mmap.PROT_EXEC,flagsmmap.MAP_PRIVATE|mmap.MAP_ANONYMOUS,)mem.write(bs)mem.flush()call_pointer(mem,fle[symbols][_start])操作系统内核与 Shebang (#!) 的浪漫彩蛋加载器其实是操作系统内核实现的一部分。当你调用execve(path, argv, envp)时内核Linux 中的binfmt_elf.c会亲自解析可执行文件扫描PT_LOAD段并完成内存映射。但是等等运行程序的两种方法/bin/ls(这是一个标准的 ELF 二进制文件)./a.py(这明明是个纯文本啊操作系统怎么懂 Python)Shebang 机制的内核魔术这是 UNIX 给程序员留下的最浪漫的彩蛋对#注释的“妙用”。如果一个文本文件的第一行是#!A B C操作系统在execve尝试加载它时会发现开头的 Magic Number 不是 ELF 的\x7fELF而是#!(十六进制为0x23 0x21)。此时内核binfmt_script.c会立刻心领神会把执行命令偷偷狸猫换太子转换为execve(A, [A, B C, any_file], envp)/* Linux 内核源码片段检查是否以 #! 开头 */if((bprm-buf[0]!#)||(bprm-buf[1]!!))return-ENOEXEC;...fileopen_exec(i_name);这就是为什么你在 Python 脚本的第一行写上#!/usr/bin/env python3后这个普通的文本文件就拥有了像二进制程序一样直接运行的魔法。rootLAPTOP-GT06V0GS:/mnt/d/CSLab/osCourse/lec10/shebang# ./goodargv[0]A argv[1]B C argv[2]./good rootLAPTOP-GT06V0GS:/mnt/d/CSLab/osCourse/lec10/shebang# ./bad-bash: ./bad:..: bad interpreter: Permission denied计算机系统里没有魔法所有的神奇现象背后都是一行行清晰可查的 C 语言代码

相关新闻

LangGraph 工作流:权限日志没搞定,Agent 上线就崩?

LangGraph 工作流:权限日志没搞定,Agent 上线就崩?

聊《同样是LangGraph,为什么有的能上线、有的只能演示?》之前,先说一句实在的:别急着背概念,先看它在真实项目里到底解决什么问题。摘要最近大模型应用从 Demo 转向权限、日志和可观测,这个趋势背后是团队对…

2026/7/29 0:38:36 阅读更多 →
万字图文盘点RAG常见的100个核心概念:前 30 个

万字图文盘点RAG常见的100个核心概念:前 30 个

很多同学看了十几篇 RAG 教程,Embedding、Chunk、向量数据库、BM25 单独都认识,连起来却分不清谁先谁后。 因为 RAG 不只是接个向量数据库。前面要处理文档,后面要排序结果、控制上下文,任何一环出问题,答案都会偏。 …

2026/7/29 0:38:36 阅读更多 →
Linux提权实战:从SUID、Capabilities到内核漏洞的系统化攻防指南

Linux提权实战:从SUID、Capabilities到内核漏洞的系统化攻防指南

1. 项目概述:从靶机到实战的提权思维构建最近在VulnHub上通关了几个经典的Linux靶机,发现一个非常有意思的现象:很多初学者在拿到一个低权限shell后,往往会陷入迷茫,不知道下一步该往哪里走。他们可能知道一些零散的提…

2026/7/29 0:38:36 阅读更多 →

最新新闻

KEYSIGHT是德科技 E8362C PNA系列20 GHz高性能微波矢量网络分析仪

KEYSIGHT是德科技 E8362C PNA系列20 GHz高性能微波矢量网络分析仪

KEYSIGHT(原Agilent)E8362C是一款PNA系列20 GHz高性能微波矢量网络分析仪,依托是德科技40年的微波测量技术积累,在测试速度、动态范围和功能扩展性上具备行业标杆表现,广泛用于射频、微波器件的高精度参数测试场景。核…

2026/7/29 0:47:39 阅读更多 →
求职补贴1500元怎么发到位:就业SaaS系统通知触达+过程追踪3步走

求职补贴1500元怎么发到位:就业SaaS系统通知触达+过程追踪3步走

摘要:2026届困难高校毕业生一次性求职补贴1500元/人已全面启动申领,覆盖7类困难群体,申领窗口集中在7月至8月。就业中心面临的痛点不是学生不需要补贴,而是手工通知手动追踪的模式在暑期攻坚期难以穿透到每个符合条件的学生。就业…

2026/7/29 0:47:39 阅读更多 →
4G/5G布控球接入国标GB28181视频监控平台EasyCVR:应急指挥现场画面秒级回传的实战方案

4G/5G布控球接入国标GB28181视频监控平台EasyCVR:应急指挥现场画面秒级回传的实战方案

当突发事件发生时,指挥中心的第一反应永远是:"现场画面传回来了吗?“传统方案从架设设备、调试网络、到画面回传,少则半小时,多则数小时。而5G布控球EasyCVR的组合,真正实现了"到现场即开即传”—…

2026/7/29 0:47:39 阅读更多 →
开源Modbus调试工具终极指南:3步解决工业自动化通讯难题

开源Modbus调试工具终极指南:3步解决工业自动化通讯难题

开源Modbus调试工具终极指南:3步解决工业自动化通讯难题 【免费下载链接】OpenModScan Open ModScan is a Free Modbus Master (Client) Utility 项目地址: https://gitcode.com/gh_mirrors/op/OpenModScan 面对复杂的工业设备通讯调试,你是否还在…

2026/7/29 0:46:38 阅读更多 →
物联网低功耗设备电池寿命优化方案

物联网低功耗设备电池寿命优化方案

1. 不可充电电池的寿命挑战与优化思路在物联网传感器节点、便携式医疗设备等低功耗应用场景中,不可充电的初级电池(如锂锰纽扣电池)面临着严峻的寿命挑战。这类设备通常需要持续工作5-10年,但同时又存在周期性的大电流脉冲需求&am…

2026/7/29 0:46:38 阅读更多 →
基于YOLOv5的中国象棋AI辅助工具实践指南:解决传统棋局分析难题的完整解决方案

基于YOLOv5的中国象棋AI辅助工具实践指南:解决传统棋局分析难题的完整解决方案

基于YOLOv5的中国象棋AI辅助工具实践指南:解决传统棋局分析难题的完整解决方案 【免费下载链接】VinXiangQi Xiangqi syncing tool based on Yolov5 / 基于Yolov5的中国象棋连线工具 项目地址: https://gitcode.com/gh_mirrors/vi/VinXiangQi 中国象棋爱好者…

2026/7/29 0:46:38 阅读更多 →

日新闻

【RT-DETR多模态创新改进】CVPR 2025 | 独家特征融合创新改进篇 | 引入RLAB残差线性注意力模块,有效融合并强调多尺度特征,多种改进点,适合红外与可见光融合目标检测任务,有效涨点

【RT-DETR多模态创新改进】CVPR 2025 | 独家特征融合创新改进篇 | 引入RLAB残差线性注意力模块,有效融合并强调多尺度特征,多种改进点,适合红外与可见光融合目标检测任务,有效涨点

一、本文介绍 🔥本文在RT-DETR多模态融合目标检测中引入RLAB残差线性注意力模块,可在不同模态特征交互阶段进行多次残差细化,使可见光、红外等特征在尺度、语义和空间位置上更好对齐;随后将细化特征与解码器输出拼接并生成Q、K、V,通过线性注意力自适应强化关键通道、目…

2026/7/29 0:00:23 阅读更多 →
AI编程系列02:合并知识功能,给 AI 问数和 RAG 场景打基础

AI编程系列02:合并知识功能,给 AI 问数和 RAG 场景打基础

AI编程系列02:合并知识功能,给 AI 问数和 RAG 场景打基础 在上一期「AI编程系列」中,我们学习了如何构建一个基础的 AI 问答系统,通过简单的输入输出让模型回应问题。但现实世界中的 AI 应用往往需要处理更复杂的场景:…

2026/7/29 0:00:23 阅读更多 →
AI智能体开发实战:从工具调用到企业级部署

AI智能体开发实战:从工具调用到企业级部署

1. 从被动问答到主动执行:AI Agent的范式转变过去两年,大语言模型最显著的应用形态是聊天机器人——用户提问,AI回答。但真正的生产力革命发生在2023年下半年:当AI学会主动调用工具完成任务时,生产力工具的历史被彻底改…

2026/7/29 0:00:23 阅读更多 →

周新闻

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 数据集6000张 完整源码已标注数据集训练好的模型环境配置教程程序运行说明文档,可以直接使用!系统支持图片、视频、摄像头等多种方式检测裂缝,功能强大实用。 1数据集6000张 8各类别

2026/7/28 12:04:22 阅读更多 →
深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

pubg数据集 精选原图1.42万数据 1.49万标签 无任何重复、算法增强或冗余图像! pubg绝地求生目标检测数据集 1分类:e_body,14905个标签,txt格式 共计14244张图,99%为640*640尺寸图像 适合yolo目标检测、AI训练关键词&am…

2026/7/28 8:29:16 阅读更多 →
Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex检测数据集数据集详情检测类别: allies enemy tag图片总量:7247张训练集:5139张验证集:1425张测试集:683张标注状态:全部已标注,即拿即用数据格式:支持YOLO格式及其他格式&#…

2026/7/28 5:03:42 阅读更多 →

月新闻