守护进程&僵尸进程&孤儿进程

守护进程

一般为 Daemon进程,常在系统引导载入时启动,在系统关闭时终止。许多后台服务都是通过守护进程实现的。

创建步骤:

  • 执行一个fork(),之后父进程退出,子进程继续执行
  • 子进程调用setsid()开启一个新回话并释放它与控制终端之间的所有关联关系。结果就是使子进程: (a)成为新会话的首进程,(b)成为一个新进程组的组长进程,©没有控制终端。
  • 修改进程的当前工作目录,通常会改为根目录(/)
  • 关闭daemon从其父进程继承而来的所有打开着的文件描述符

僵尸进程

子进程退出时,父进程并未对其发出的SIGCHLD信号进行适当处理,导致子进程停留在僵死状态等待其父进程为其收尸。

孤儿进程

在其父进程执行完成或被终止后仍继续运行的一类进程。这些孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。

kill -9或ctrl+c到底发生了什么

INT 2 中断(同 Ctrl + C)

TERM 15 终止:可以做准备工作,如遇阻塞也可以忽略

KILL 9 强制终止

fork()和exec()

fork()

创建启动一个新进程,该进程是调用它的进程的副本,两个进程完全相同。

子进程拥有新的PID,fork()的返回值,若为0,则表示是在子进程中返回;若大于0,则表示是在父进程中返回,且该值为子进程的PID。

exec()

用另一个(不相同的)进程映像替换当前进程映像,当前进程的“数据段”,“堆栈段”和“代码段”被新程序改写。

新程序会保持调用exec()进程的PID不变。

零拷贝

参考https://juejin.cn/post/6995519558475841550

read(); write() 传统文件传输

mmap(); write() 虚拟内存映射

mmap() 替换了read(),会直接把内核缓冲区里的数据映射到用户空间,这样,操作系统内核与用户空间就不需要再进行任何的数据拷贝操作。

sendfile()

有两个参数,分别是目的端和源端的文件描述符。

替代前面的 read()write() 这两个系统调用,这样就可以减少一次系统调用,也就减少了 2 次上下文切换的开销。可以直接把内核缓冲区里的数据拷贝到 socket 缓冲区里,不再拷贝到用户态。

scatter-gather sendfile()

  • 第一步,通过 DMA 将磁盘上的数据拷贝到内核缓冲区里;
  • 第二步,缓冲区内存地址和数据长度传到 socket 缓冲区,这样网卡的 SG-DMA 控制器就可以直接将内核缓存中的数据拷贝到网卡的缓冲区里,此过程不需要将数据从操作系统内核缓冲区拷贝到 socket 缓冲区中,这样就减少了一次数据拷贝;


hhhhh