hello world的代码、程序和进程

咱们从“Hello World”这个例子说起,先搞清楚三个基本概念:代码、程序和进程。代码就是写在编辑器里的文本,像 helloWorld.c 里的那些字母数字;程序是通过编译器把代码转成的可执行文件;进程才是真正跑起来的那个实例。 你把这段代码保存为 helloWorld.c,它现在就是一堆只读的文本,啥也干不了。接着你用 gcc 把它编译成二进制的可执行文件,这时候系统才能认出它、加载它。当你执行 ./helloWorld 时,“Hello World”出来的那一刻,一个新的进程就诞生了。这个进程会去执行 helloWorld 文件里的机器码,直到 sleep 完那 10 秒才结束。你用 ps 命令查一下就能看到一个 PID 是 6163 的进程正在跑,那就是刚才启动的那个实例。 每个命令其实都是在 shell 里敲出来的,你打开终端输入命令时,系统会给你创建一个新的进程。比如你执行 ps -aef,就能看到当前的 shell 通常是大多数进程的“老父亲”,它的 PID 是 3079。这就像一棵大树的树干,所有其他进程都是从这里分叉出去的。 如果某个子进程的父进程突然挂了,它就成了没爹的“孤儿”,这时候系统会立刻把它收过来,让它当 init 的孩子。init 这个进程的 PID 是 1,就像所有进程的大总管。你用 pstree 就能看到整个进程树是以 init 为根的。 进程的一生大致是这样的:它先通过 fork 复制一份父进程的地址空间,变成“双胞胎兄弟”;然后通过 exec 加载新的程序进来,把原来的内存都换掉;接着进就绪队列排队等 CPU 时间片;等到自己要用硬盘或者网络的时候就会陷入内核态;要是数据没到就休眠等着;最后可以通过 exit 或者信号退出。如果父进程不调用 wait 回收它,那它就会变成僵尸状态,只占着 PID 号却啥也不干。 COW(写时复制)机制在这里特别关键。在 fork 后父子进程会先共享物理内存页,只有当你真的要写数据时才会真正复制一份内存出来。这样一来小改动大家还能继续共享空间,大改动各自单独来就不会互相影响了。 总结一下重点:代码是静态的蓝图,程序是执行体,进程是活的实例。每个进程都得有个爹(除非是 init 直接生的)。fork 加上 exec 是 Linux 下创建新进程的标准套路;COW 让复制和共享两者都有好处。 把这几句话记住了,再复杂的系统调度你也能一眼看明白。