wxvirus wxvirus
首页
  • Go文章

    • Go语言学习
  • Rust

    • Rust学习
  • Java

    • 《Java》
  • Python文章

    • Python
  • PHP文章

    • PHP设计模式
  • 学习笔记

    • 《Git》
  • HTML
  • CSS
  • JS
  • 技术文档
  • GitHub技巧
  • 刷题
  • 博客搭建
  • 算法学习
  • 架构设计
  • 设计模式
  • 学习
  • 面试
  • 实用技巧
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

无解的lifecycle

let today = new Beginning()
首页
  • Go文章

    • Go语言学习
  • Rust

    • Rust学习
  • Java

    • 《Java》
  • Python文章

    • Python
  • PHP文章

    • PHP设计模式
  • 学习笔记

    • 《Git》
  • HTML
  • CSS
  • JS
  • 技术文档
  • GitHub技巧
  • 刷题
  • 博客搭建
  • 算法学习
  • 架构设计
  • 设计模式
  • 学习
  • 面试
  • 实用技巧
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • C&C++

  • PHP

    • PHP基础或常见方法

    • Laravel

    • ThinkPHP

    • PHP多进程编程

      • 程序与进程
      • PHP解释器的执行过程
      • 进程环境
      • 解释器文件
      • 进程标识与fork
        • 进程标识
          • 进程标识 id 号:pid
        • fork
          • fork 的一个工作流程
      • 进程退出
      • 进程exec
      • 进程调度
      • 多进程编写
      • SUID特权进程
      • 进程查看
      • 中断信号
      • 进程关系与守护进程
      • 进程组
      • 会话
      • 守护进程
      • 作业控制
      • 进程间通信
    • swoole

  • Python

  • Go

  • microservice

  • rust

  • Java

  • 学习笔记

  • 后端
  • PHP
  • PHP多进程编程
wxvirus
2022-04-04

进程标识与fork

# 进程标识

一个程序被加载到内存中运行,系统会为这个进程分配相应的标识信息,比如 pid,ppid,uid,euid,pgid,sid,egid...etc

# 进程标识 id 号:pid

使用php的posix_getpid函数来获取进程 id,此函数不能在windows下运行,必须在linux或者macos或者unix系统下运行才有效,否则会报错。

fprintf(STDOUT, "pid=%s\n", posix_getpid());
1

STDOUT:标准输出,对应屏幕终端

我们如果直接这样运行,会直接运行完就结束,我们加一个死循环,保持运行,来查看进程

fprintf(STDOUT, "pid=%s\n", posix_getpid());

while (1) {

}
1
2
3
4
5

使用pstree可以看出进程间的关系,父子,兄弟

├─sshd,1590 -D
  │   ├─sshd,26693
  │   │   ├─bash,27797
  │   │   │   └─php,29130 demo5.php
  │   │   ├─bash,29178
  │   │   │   └─pstree,29319 -ap
  │   │   └─sftp-server,26695
  │   └─sshd,29285

1
2
3
4
5
6
7
8
9

或者使用ps -exj来观察进程的运行状态,或者使用ps -aux

可以查看到对应的:PID、PPID、PGID、UID、TTY、STAT、TIME、COMMAND

27797 29130 29130 27797 pts/0    29130 R+       0   2:14 php demo5.php XDG_SESSION_ID=40751 HOSTNAME=VM-16-4-centos TERM=xterm-256color SHELL=/bin/b
1
  • R:运行状态
  • Z:僵尸状态
  • S:睡眠状态,可被唤醒
  • T:停止状态
  • D:也是睡眠,但是无法被唤醒
fprintf(STDOUT, "pid=%s\n", posix_getpid()); // 进程自己的标识
fprintf(STDOUT, "ppid=%s\n", posix_getppid()); // 父进程的标识
fprintf(STDOUT, "pgid=%s\n", posix_getpgrp()); // 进程组长的 id
fprintf(STDOUT, "sid=%s\n", posix_getsid(posix_getpid())); // 会话id
fprintf(STDOUT, "uid=%s\n", posix_getuid()); // 用户标识 是指当前登录用户 实际用户uid
fprintf(STDOUT, "gid=%s\n", posix_getgid()); // 当前组 组id
fprintf(STDOUT, "euid=%s\n", posix_geteuid()); // 有效用户euid
fprintf(STDOUT, "egid=%s\n", posix_getegid()); // 有效组egid

while (1) {

}
1
2
3
4
5
6
7
8
9
10
11
12
pid=31919
ppid=27797
pgid=31919
sid=27797	# 当前会话id,就是bash的id
uid=0 # 如果切换当前root用户这边数据就会发生变化
gid=0
euid=0
egid=0

1
2
3
4
5
6
7
8
9
├─sshd,1590 -D
  │   ├─sshd,26693
  │   │   ├─bash,27797
  │   │   │   └─php,31919 demo5.php
  │   │   ├─bash,29178
  │   │   │   └─pstree,31939 -ap

1
2
3
4
5
6
7

查看当前用户的组

[root@VM-16-4-centos process]# cat /etc/passwd
root:x:0:0:root:/root:/bin/bash

# 下面还有很多,就不多列

# 主要是这2个
0:0
1
2
3
4
5
6
7

# fork

php 官网文档地址 (opens new window)

pcntl_fork — 在当前进程当前位置产生分支(子进程)。译注:fork 是创建了一个子进程,父进程和子进程 都从 fork 的位置开始向下继续执行,不同的是父进程执行过程中,得到的 fork 返回值为子进程 号,而子进程得到的是 0。

