先补充一点知识
PGID相同说明他是属于一个进程组
第一个进程叫做组长
前后台管理是以进程组为单位
你ctrl c将sleep进程杀掉,-->你从键盘输入,将整个进程组都退出了
前台进程后台进程
前台进程
前台进程就是可以接收键盘输入的进程,当我sleep时,在往终端输入时,没有任何的反应,因为sleep启动,bash进程自动变成了后台进程
再ctrl+c,将sleep这个前台进程杀掉了,bash就立马接管了前台,因为如果他不接管前台进程的化,就没有前台进程了
后台进程
就是不能从键盘获取数据信息的
再命令后面+&就可以启动后台进程
那如何将一个后台进程杀了??
kill -9 pid
或者把后台进程调成前台进程,然后再ctrl c将这个进程杀死,
那如何将一个后台进程变成前台进程??
fg+作业号
作业号
后台进程前面有序号那个就是作业号,
作业vs进程组
作业有进程组来进行完成
将一个作业变成前台进程
然后ctrl z可以将前台进程变成后台进程,并且是T状态
bg+作业号,可以让后台进程继续运行
除上面之外我们不难发现
之前启动的进程SID都是相同的,SID又是什么,其实就是会话ID
我们还发现这个会话id是这些进程的ppid,就是父进程,还是bash进程
- Windows 上打开 Xshell,SSH 远程连上 Linux 服务器。
- Linux 这边创建出一个伪终端文件(pts),同时启动第一个进程:
bash。bash 就是会话首进程,bash 自己的 PID,就等于整个会话的 SID(Session ID) - 在这个 bash 里面敲命令,运行 sleep、ls、程序,这些全部是这个会话里面的子进程。所有子进程全部继承同一个 SID,共享这一个终端 pts。
当然也可以打开多个bash,它也会建立多个会话
我们多打开一个终端,这个路径下面的文件就会多一个pts
当退出会话、关闭 bash 终端时,该会话内的进程通常会随之结束。但部分进程可以在会话关闭之后继续运行.
如果想让我们写的./HTTP可以不受会话的影响,该怎么办???
那就让他这个进程,自成会话
调用setsid
setsid 系统调用有一条硬性规则:调用 setsid 的进程,不能是进程组组长。
如果当前进程本身就是进程组组长,直接调用setsid()会调用失败,无法创建新会话。
标准解决思路: 父进程先执行fork()创建子进程,让子进程去调用 setsid (),随后父进程直接退出。 子进程失去父进程,成为孤儿进程,由系统 init/systemd 接管; 子进程调用setsid(),成功创建独立会话,脱离原有终端,这就是守护进程的核心实现逻辑。
进程组!=组长进程,他只是用了组长的pid
进程组组长不在了,组还是依然存在,全部进程都退出了,组才会消失
守护进程也是孤儿进程,也叫做精灵进程
daemon
说明自成进程组,自成Sid
之前存在的问题
服务器重启端口绑定失败
现象:关闭我们写的 HTTP 服务器程序,立刻重新启动服务,bind()绑定端口直接失败,提示端口被占用,明明程序已经退出了。
为什么会出现绑定失败?
并不是我们的socket()创建套接字出错,问题出在 TCP 连接的 TIME‑WAIT 状态。
当服务端程序直接 kill/ctrl‑c 关闭后,操作系统不会立刻释放端口。内核会把旧连接保持在TIME‑WAIT状态一段时间(默认几十秒)。
TIME‑WAIT 作用:保证网络上残留的迟到数据包全部消失,避免旧连接的报文干扰新启动的服务器。
这就导致:端口还被内核占用,新程序调用 bind 绑定同一个端口就失败。 服务器端口一般固定写死,不能随便换端口号,我们希望程序关闭后马上就能复用原端口启动,减少业务中断损失。
要采用地址复用
服务器的端口号是不能随便改的
为什么要立即重启??减少损失