php进程间传递文件描述符

6 篇文章 0 订阅

 进程间传递文件描述符有什么实际应用场景呢?


-  最近看到golang中关于服务器平滑热重启reload时,需要长链接不被断开,需要fork一个子进程出来,然后把父进程的所有socket的文件 描述符(即:所有hold的客户端连接)都传递到子进程。在没研究linux进程间传递文件描述符之前,我的脑海里只有fork时,发生copy-on-write,父子进程间直接就可以共享连接fd了,但是这个时候,如果父进程退出,那所有的连接也被掐断了,因为父子进程共享连接资源了。所以需要将fd关联到的资源完整的clone到子进程中,使得父子进程对应的fd完全脱离关系,不过fd从父进程copy到子进程之后,想要fd值(int)都保持一致,不太可能,因为子进程要重新分配fd的。
 

 

如何实现进程间传递fd呢?

- 大概就是通过unixsockt,一端sendmsg, 另外一端recvmsg,但是不是简单的传输消息内容,需要告诉内核传输的是文件描述符 SCM_RIGHTS。 下面直接给出php版本的demo

<?php

$fds = [];
$ret = socket_create_pair(AF_UNIX, SOCK_DGRAM, 0, $fds);
if (!$ret) {
    exit(socket_strerror(socket_last_error()));
}
$pid = pcntl_fork();
if ($pid > 0) {
    socket_close($fds[0]);
    $handle = fopen(__DIR__ . '/atomic.txt', 'a+');
    var_dump($handle);
    socket_sendmsg($fds[1], [
        'control' => [
            [
                'level' => SOL_SOCKET,
                'type'  => SCM_RIGHTS,
                'data'  => [$handle]
            ]
        ]
    ], 0);
    sleep(1);
} else {
    socket_close($fds[1]);
    $data = [
        'controllen' => socket_cmsg_space(SOL_SOCKET, SCM_RIGHTS, 1)
    ];
    $result = socket_recvmsg($fds[0], $data, 0);
    var_dump("recv ok\n");
    var_dump($data['control'][0]['data'][0]);
    fwrite($data['control'][0]['data'][0], 'passing fd in PHP' . PHP_EOL);
}

上述代码中,父进程var_dump($handle),和子进程var_dump($data['control'][0]['data'][0]); 两次打印的resource资源类型int值已经变化了,说明fd已经完整clone过去,父进程退出,也不会影响子进程的这个fd了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值