
大家好,接下来的一段时间我将开始学习野火的Linux系统课程并将学习到的干货逐步更新到我的CSDN博客中。没时间刷课的同学可以把我的博客喂给AI 突击一下。
目录
三个问题
1、了解 Hello World 程序的执行过程有什么用?
2、裸机开发中的 HelloWorld 程序是怎么执行的?
3、Linux 系统下的 Hello World 程序是怎么执行的?
阶段一:GCC 编译四步
阶段二:程序运行完整流程
四个案例
gcc 预处理 c 文件
gcc 编译 c 文件(生成汇编)
gcc 编译汇编(生成目标文件)
gcc 链接可重定位文件
Linux系统下的Hello World的借鉴意义非常强, 对我们以后进一步学习其他课程起到很好的指导作用,面试的时候面试官也很爱问这部分知识来考验面试者知识扎实程度,大家尽量把这块“硬骨头”啃下来。
5. Linux系统下的Hello World — [野火]嵌入式Linux基础与应用开发实战指南——基于i.MX6ULL开发板 文档
https://doc.embedfire.com/linux/imx6/linux_base/zh/latest/linux_app/hello_in_linux/hello_in_linux.html
三个问题
1、了解 Hello World 程序的执行过程有什么用?
2、裸机开发中的 HelloWorld 程序是怎么执行的?
裸机:无操作系统,CPU 上电直接跳转到程序入口。
上电→CPU 复位,执行复位向量入口函数→初始化栈、bss 段→手动调用 main 函数→执行打印(操作寄存器驱动串口)→程序循环 / 退出。
3、Linux 系统下的 Hello World 程序是怎么执行的?
完整链路分为两大阶段:GCC 编译阶段 + 程序运行阶段(Shell‑内核‑glibc‑应用)
阶段一:GCC 编译四步
| ① | 预处理 | gcc -E hello.c -o hello.i | hello.c | hello.i | 展开头文件、宏替换,去掉注释 |
| ② | 编译 | gcc -S hello.i -o hello.s | hello.i | hello.s | C 语言→汇编代码 |
| ③ | 汇编 | gcc -c hello.s -o hello.o | hello.s | hello.o | 汇编→机器码,可重定位目标文件 |
| ④ | 链接 | gcc hello.o -o hello | hello.o | hello(ELF 可执行程序) | 合并段,链接系统库,生成最终可执行文件 |
编译完成得到 ELF 格式 hello,Shell 输入 ./hello 开始运行。
阶段二:程序运行完整流程
⑤ Shell 收到./hello命令 ⑥ Shell 调用fork()系统调用,创建子进程 ⑦ 子进程调用execve()用户态库函数 ⑧ 陷入内核,执行系统调用入口sys_execve() ⑨ 内核内部调用do_execve(),解析 ELF 文件 ⑩ load_elf_binary():内核加载 ELF 程序到进程虚拟地址空间;加载动态链接器ld‑linux‑xx.so ⑪ 把 CPU 控制权交给动态链接器 ⑫ 动态链接器完成库重定位,调用_start;_start调用 glibc 入口_libc_start_main() ⑬ _libc_start_main()做初始化,调用我们写的 main () 函数 ⑭ main 内部执行printf("hello,world!\\r\\n");main 返回后 glibc 调用_exit()系统调用,通知内核销毁进程,程序结束。
关键点:main 不是程序的真正入口,真正入口是_start,main 只是库函数调用的一个普通函数。
四个案例
gcc 预处理 c 文件
gcc -E hello.c -o hello.i #末尾加上-v把信息全部打印出来

| cc1 | GCC 的 C 语言编译器前端(真正干活的程序,gcc 命令只是个调度器) |
| -E | 只做预处理,不编译 |
| hello.c | 输入源文件 |
| -o hello.i | 输出预处理后的 .i 文件 |
| -fstack-protector-strong | 栈保护(防溢出攻击) |
| -Wformat -Wformat-security | 格式化字符串安全警告 |
gcc 编译 c 文件(生成汇编)
gcc -S hello.i -o hello.s #末尾加上-v把信息全部打印出来

| cc1 | 同一个编译器前端,这次不带 -E |
| -fpreprocessed | 告诉 cc1 输入已经是预处理过的文件,不用再处理宏了 |
| hello.i | 输入:预处理文件 |
| -o hello.s | 输出:汇编代码 .s 文件 |
gcc 编译汇编(生成目标文件)
gcc -c hello.s -o hello.o #末尾加上-v把信息全部打印出来
![]()
| as | binutils 里的汇编器,不属于 gcc 本体 |
| -64 | 生成 64 位目标代码 |
| hello.s | 输入:汇编文件 |
| -o hello.o | 输出:二进制目标文件 .o(ELF 可重定位文件) |
gcc 链接可重定位文件
gcc hello.o -o hello #末尾加上-v把信息全部打印出来

| collect2 | GCC 的链接器封装,内部最终调用 ld |
| crt1.o / crti.o / crtbegin.o | C 运行时启动文件,包含 _start 入口,负责调用 _libc_start_main → main |
| hello.o | 我们自己编译的目标文件 |
| crtend.o / crtn.o | 运行时收尾文件 |
| -lc | 链接 libc 标准 C 库(printf 就在这里) |
| -o hello | 输出最终可执行程序 |
网硕互联帮助中心






评论前必须登录!
注册