linux php sid(七)会话
bash进程与终端概念
会话基本概念
说起会话,我们经常登录到linux系统, linux是一个多用户多任务的分时操作系统,必须要支持多个用户同时登陆同一个操作系统,当一个用户登陆一次终端时就会产生一个会话,执行各种各样的程序,这都牵涉到会话。
会话是基于连接的。会话的源头,就是用户与系统之间连接的启用。
会话:会话(session)是一个或多个进程组的集合。
会话首进程:一个会话里是有很多进程的,第一个被创建出来的进程就是会话首进程,会话首进程(session leader)是指创建会话的进程,其进程ID会成为会话ID,会话中的所有进程都具有相同的会话标识符。
每个会话有一个会话首进程,即创建会话的进程,建立与终端连接的就是这个会话首进程,也被称为控制进程。一个会话可以包括多个进程组, 这些进程组可被分为一个前台进程组和一个或多个后台进程组。为什么要这么分呢?前台进程组是指需要与终端进行交互的进程组(只能有一个)
使用会话最多的是支持任务控制的shell,由shell创建的所有进程组与shell自身隶属于同一会话,shell是此会话的会话首进程。
打开控制终端会致使会话首进程成为终端的控制进程。一旦断开了与终端的连接(比如,关闭了终端窗口),控制进程将会收到SIGHUP信号。
创建一个会话
- posix_setsid() 使当前进程成为session leader(会话首进程)
- 不能使用组长进程调用
posix_setsid
函数,要是硬要调用,就会报错。
我们可以编写代码测试一下
<?php
# 设置当前进程为会话首进程
$sid = posix_setsid();
#调用 posix_setsid() 函数错误会返回 -1
if(-1 === $sid){
print("sid error".PHP_EOL);
}
# 获取当前进程进程pid
$pid = posix_getpid();
#打印当前进程pid,调用posix_setsid函数后的会话id,组id,当前进程所属的会话id
fprintf(STDOUT,"pid=%d,sid=%d,pgid=%d,getsid=%d\n",$pid,$sid,posix_getpgid($pid),posix_getsid($pid));
# 方便查看进程关系
while(true)
{
#睡眠
sleep(2);
}
先执行demo1.php 后我们在另一个终端执行 pstree -ap
查看进程关系,对比两张图发现,执行demo1.php 得到当前进程id为 12968 ,又因为demo1.php 是在bash 进程执行所以会话id 为 1526,组id和进程id相同表示当前进程就是进程组长,所以就不难理解为什么调用posix_setsid
函数返回 -1
了。
- 我们一般先创建一个子进程,让父进程exit 退出,由子进程调用
posix_setsid
函数
我们也可以编写代码测试一下
<?php
#设置会话前先打印做对比
#打印当前进程pid,组id,当前进程所属的会话id,当前进程父进程ppid
$pid = posix_getpid();
fprintf(STDOUT,"pid=%d,pgid=%d,getsid=%d,ppid=%d\n",$pid,posix_getpgid($pid),posix_getsid($pid),posix_getppid());
# fork 子进程
$pid = pcntl_fork();
if($pid > 0){
exit(0);
}
# 设置当前进程为会话首进程
$sid = posix_setsid();
#调用 posix_setsid() 函数错误会返回 -1
if(-1 === $sid){
print("sid error".PHP_EOL);
}else{
print("会话首进程设置成功".PHP_EOL);
}
# 获取当前进程进程pid
$pid = posix_getpid();
#打印当前进程pid,调用posix_setsid函数后的会话id,组id,当前进程父进程ppid
fprintf(STDOUT,"pid=%d,sid=%d,pgid=%d,getsid=%d\n",$pid,$sid,posix_getpgid($pid),posix_getppid());
# 方便查看进程关系
while(true)
{
#睡眠
sleep(2);
}
先执行demo2.php 后我们在另一个终端执行 pstree -ap|grep -E "demo2.php|bash|systemd|sshd"
查看进程关系,对比两张图发现,demo2.php 在创建子进程后父进程退出,留下子进程,子进程必不会是进程组长,故而可以调用 posix_setsid
函数设置自己为会话首进程,需要特别注意的是,子进程设置自己为会话首进程后终端连接就断开了
,也就是说这时候你在终端输入什么 ctrl+c
对demo2.php 是没有作用的,它已经彻底转为后台进程了
- 调用
posix_setsid
函数之后,该进程会变成 组长进程,同时也会变成会话首进程 - 同时该进程没有控制终端(没有控制终端可以理解为,进程没有连接显示器,没有连接键盘)它没有控制终端了,你在终端里输入任何数据都没有反应