PHP 大会日本 2024

ftok

(PHP 4 >= 4.2.0, PHP 5, PHP 7, PHP 8)

ftok将路径名和项目标识符转换为 System V IPC 密钥

描述

ftok(字符串 $filename, 字符串 $project_id): 整数

该函数将现有可访问文件的$filename和项目标识符转换为一个整数,例如用于shmop_open()和其他 System V IPC 密钥。

参数

filename

可访问文件的路径。

project_id

项目标识符。这必须是一个单字符字符串。

返回值

成功时,返回值将是创建的密钥值,否则返回-1

参见

添加注释

用户贡献的注释 6 个注释

abk at avatartechnology dot com
20 年前
感谢 [email protected],他从 linux glibc 2.3.2 获取了此信息:https://php.net/manual/en/function.shmop-open.php -- 我把它放在这里,因为它可能对其他人有所帮助。

function ftok($pathname, $proj_id) {
$st = @stat($pathname);
if (!$st) {
return -1;
}

$key = sprintf("%u", (($st['ino'] & 0xffff) | (($st['dev'] & 0xff) << 16) | (($proj_id & 0xff) << 24)));
return $key;
}
vlatko dot surlan at evorion dot hr
11 年前
ftok 与 shm 相关函数(如 shmop_open 和 shm_attach)的用法相当不直观,可以简单地解释为避免 shm 密钥冲突的需要。使用属于您项目的文件的 ftok 可能会生成唯一的密钥。此外,使用您项目中的文件的 ftok 可以避免存储密钥,以便其他进程可以访问该段,因为如果您传递相同的文件,ftok 将始终为您提供相同的密钥。
david dot rech at virusmedia dot de
20 年前
Windows 上缺少 ftok()?这是我的一点解决方法

<?php
if( !function_exists('ftok') )
{
function
ftok($filename = "", $proj = "")
{
if( empty(
$filename) || !file_exists($filename) )
{
return -
1;
}
else
{
$filename = $filename . (string) $proj;
for(
$key = array(); sizeof($key) < strlen($filename); $key[] = ord(substr($filename, sizeof($key), 1)));
return
dechex(array_sum($key));
}
}
}
?>

注意:即使概率很低,也*可能*存在重复的密钥。

密钥的计算方式与原始的 UNIX ftok() 不同,因为例如 fileinode() 在 Windows 上也缺失。通常,ftok() 会根据文件 inode 和文件所在的硬盘的系统次要 ID 计算密钥。

行为类似于 PHP 的 ftok(),如果文件丢失或 $filename 为空,则返回 -1,成功时计算的整数为十六进制。

--
此致,
David Rech
mbowie at buzmo dot com
20 年前
如果您计划使用 ftok() 生成要与其他应用程序共享的 IPC 标识符,请注意 PHP 使用 proj 参数的 ASCII 值生成密钥,而不是 proj(也称为 id)参数本身。

这样做的结果是,如果您在 PHP 端使用“1”作为 id,则需要在其他地方使用 49。

在所有操作系统上可能并非如此,但对于 FreeBSD 来说确实如此,FreeBSD 要求传递给 ftok 的 id 参数为整数。

还要注意的是,ipcs 和 ipcrm 对调试 SysV 队列等非常有用。

参考
https://freebsd.ac.cn/cgi/man.cgi?query=ftok
http://www.asciitable.com
seelts at gmail dot com
9 年前
[email protected] 复制了 [email protected] 的代码
但它不正确。
正确的版本在这里
<?php
function ftok ($filePath, $projectId) {
$fileStats = stat($filePath);
if (!
$fileStats) {
return -
1;
}

return
sprintf('%u',
(
$fileStats['ino'] & 0xffff) | (($fileStats['dev'] & 0xff) << 16) | ((ord($projectId) & 0xff) << 24)
);
}
?>

不同之处在于 $projectId 字符串应通过 ord() 函数用作 ASCII 值。否则它将被解释为 0。
marco at greenlightsolutions dot nl
17 年前
由于 ftok 仅使用文件的 inode 的最后 16 位,因此您可能会在大型文件系统上发生冲突。不幸的是,在大型文件系统上,您可能会很快发生冲突:如果您有 350-400 个文件的集合,则其中两个文件的 inode 具有相同的最后 16 位的可能性很大。因此,我开始使用 fileinode 而不是 ftok 与 shmop_open 等函数一起使用。
To Top