守护进程

守护进程作为一种常驻进程服务,很常见,例如 PHP-FPM, NGINX,REDIS,都需要一个父进程来支持整个服务。但是用 PHP 编写守护进程不多见,今天就来用 PHP 来实现一下。

步骤

● fork 子进程

● 父进程退出

● 设置新的会话

● 重置文件掩码

● 关闭标准输入输出

实现

我们对着以上的步骤来实现,在这之前需要 pcntl 和 posix 扩展,请确保安装了。

function daemon() {    $pid = pcntl_fork();    // fork 失败    if ($pid < 0) {        exit('fork failed');    } else if ($pid > 0) {       // 退出父进程        exit(0);    }    // 设置新的会员    // setsid 有几个注意点    // 不能是进程组的组长调用    // 对于进程组组员调用会产生新的会话和进程组,并成为该进程组的唯一成员,调用的进程将脱离终端    if (posix_setsid() < 0) {        exit('set sid failed');    }    // 重置文件掩码    umask(0);    // 切换工作目录    chdir('/');    // 关闭标准输入输出    fclose(STDIN);    fclose(STDOUT);    fclose(STDERR);}

细节

// 获取进程IDvar_dump(posix_getpid());// 获取进程组IDvar_dump(posix_getpgid(posix_getpid()));// 获取进程会话ID    var_dump(posix_getsid(posix_getpid()));

三者结果相同,说明了该进程即使进程组的组长,也是会话首领。

为什么需要 umask (0)

当你在 linux 调用 umask 的时候你会看到一个掩码值,这个掩码决定了你创建文件权限范围,例如本人当前机器的 umask 为

0022

文件的最大权限是 0666,而目录的最大权限是 0777, 那么当前用户的创建的目录权限就是 0755,对于当前用户而言就是 rwx-rx-rx 权限。而文件则是 0644,对于当前用户而言 rw-r-r 权限。所以如果没有重置掩码的话,那么对于目录而言就是 0755,而文件则是 0644 了。

注意

如果你在进程使用了 echo var_dump 等函数,一定要把标准输出等重定向到其他文件流中。新增加下面代码就可以了。

global $stdin, $stdout, $stderr;$stdin = fopen('/dev/null', 'r');$stdout = fopen('/www/php/txt.txt','wb');$stderr = fopen('/dev/null', 'wb');

因为在上面已经关闭了标准输入输出,此时文件描述符 fd 已经没有,所有重新打开之后 fd 从非负开始依次是 0,1,2。正好作为标准输入输出的文件。当然重定向到那里需要你自己设置。

最后的二次 fork

这个问题需要好好斟酌,因为是非必须的。目前想不到有什么场景下必须两次 Fork。

更多相关文章

  1. php文件上传步骤是什么
  2. php如何获取上传文件大小
  3. php引入文件的四个方法
  4. PHP实时生成并下载超大数据量的EXCEL文件
  5. PHP实现文件上传下载实例详细讲解
  6. php怎么启动exe文件
  7. PHP高性能Excel扩展1.2.8发布,文件读取数据类型可控!
  8. PHP 中使用 TUS 协议来实现大文件的断点续传
  9. php实现共享内存进程通信函数之shm

随机推荐

  1. golang 引用和指针的区别
  2. golang 内存泄露的原因
  3. golang 为什么高并发
  4. golang 默认几核运行
  5. golang 适合做web开发吗
  6. golang可以跨平台吗
  7. golang 是什么写的
  8. golang 开发效率高么
  9. golang 什么时候用锁
  10. golang如何设置时间