pcntl_fork会执行两次,会返回两次

第一次执行可能是父进程

第二次执行可能是子进程

// fork pcntl_fork 函数
// 会返回2次,会执行2次
// 第一次执行可能是父进程
// 第二次执行可能是子进程
// 父进程运行
fprintf(STDOUT, "现在我的标识是: pid=%d\n", posix_getpid());
$pid = pcntl_fork();
// fork执行之后,本行会有两个进程运行,分别是子进程和父进程 a, b 【父进程从fork开始运行,子进行从下面的打印函数开始运行】
// 子进程前面的代码 它不会运行
fprintf(STDOUT, "pid = %d ppid=%d.\n", posix_getpid(), posix_getppid());

1
2
3
4
5
6
7
8
9
10
11

进程运行

  1. shell 终端输入 php demo5.php 之后
  2. 这个父进程会从 $pid = pcntl_fork(); 开始运行,执行 pcntl_fork 函数
  3. 这个函数执行成功之后,会创建一个子进程,子进程会复制父进程的代码段和数据段
  4. 然后父进程继续执行 fprintf(STDOUT, "pid = %d run here.\n", posix_getpid());
  5. 然后进程结束,子进程开始从 fprintf(STDOUT, "pid = %d run here.\n", posix_getpid()); 开始运行,执行打印语句
  6. 语句之后,进程结束
  7. 当父进程调用 pcntl_fork 之后,创建出来的子进程,这个时候就有两个进程,那么父进程和创建出来的子进程哪个进程先运行时无法确定的,也是无法知道的,是由操作系统来决定的,它的进程调度由系统决定
  8. 一般情况下,都是父进程先运行,子进程后运行;如果说父进程先运行,先结束,这个时候这个子进程就没有父亲了,这个时候它就成为了孤儿进程,这个时候它会被 1 号进程接管,就是系统进程,是所有进程的父亲
  9. 变成孤儿进程的后果:就是它跑到后台去运行了,它不在前台运行了。
  10. 所以我们一般让父进程后结束,先让子进程先运行
[root@VM-16-4-centos process]# php demo5.php
现在我的标识是: pid=12778
pid = 12778 ppid=27797.
pid = 12779 ppid=12778.

1
2
3
4
5

# fork 的一个工作流程

<?php

// fork pcntl_fork 函数
// 会返回2次,会执行2次
// 第一次执行可能是父进程
// 第二次执行可能是子进程
// 父进程运行
fprintf(STDOUT, "现在我的标识是: pid=%d\n", posix_getpid());
$pid = pcntl_fork(); // fork 之后,它是一个普通的变量,它是数据,子进程就能复制

// 最好把0写在前面
if (0 == $pid) {
    // 子进程运行的开始的地方
    fprintf(STDOUT, "pid=%d 我是子进程开始运行了\n", posix_getpid());
} else {
    // 父进程
    sleep(2); // 睡眠的目的是让子进程线运行,父进程先睡眠
    fprintf(STDOUT, "pid=%d 我是父进程睡了2秒才开始运行了\n", posix_getpid());
}

// fork执行之后,本行会有两个进程运行,分别是子进程和父进程 a, b 【父进程从24行开始运行,子进行从27行开始运行】
// 子进程前面的代码 它不会运行
// 子进程得到的数据 $pid 得到的结果是0
fprintf(STDOUT, "pid = %d ppid=%d.\n", posix_getpid(), posix_getppid());

// 这一行结束
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
现在我的标识是: pid=25091
pid=25092 我是子进程开始运行了
pid = 25092 ppid=25091.
pid=25091 我是父进程睡了2秒才开始运行了
pid = 25091 ppid=25003.

1
2
3
4
5
6

这个才是一个正常的结束。

注意

父进程必须先让子进程先结束!如果说父进程先结束,子进程被 1 号线程接管,变成孤儿进程。

如果说子进行先结束,父进程后结束,这种情况一般来说是正常的,但是父进程应该回收子进程。

也就是子进程结束时,还会生成一些数据,比如状态码等其他信息,并没有完全释放,需要父进程回收。

fork流程

COW 技术

COW

if (0 == $pid) {
    // 子进程运行的开始的地方
    fprintf(STDOUT, "pid=%d 我是子进程开始运行了\n", posix_getpid());
    fprintf(STDOUT, "子进程变量pid = %d\n", $pid);
} else {
    // 父进程
    sleep(2); // 睡眠的目的是让子进程线运行,父进程先睡眠
    fprintf(STDOUT, "pid=%d 我是父进程睡了2秒才开始运行了\n", posix_getpid());
    fprintf(STDOUT, "父进程变量pid = %d\n", $pid);
}
1
2
3
4
5
6
7
8
9
10

子进程的$pid为 0

[root@VM-16-4-centos process]# php demo5.php
现在我的标识是: pid=29330
pid=29331 我是子进程开始运行了
子进程变量pid = 0
pid = 29331 ppid=29330.
pid=29330 我是父进程睡了2秒才开始运行了
父进程变量pid = 29331
pid = 29330 ppid=25003.

1
2
3
4
5
6
7
8
9
编辑 (opens new window)
上次更新: 2022/04/04, 13:16:02
解释器文件
进程退出

← 解释器文件 进程退出→

最近更新
01
vue3配合vite初始化项目的一些配置
07-26
02
网盘系统开发学习
07-24
03
linux多进程
06-19
更多文章>
Theme by Vdoing | Copyright © 2021-2024 wxvirus 苏ICP备2021007210号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式