gpt4 book ai didi

php - 为什么 pcntl_fork() 复制 PHP 对象?

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:41:43 24 4
gpt4 key购买 nike

pcntl_fork() 的手册说:

The pcntl_fork() function creates a child process that differs from the parent process only in its PID and PPID.

然而,运行这个简单的测试让我感到惊讶:

class Foo
{
public function bar()
{
if (pcntl_fork()) {
echo spl_object_hash($this), PHP_EOL;
} else {
echo spl_object_hash($this), PHP_EOL;
}
}
}

(new Foo)->bar();

结果如下:

000000005ec7fd31000000003f0fcfe6
000000006b4cd5fc000000007fee8ab7

根据文档所说,我希望父子共享相同的变量,特别是,当从一个对象中 fork() 时,我希望对对象的引用是在两个过程中相同。但上面的例子表明它们不是。

有趣的是,这里没有发生克隆,看起来对象只是被复制了。如果我添加一个 __clone() 函数,我可以看到它在 fork 期间没有被调用。

变量/对象不被两个进程共享的任何原因,或者关于主题人员的任何好的阅读?

最佳答案

对象的引用在forked进程中是相同的,因为对象在子进程的内存空间中的内存位置是相同的。

哈希计算为对象地址 XOR 随机掩码(仅生成一次),如您在 PHP 源代码 ext/spl/php_spl.c 中所读:

PHPAPI void php_spl_object_hash(zval *obj, char *result TSRMLS_DC) /* {{{*/
{
intptr_t hash_handle, hash_handlers;
char *hex;

if (!SPL_G(hash_mask_init)) {
if (!BG(mt_rand_is_seeded)) {
php_mt_srand(GENERATE_SEED() TSRMLS_CC);
}

SPL_G(hash_mask_handle) = (intptr_t)(php_mt_rand(TSRMLS_C) >> 1);
SPL_G(hash_mask_handlers) = (intptr_t)(php_mt_rand(TSRMLS_C) >> 1);
SPL_G(hash_mask_init) = 1;
}

hash_handle = SPL_G(hash_mask_handle)^(intptr_t)Z_OBJ_HANDLE_P(obj);
hash_handlers = SPL_G(hash_mask_handlers)^(intptr_t)Z_OBJ_HT_P(obj);

spprintf(&hex, 32, "%016x%016x", hash_handle, hash_handlers);

strlcpy(result, hex, 33);
efree(hex);
}
/* }}} */

如果随机数生成器在调用函数之前被播种,您将获得子进程和父进程完全相同的输出。但在这种情况下不是,每个进程都计算自己的种子。 GENERATE_SEED 的代码为:

#ifdef PHP_WIN32
#define GENERATE_SEED() (((long) (time(0) * GetCurrentProcessId())) ^ ((long) (1000000.0 * php_combined_lcg(TSRMLS_C))))
#else
#define GENERATE_SEED() (((long) (time(0) * getpid())) ^ ((long) (1000000.0 * php_combined_lcg(TSRMLS_C))))
#endif

如您所见,种子取决于进程 ID,这对于父进程和子进程当然是不同的。

因此,不同的随机数生成器种子、不同的随机掩码、不同的哈希值。

关于php - 为什么 pcntl_fork() 复制 PHP 对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15770453/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com