企业的后端服务器领域,一直是类 Unix 系统的天下,在系统的众多概念中,进程是应用得以运行的核心所在。

✨ 进程要素

  • pid,每个进程都有一个唯一标识;
  • ppid,创建该进程的父进程的唯一标识;
  • name,除了进程的 pid,也可以给进程设置名称;
  • fd,file descriptor,打开文件描述符,Unix 哲学之一:万物皆文件,fd 被用来代表打开的文件,所有设备、socket、pipe 等都有自己对应的一个 fd,fd 不会在无关的进程间共享,关于 fd 的一个典型案例是 0/1/2 代表 stdin/stdout/stderr;
  • limits,分配给进程的各种资源可以设置限制,可以限制 CPU 使用时间、fd 数量(对高并发有影响)、文件锁数量等,一般有如下两种类型
    • soft limits,进程可以自行修改;
    • hard limits,只有超级用户才能修改;
  • env,进程的环境变量,包含若干 k-v 对;
  • argv,通过命令行传递给进程的参数数组;
  • exit code,进程退出时可以设置退出码(0-255),0 代表成功。

🧙‍♂️ 进程创造

可以通过系统调用 fork 来创建一个进程,调用 fork 的进程称为父进程,创建出来的进程称为子进程,子进程会获得父进程所使用内存的一份完整拷贝(包括 fd)。假设有进程 A 从存储加载了 100 M 的内容到内存,当 A fork 出子进程 B 时,B 会从 A 的内存中拷贝这 100 M 的内容到自己的内存空间,而不用再去存储中加载(采用了 CoW 机制的情况下,只有在某进程发生写的时候才实际分裂出一个内存拷贝)。父进程可以阻塞等待(wait)子进程退出,适用于异步任务场景。

如果通过 exec,则生成一个新进程,覆盖当前进程。

💀 特殊进程

孤儿进程(Orphaned Process),当父进程挂掉而子进程还在执行时,子进程就成为孤儿进程,孤儿进程会自动托管给 pid 为 1 的守护进程 init。

僵尸进程(Zombie Process),进程死亡后并没有完整地退出,需要父进程收拾残骸(进程返回值和其他信息)。所有已退出的子进程,如果退出状态没有被父进程 wait(信息一直挂在内核中),就属于僵尸进程。当子进程退出时,内核会登记该进程的退出信息,需要父进程调用 wait 去请求,请求之后内核就会清理掉这部分信息。如果父进程没有使用 wait 等待子进程结束,则需要提前执行 detach 操作,detach 操作会 spawn 出一个线程专门 wait 子进程的退出信息。

守护进程(Daemon Process),没有明确的结束期限,可以执行到地老天荒的后台进程,通常提供基础功能,如 pid 为 1 的 init 进程。

🪁 信号

通过内核作为中转站,一个进程可以发送 signal 给另一个进程,只要知道其 pid。

Action 的类型解释:

  • Term,进程立即结束;
  • Core,进程立即结束并打印 dump 文件;
  • Ign,忽略该信号;
  • Stop,进程停止或暂停;
  • Cont,进程将继续。

🎯 通信

进程间通信称为 IPC(Inter-Process Communication),可以采用 pipe,进行单工通信,也可以采用 unix socket,供同一台机器上的进程进行双工通信,unix socket 的方式比 tcp socket 更适合于 IPC — 因为本机没有必要过一遍网络协议栈。


参考

  • 《Working with Unix Processes》
分类: CODE啃书

0 条评论

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注