5-3 会话

会话 会话是一个进程组,或是多个进程组的集合。 一个会话可以至少有一个控制终端(物理终端,伪终端) 一个会话至少有一个前台进程组(前台就是指能输入的 bin/bash ),其它就是后台进程组 一个会话如果连接了一个控制终端,就叫控制进程 因为这个会话首进程 /bin/bash 是连接控制终端(伪终端设置驱动程序+tcp/ip 对端的ssh client) 的,所以创建的子进程,也会继承 bin/bash 的控制终端(0,1,2标准输出,标准输入,标准错误) 在终端的输入会影响前台进程组,ctrl+c (会终止前台进程)。 会话的创建 使用 posix_setsid() / setsid(2)创建。 不能使用组长进程调用 setsid 函数,硬要调用会报错 一般先创建一个子进程,让父进程exit,由子进程调用 setsid 调用 setsid 之后,该进程会变成组长进程,同时也会变成会话首进程 同时该进程没有控制终端(没有终端了,可以认为它没有连接显示器,没有连接键盘) 它没有控制终端了,你在终端里输入任何数据都没有反应的 phpdemo19.php <?php function showPid() { $pid = posix_getpid(); fprintf(STDOUT, "pid=%d,ppid=%d,pgid=%d,sid=%d\n",$pid,posix_getppid(),posix_getpgid($pid),posix_getsid($pid)); } showPid(); $pid = pcntl_fork(); if ($pid > 0) { exit(0); } if (-1 == posix_setsid()) { echo 'error'.PHP_EOL; $erro_no = pcntl_errno(); echo pcntl_strerror($erro_no).PHP_EOL; } else { echo '会话创建成功'....

2022-06-10 21:37:27 · 王二

5-2 进程组

进程组,就是一个或是多个进程的集合,每一个进程都有个标识「组ID(PGID)」,表示该进程属于哪个进程组。 bash 进程启动之后,它会自己 setsid 把自己设置为会话首进程,也会设置自己为组长进程。 进程:正在执行的程序,这个程序是在 bin/bash 进程里启动的。 进程启动之后(通过 execve 函数启动),它会继承一些属性比如说组ID,会话ID,同时也会继承父进程已经打开的文件描述符(伪终端里的):0/标准输入,1/标准输出,2/标准错误,通过 pts、ptmx 模拟出来的。 demo17.php $pid = posix_getpid(); fprintf(STDOUT, "pid=%d,ppid=%d,pgid=%d,sid=%d\n",$pid,posix_getppid(),posix_getpgid($pid),posix_getsid($pid)); 查看当前 bash 进程 PID $ echo $$ 1031235 另外一个 SSH 连接,追踪上一个 bash 进程 $ strace -f -s 65500 -o demo17.log -p 1031235 在 bash 进程 1031235 中,执行代码 $ php demo17.php pid=1032568,ppid=1031235,pgid=1032568,sid=1031235 demo17.log # bash 进程 clone 一个子进程 1032568 1031235 clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f2c4847ba10) = 1032568 1032568 getpid() = 1032568 ... # 子进程将自己设置为组长进程 1031235 setpgid(1032568, 1032568) = 0 ....

2022-05-08 12:31:27 · 王二

5-1 Bash进程与终端

什么是终端 能实现数据输入、输出的统称为终端。 物理终端:传统显示器、键盘,通过 VGA、HDMI、USB 等连接。 软件终端(虚拟终端/伪终端):通过 TCP/IP 协议实现的终端,能模拟出来一个实现「数据输入、输出」的终端,比如:ssh、telnet … 这篇博客介绍的比较详细:「转」彻底理解Linux的各种终端类型以及概念。 伪终端的连接过程 在linux中有物理终端,有虚拟终端(伪终端)。 sshd 服务会打开一个 [dev/ptmx],这个文件是一个伪终端主设备文件。 bin/bash 会打开一个 dev/pts(0,1…), 是一个伪终端从设备文件。 ptmx/ptsx 它们通过伪终端设备驱动程序模拟出输入和输出的功能。 bin/bash 进程就可以实现数据读取和数据写入。 ssh客户端 ——————> 远程服务器的一个进程 ——-> ssh客户端。 输入单元(ssh客户端)——–> /bin/bash进程————–> 输出单元(ssh客户端)。 bin/bash 启动之后,对终端数据的读取和写入就是通过 pts 实现的(能实现标准输入,标准输出)。 dev/pts0 0 1 2 标准输入,标准输出,标准错误。 通过 strace 命令查看sshd服务: strace 前进程关系: ├─sshd,9408 │ └─sshd,2888142 │ └─bash,2888170 │ └─pstree,2889779 -ap strace 中: $strace -f -s 65500 -o sshd.log -p 9408 # strace 查看系统调用,进行一个新的 SSH 连接 strace: Process 9408 attached strace: Process 2888330 attached strace: Process 2888331 attached strace: Process 2888336 attached strace: Process 2888342 attached strace: Process 2888343 attached strace: Process 2888344 attached strace: Process 2888345 attached strace: Process 2888346 attached strace: Process 2888347 attached strace: Process 2888348 attached strace: Process 2888349 attached strace: Process 2888350 attached strace: Process 2888351 attached strace: Process 2888352 attached strace: Process 2888353 attached strace: Process 2888354 attached strace: Process 2888355 attached strace: Process 2888356 attached strace: Process 2888357 attached # 新的SSH连接 strace: Process 2888358 attached strace: Process 2888359 attached strace: Process 2888360 attached strace: Process 2888361 attached strace: Process 2888362 attached strace: Process 2888363 attached strace: Process 2888364 attached strace: Process 2888365 attached strace: Process 2888382 attached ^Cstrace: Process 9408 detached # 终止信号 strace: Process 2888330 detached strace: Process 2888357 detached 新的 SSH 连接以后的进程关系:...

2022-03-16 15:33:55 · 王二

4-4 发送信号

发送信号的几种形式 kill -s 信号编号|信号名字 进程PID 在程序中使用posix_kill 给一个指定的进程或是进程组发送信号 pcntl_alarm SIGALRM 在终端按下特殊键 ctrl+c、 ctrl+z、ctrl+\ 网络 SIGURG、SIGPIPE、SIGCHLD(当子进程结束的时候) pcntl_signal_dispatch pcntl_signal_dispatch,调用等待信号的处理器。 调用每个等待信号通过 pcntl_signal 安装的处理器。 posix_kill posix_kill,Send a signal to a process. Send the signal to the process with the process identifier process_id. kill, send signal to a process. The kill() system call can be used to send any signal to any process group or process. If pid is positive, then signal sig is sent to the process with the ID specified by pid....

2022-03-15 17:42:37 · 王二

4-3 信号集

信号集 信号集是指信号的集合。 主程序可以选择阻塞某些信号,被阻塞的信号集称为阻塞信号集。 当进程阻塞了某个信号(通过 pcntl_sigpromask 来设置信号屏蔽字),如果在运行期间接收到了阻塞的信号时,这个信号的处理程序不会被执行,这个信号会放在被挂起的信号集里(信号未决集)。 sigpending PHP 没有实现这个函数。 examine pending signals. sigpending() returns the set of signals that are pending for delivery to the calling thread (i.e., the signals which have been raised while blocked). The mask of pending signals is returned in set. pcntl_sigpromask pcntl_sigpromask 设置或检索阻塞信号,用来增加,删除或设置阻塞信号,具体行为 依赖于参数how。 pcntl_sigprocmask(int $how, array $set, array &$oldset = ?): bool 参数: how: 设置 pcntl_sigprocmask()函数的行为。 可选值: SIG_BLOCK: 把信号加入到当前阻塞信号中。 SIG_UNBLOCK: 从当前阻塞信号中移出信号。 SIG_SETMASK: 用给定的信号列表替换当前阻塞信号列表。 set:...

2022-03-15 16:54:58 · 王二

4-2 编写中断信号处理程序

pcntl_signal 信号处理函数 安装一个信号处理器。 说明: pcntl_signal(int $signo, callback $handler, bool $restart_syscalls = true): bool 函数 pcntl_signal 为 signo 指定的信号安装一个新的信号处理器。 参数: signo 信号编号。 handler 信号处理器可以是用户创建的函数或方法的名字,也可以是系统常量 SIG_IGN(译注:忽略信号处理程序)或SIG_DFL(默认信号处理程序). 注意: 注意当你使用一个对象方法的时候,该对象的引用计数回增加使得它在你改变为其他处理或脚本结束之前是持久存在的。 restart_syscalls 指定当信号到达时系统调用重启是否可用。(译注:经查资料,此参数意为系统调用被信号打断时,系统调用是否从 开始处重新开始,但根据http://bugs.php.net/bug.php?id=52121,此参数存在bug无效。 成功时返回 true, 或者在失败时返回 false。 中断系统调用 当进程正在执行系统调用的时候,接收到中断信号,那么这个系统调用就会被中断,比如说进程正在写文件,无法恢复。 如果能恢复我们称为:可重入函数,否则就是非可重入函数。 若一个程序或副程序可以“在任意时刻被中断然后操作系统调度执行另一段代码,这段代码又使用了该副程序不会出错”,则称其为可重入(reentrant 或 re-entrant)的。即当该副程序正在运作时,执行线程可以再次进入并执行它,仍然可得到符合设计时所预期的结果。与多线程并发执行的线程安全不同,可重入强调对单一线程执行时重新进入同一个子程序仍然是安全的。 ——可重入 一般在中断信号处理函数,不要写太多的业务逻辑。 我们经常把中断信号用于通知。 中断信号动作 每个信号都有相应的动作(信号处理程序): 用户自定义的中断信号处理程序 SIG_DEF 系统默认动作(结果一般都会让进程终止或是停止,终止+core) 忽略 SIG_IGN ignore 进程启动的时候,信号的动作默认是系统行为,如果编写对应处理程序,会覆盖掉默认动作,有些信号不可以覆盖,例如 SIGKILL、SIGSTOP。 信号处理程序的继承 当父进程创建一个子进程的时候,子进程是继承父进程的中断信号处理程序的。 function sigHandler($signo) { fprintf(STDOUT, "pid = %d,我接收到一个信号:%d \n", posix_getpid(), $signo); } pcntl_signal(SIGINT, 'sigHandler'); pcntl_signal(SIGUSR2,SIG_IGN); // 忽略信号 // SIGKILL、SIGSTOP 信号是无法捕捉的,编写的信号处理程序不会执行 // pcntl_signal(SIGKILL, 'sigHandler'); // pcntl_signal(SIGSTOP, 'sigHandler'); $pid = pcntl_fork(); while (1) { pcntl_signal_dispatch(); fprintf(STDOUT, "pid = %d, main process doing something ....

2022-03-15 10:57:49 · 王二

4-1 什么是中断信号(软中断)

中断信号 指软件中断信号,简称软中断。 中断信号处理程序(信号处理函数,信号捕捉函数)完以后,就会返回继续执行主程序。 中断是用以提高计算机工作效率、增强计算机功能的一项重要技术。最初引入硬件中断,只是出于性能上的考量。如果计算机系统没有中断,则处理器与外部设备通信时,它必须在向该设备发出指令后进行忙等待(Busy waiting),反复轮询该设备是否完成了动作并返回结果。这就造成了大量处理器周期被浪费。 引入中断以后,当处理器发出设备请求后就可以立即返回以处理其他任务,而当设备完成动作后,发送中断信号给处理器,后者就可以再回过头获取处理结果。这样,在设备进行处理的周期内,处理器可以执行其他一些有意义的工作,而只付出一些很小的切换所引发的时间代价。后来被用于CPU外部与内部紧急事件的处理、机器故障的处理、时间控制等多个方面,并产生通过软件方式进入中断处理(软中断)的概念。 ——中断 中断尽管可以提高计算机处理性能,但过于密集的中断请求/响应反而会影响系统性能。这类情形被称作中断风暴(interrupt storm)。 中断处理过程示意图 中断源 就是产生中断信号的单元。 在终端按下按键产生的中断信号 ctrl+c, ctrl+z, ctrl+\ 硬件异常 在终端使用 kill 来发送中断信号 posix_kill / kill(2) 函数、pcntl_alarm / alarm(2)函数 软件产生的中断信号 SIGURG [TCP/IP],SIGALRM 中断响应 对信号的处理。 忽略 执行中断处理函数(捕捉信号执行信号处理函数) 执行系统默认 signal ===> 动作[忽略,默认,执行用户编写好的信号处理函数] 中断返回 中断服务程序运行完之后返回。 信号对进程的影响: 直接让进程终止 让进程停止 SIGCONT 可以唤醒进程到前台继续运行 demo11.php <?php echo posix_getpid(); while (1){ ; } 发送 SIGSTOP 让进程停止之后 [1] Killed php demo11.php [2] Killed php demo11.php [3]+ Stopped php demo11.php $jobs [1]+ Stopped php demo11....

2022-03-09 11:27:09 · 王二

3-7 进程查看

一个程序启动之后就是一个进程,进程的数据在内存中,包括正文段和数据段,内存中的一些数据也会写入到proc文件系统中。 $ ll /proc/ total 4 dr-xr-xr-x 447 root root 0 Mar 8 06:31 ./ drwxr-xr-x 1 root root 4096 Mar 1 07:45 ../ dr-xr-xr-x 9 root root 0 Mar 8 11:43 1/ dr-xr-xr-x 9 root root 0 Mar 8 11:47 12/ dr-xr-xr-x 9 root root 0 Mar 8 11:47 21/ dr-xr-xr-x 9 root root 0 Mar 8 11:47 22/ dr-xr-xr-x 9 root root 0 Mar 8 11:47 23/ dr-xr-xr-x 9 root root 0 Mar 8 11:47 24/ dr-xr-xr-x 9 root root 0 Mar 8 11:47 3252/ dr-xr-xr-x 9 laradock laradock 0 Mar 8 11:47 499/ dr-xr-xr-x 9 root root 0 Mar 8 11:47 983/ top top - display Linux processes....

2022-03-08 15:20:35 · 王二

3-6 SUID特权进程

SUID、SGID 概念 The Unix access rights flags setuid and setgid (short for “set user ID” and “set group ID”) allow users to run an executable with the file system permissions of the executable’s owner or group respectively and to change behaviour in directories. They are often used to allow users on a computer system to run programs with temporarily(暂时、临时) elevated(提高) privileges in order to perform a specific task. While the assumed user id or group id privileges provided are not always elevated, at a minimum they are specific....

2022-03-08 10:19:25 · 王二

3-5多进程编写

多进程编写需要清楚的几个问题 创建了几个进程? 每个进程 $count 是多少? 每个进程从哪个地方开始运行代码的? fork 之后,每个进程的变量 $i, $count 的值是多少 ? 每个进程运行到哪一行语句结束? 示例一: 代码 <?php $count = 10; for ($i = 0; $i < 2; $i++){ $pid = pcntl_fork(); // step1-1 parent 创建子进程 child-1: count = 10, i = 0 // step3-1 cpu 调度 parent 创建子进程 child-2: count = 100, i = 1 // step5-1 cpu 调度 child-1 创建子进程 child-3: count = 11, i = 1 if ($pid == 0){ $count += 1; // step1-2 child-1 执行:count = 11, i = 1 // step4 child-2 执行: count = 101, i = 2 // child-2 最终结果:count = 101 // step6 child-3 执行:count = 12, i = 2 } else { $count *= 10; // step2 cpu 调度 parent:count = 100, i = 1 // step3-2 cpu 调度 parent:count = 1000, i = 2 for循环退出 // parent 最终结果:count = 1000 // step5-2 cpu 调度 child-1:count = 110, i = 2 // child-1 最终结果:count = 110 } } while(1){ fprintf(STDOUT, "pid=%d,count=%d\n", posix_getpid(), $count); sleep(3); } 分析: step1-1 parent 创建子进程 child-1:count = 10, i = 0...

2022-03-07 12:15:30 · 王二