在 Windows 里,如果你把 game.exe 改名为 game.txt,双击它只会打开记事本,程序无法运行。因为 Windows 极其依赖后缀名来判断文件类型。
但在 Linux 世界,文件名真的只是一个名字。你可以把 Python 脚本命名为 script.png,只要设置正确,它依然能正常运行。文件扩展名在 Linux 主要是为了方便人类管理和区分,系统本身根本不在乎。
那么,Linux 究竟靠什么来判断一个文件能不能跑、该怎么跑?这取决于它内部的一套判定流程。
1. 找文件 (Shell)
这一步取决于输入命令的方式。
只输入命令名
输入 python 或 ls 时,Shell 不知道文件在哪里。它需要按顺序查找:
- 2. 内建命令:检查是否是 Shell 自带的功能,如
cd。 - 3. 环境变量:扫描
$PATH 变量中的目录,直到找到同名文件。
输入具体路径
输入 ./script.sh 或 /bin/ls 时,已经指定了位置,Shell 跳过查找,直接把路径交给系统。
2. 查权限 (文件系统)
找到文件后,内核会先检查 x (Execute) 权限位。
如果不具备这个权限,系统直接报错 Permission denied,内核不会读取文件内容。必须使用 chmod +x 命令开启权限后才能继续。
3. 识别格式 (内核)
权限检查通过后,Linux 内核读取文件开头的数据(魔数字),决定由谁来执行。
二进制程序 (ELF)
文件开头是 7F 45 4C 46。内核直接加载代码并运行。这是 Linux 最主要的可执行格式,支持代码直接编译在内核核心中。
Window 中的 exe等文件也有魔术字,但文字扩展名改了系统不会去看魔术字。
特定格式的文件也有魔术字,如JPEG、PDF、Java 的 class等。
但系统默认只处理它认识的。
查看/boot/config-$(uname -r)中的配置
# Executable file formats#CONFIG_BINFMT_ELF=yCONFIG_COMPAT_BINFMT_ELF=yCONFIG_ELFCORE=yCONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=yCONFIG_BINFMT_SCRIPT=yCONFIG_BINFMT_MISC=mCONFIG_COREDUMP=y# end of Executable file formats
说明:
- • CONFIG_BINFMT_ELF=y:y 代表内置。ELF 支持直接写在内核代码里,无法卸载。
- • CONFIG_BINFMT_SCRIPT=y:脚本支持也是内置的。
- • CONFIG_BINFMT_MISC=m:m 代表模块。这是扩展功能,需要时才加载,用
lsmod 能看到。
脚本文件 (Shebang)
文件开头是 #!,对应的十六进制是 23 21。内核读取 #! 后面的路径,启动对应的解释器(如 /bin/bash),把脚本作为参数传给它。
可以用 file 命令测试下修改 Shebang 的效果。
me@T420:~$ vim test.shme@T420:~$ cat test.shcd ..me@T420:~$ file test.shtest.sh: ASCII textme@T420:~$me@T420:~$ vim test.shme@T420:~$ cat test.sh#!/usr/bin/python3cd ..me@T420:~$ file test.shtest.sh: Python script, ASCII text executableme@T420:~$me@T420:~$ vim test.shme@T420:~$ cat test.sh#!/usr/bin/bashcd ..me@T420:~$ file test.shtest.sh: Bourne-Again shell script, ASCII text executable
自定义格式 (binfmt_misc)
文件既不是 ELF 也不是脚本,例如 Java 的 .class。
内核会去查 /proc/sys/fs/binfmt_misc 中注册的规则。
如果匹配到对应的魔数,就调用预设的外部程序。
简单总结执行流程