Linux session(会话)
笔者在前文《Linux job control》中介绍了进程组(job)的概念以及常见的 job control 操作,本文接着介绍 session 的概念。本文中演示部分使用的环境为 ubuntu 18.04。
session 是什么?
我们常见的 Linux session 一般是指 shell session。Shell session 是终端中当前的状态,在终端中只能有一个 session。当我们打开一个新的终端时,总会创建一个新的 shell session。
就进程间的关系来说,session 由一个或多个进程组组成。一般情况下,来自单个登录的所有进程都属于同一个 session。我们可以通过下图来理解进程、进程组和 session 之间的关系:
会话是由会话中的第一个进程创建的,一般情况下是打开终端时创建的 shell 进程。该进程也叫 session 的领头进程。Session 中领头进程的 PID 也就是 session 的 SID。我们可以通过下面的命令查看 SID:
$ ps -o pid,ppid,pgid,sid,tty,comm
Session 中的每个进程组被称为一个 job,有一个 job 会成为 session 的前台 job(foreground),其它的 job 则是后台 job(background)。每个 session 连接一个控制终端(control terminal),控制终端中的输入被发送给前台 job,从前台 job 产生的输出也被发送到控制终端上。同时由控制终端产生的信号,比如 ctrl + z 等都会传递给前台 job。
一般情况下 session 和终端是一对一的关系,当我们打开多个终端窗口时,实际上就创建了多个 session。
Session 的意义在于多个工作(job)在一个终端中运行,其中的一个为前台 job,它直接接收该终端的输入并把结果输出到该终端。其它的 job 则在后台运行。
session 的诞生与消亡
通常,新的 session 由系统登录程序创建,session 中的领头进程是运行用户登录 shell 的进程。新创建的每个进程都会属于一个进程组,当创建一个进程时,它和父进程在同一个进程组、session 中。
将进程放入不同 session 的惟一方法是使用 setsid 函数使其成为新 session 的领头进程。这还会将 session 领头进程放入一个新的进程组中。
当 session 中的所有进程都结束时 session 也就消亡了。实际使用中比如网络断开了,session 肯定是要消亡的。另外就是正常的消亡,比如让 session 的领头进程退出。一般情况下 session 的领头进程是 shell 进程,如果它处于前台,我们可以使用 exit 命令或者是 ctrl + d 让它退出。或者我们可以直接通过 kill 命令杀死 session 的领头进程。这里面的原理是:当系统检测到挂断(hangup)条件时,内核中的驱动会将 SIGHUP 信号发送到整个 session。通常情况下,这会杀死 session 中的所有进程。
session 与终端的关系
如果 session 关联的是伪终端,这个伪终端本身就是随着 session 的建立而创建的,session 结束,那么这个伪终端也会被销毁。
如果 session 关联的是 tty1-6,tty 则不会被销毁。因为该终端设备是在系统初始化的时候创建的,并不是依赖该会话建立的,所以当 session 退出,tty 仍然存在。只是 init 系统在 session 结束后,会重启 getty 来监听这个 tty。
nohup
如果我们在 session 中执行了 nohup 等类似的命令,当 session 消亡时,相关的进程并不会随着 session 结束,原因是这些进程不再受 SIGHUP 信号的影响。比如我们执行下面的命令:
$ nohup sleep >/dev/null >& &
此时 sleep 进程的 sid 和其它进程是相同的,还可以通过 pstree 命令看到进程间的父子关系:
如果我们退出当前 session 的领头进程(bash),sleep 进程并不会退出,这样我们就可以放心的等待该进程运行结果了。
nohup 并不改变进程的 sid,同时也说明在这种情况中,虽然 session 的领头进程退出了,但是 session 依然没有被销毁(至少 sid 还在被引用)。重新建立连接,通过下面的命令查看 sleep 进程的信息,发现进程的 sid 依然是 7837:
但是此时的 sleep 已经被系统的 1 号进程 systemd 收养了:
setsid
setsid 会创建一个新的 session,它的目的是让进程在后台执行命令,实现方式就是让命令进程运行在一个新的与终端脱离的 session 中。看下面的示例:
$ setsid sleep
查找之下居然没有发现 sleep 进程的踪迹:
通过 grep 查询 sleep 进程的 PID:
去查看 sleep 进程所在的 sid,发现是一个新的 session ID,并且没有关联终端:
当一个进程通过调用 setsid 成为一个新的 session 领头进程时,它会与控制终端断开连接。
此时通过 pstree 查看进程间的关系,发现 sleep 进程直接被系统的 1 号进程 systemd 收养了:
控制终端(controlling terminal)
控制终端是进程的一个属性。通过 fork 系统调用创建的子进程会从父进程那里继承控制终端。这样,session 中的所有进程都从 session 领头进程那里继承控制终端。Session 的领头进程称为终端的控制进程(controlling process)。简单点说就是:一个 session 只能与一个终端关联,这个终端被称为 session 的控制终端(controlling terminal)。同时只能由 session 的领头进程来建立或者改变终端与 session 的联系。我们可以通过 ps 命令查看进程的控制终端:
支持 job control 的 shell 必须能够控制在某一时刻由哪个 job 使用终端。否则,可能会有多个 job 试图同时从终端读取数据,这会导致进程在接收用户输入时的混乱。为了防止这种情况发生,shell 必须按照预定的协议与终端驱动程序协作。
shell 一次只允许一个 job(进程组)访问控制终端。来自控制终端的某些输入会导致信号被发送到与控制终端关联的 job(进程组)中的所有进程。该 job 被称为控制终端上的前台 job。由 shell 管理的其他 job 在不访问终端的情况下,被称为后台 job。
Shell 的职责是通知 job 何时停止何时启动,还要把 job 的信息通知给用户,并提供机制允许用户继续暂停的 job、在前台和后台之间切换 job。比如前台 job 可以无限制的自由使用控制终端,而后台 job 则不可以。当后台 job 中的进程试图从其控制终端读取数据时,通常会向进程组发送 SIGTTIN 信号。这通常会导致该组中的所有进程停止(变成 stopped 状态)。类似地,当后台 job 中的进程试图写入其控制终端时,默认行为是向进程组发送 SIGTTOU 信号,但是否允许写入的控制会更加的复杂。
参考:
What is the definition of a “session” in linux?
Linux session和进程组概述
Job Control
Linux TTY/PTS概述
setsid source code
Linux session(会话)的更多相关文章
- nginx+keepalived+tomcat+memcache实现双VIP高可用及Session会话保持
Nginx+Keepalived+Tomcat+Memcached 实现双VIP负载均衡及Session会话保持 IP 信息列表: 名称 IP ...
- requests.session()会话保持
可能大家对session已经比较熟悉了,也大概了解了session的机制和原理,但是我们在做爬虫时如何会运用到session呢,就是接下来要讲到的会话保持. 首先说一下,为什么要进行会话保持的操作? ...
- Tomcat负载均衡、调优核心应用进阶学习笔记(三):LNMT nginx+tomcat、LAMT apache+tomcat、session会话保持、不错的站点
文章目录 LNMT nginx+tomcat LAMT apache+tomcat 基于mod_proxy 单节点 配置基于mod_proxy的负载均衡 基于mod_jk(需要编译安装) 单节点 配置 ...
- 负载均衡session会话保持方法
负载均衡时,为了保证同一用户session会被分配到同一台服务器上,可以使用以下方法:1.使用cookie将用户的session存入cookie里,当用户分配到不同的服务器时,先判断服务器是否存在该用 ...
- PHP中的session会话创建打印释放销毁;
PHP Session PHP session 变量用于存储关于用户会话(session)的信息,或者更改用户会话(session)的设置.Session 变量存储单一用户的信息,并且对于应用程序中的 ...
- 跨域请求,关于后端session会话丢失的解决办法
目前使用前后端分离的模式开发,后端提供跨域接口.前端jsonp调用,绑定数据,但是在该站点下有个人中心模块存在的情况下,服务端的session会话会被跨域请求覆盖改掉 大家都知道tomcat使用coo ...
- SESSION会话技术
以下对session会话技术详解: 要了解点http协议理解更佳--->http请求头和http相应头 在session_start的时候,浏览器会向服务器发出请求 在请求的同时,如果是第一次a ...
- PHP漏洞之session会话劫持
本文主要介绍针对PHP网站Session劫持.session劫持是一种比较复杂的攻击方法.大部分互联网上的电脑多存在被攻击的危险.这是一种劫持tcp协议的方法,所以几乎所有的局域网,都存在被劫持可能. ...
- session会话管理
session会话和cookie一起被称为会话跟踪技术,主要通过保存在服务器端的session数据和客户端浏览器的cookie数据共同完成用户访问服务器的足迹记录. 1. 什么是会话 会话sessio ...
随机推荐
- C# const 和 readonly 有什么区别
在写常量的时候,是选择使用 const 还是 static readonly 是一个让人难以决定的问题,本文告诉大家这两个方法的区别 如果一个类有静态字段,会如何初始化 可以使用的方法有两个,第一个方 ...
- H5 数据存储localStorage
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- CodeForces 242E "XOR on Segment"(线段树)
传送门 •题意 给你一个包含 n 个数的序列 a,定义序列上的两个操作: (1)$1,l,r\ :\ ans=\sum_{i=l}^{r}a_i$; (2)$2,l,r,x\ :\ \forall\ ...
- C# 简单读取文件
本文告诉大家如何使用最少的代码把一个文件读取二进制,读取为字符串 现在写了一些代码,想使用最少代码来写简单的读文件,所以我就写了这个文章 读取文件为二进制 private byte[] ReadFil ...
- hdu 2454 Degree Sequence of Graph G(可简单图化判定)
传送门 •Havel-Hakimi定理: 给定一个非负整数序列{d1,d2,...dn},若存在一个无向图使得图中各点的度与此序列一一对应,则称此序列可图化. 进一步,若图为简单图,则称此序列可简单图 ...
- [Linux] 利用tcpdump和strace进行debug
比如说要查看所有的sql查询语句,数据库的端口是3306 tcpdump -i any port 3306 -l -s 0 -w -|strings|grep -A 5 select 要查看所有的调用 ...
- 一目了然 | 数据库实例性能调优利器:Performance Insights
Performance Insights是什么 阿里云RDS Performance Insights是RDS CloudDBA产品一项专注于用户数据库实例性能调优.负载监控和关联分析的利器,以简单直 ...
- remote api
iperf -B 99.99.3.1 -c 192.168.42.242 -p 10002 -f m -i 1 -P 1 -w 1M -u -b 1M -t 20 iperf -B 192.168.4 ...
- boostrap-非常好用但是容易让人忽略的地方【3】:clearfix
代码 显示结果 代码 结果
- java 使用 morphia 存取枚举为值
源码 https://github.com/zhongchengyi/zhongcy.demos/tree/master/mongo-morphia-demo 前言 morphia是java 使用or ...