共享内存函数

目录

添加注释

用户贡献的注释 8 个注释

Craig Manley
19 年前
由于这里没有提到(缺乏)锁定需求,所以我查看了 shmop.c 扩展代码。所以,如果我错了,请纠正我,但是 shmop.c 扩展使用 memcpy() 将字符串复制到共享内存中,而无需任何形式的锁定,据我所知,memcpy() 不是原子操作。

如果像我怀疑的那样属实,那么这些“易于使用”的函数就不再那么“易于使用”了,必须用锁(例如信号量、flocks 等)来包装。
joeldg at gmail.com
18 年前
我在 2003 年写了一个 php memcache,作为一种概念验证。
它用于一些机器上进行繁重的页面负载缓存...
它运行良好。
以下是一些我制作的核心函数

<?php
###############################################
#### 共享内存函数
/*
用于调试这些
使用 `ipcs` 查看当前内存
使用 `ipcrm -m {shmid}` 移除
在某些系统上使用 `ipcclean` 清理未使用的内存,如果您
不想手动操作
*/
###############################################
function get_key($fsize, $file){
if(!
file_exists(TMPDIR.TMPPRE.$file)){
touch(TMPDIR.TMPPRE.$file);
}
$shmkey = @shmop_open(ftok(TMPDIR.TMPPRE.$file, 'R'), "c", 0644, $fsize);
if(!
$shmkey) {
return
false;
}else{
return
$shmkey;
}
//fi
}
function
writemem($fdata, $shmkey){
if(
MEMCOMPRESS && function_exists('gzcompress')){
$fdata = @gzcompress($fdata, MEMCOMPRESSLVL);
}
$fsize = strlen($fdata);
$shm_bytes_written = shmop_write($shmkey, $fdata, 0);
updatestats($shm_bytes_written, "add");
if(
$shm_bytes_written != $fsize) {
return
false;
}else{
return
$shm_bytes_written;
}
//fi
}
function
readmem($shmkey, $shm_size){
$my_string = @shmop_read($shmkey, 0, $shm_size);
if(
MEMCOMPRESS && function_exists('gzuncompress')){
$my_string = @gzuncompress($my_string);
}
if(!
$my_string) {
return
false;
}else{
return
$my_string;
}
//fi
}
function
deletemem($shmkey){
$size = @shmop_size($shmkey);
if(
$size > 0){ updatestats($size, "del"); }
if(!@
shmop_delete($shmkey)) {
@
shmop_close($shmkey);
return
false;
}else{
@
shmop_close($shmkey);
return
true;
}
}
function
closemem($shmkey){
if(!
shmop_close($shmkey)) {
return
false;
}else{
return
true;
}
}
function
iskey($size, $key){
if(
$ret = get_key($size, $key)){
return
$ret;
}else{
return
false;
}
}
################################################
?>
Roy <roy AT enhost.com>
18 年前
我已经编写了一个脚本以突出显示共享内存存储的优越性。
虽然它没有使用 shmop 函数,但底层概念是类似的。
'/shm_dir/' 是一个 tmpfs 目录,它基于共享内存,我已将其安装在服务器上。

以下是 Intel Pentium VI 2.8 服务器上的结果

对 1000 个文件的 IO 测试
常规目录的 IO 结果:0.079015016555786
共享内存目录的 IO 结果:0.047761917114258

对 10000 个文件的 IO 测试
常规目录的 IO 结果:3.7090260982513
共享内存目录的 IO 结果:0.46256303787231

对 40000 个文件的 IO 测试
常规目录的 IO 结果:117.35703110695 秒
共享内存目录的 IO 结果:2.6221358776093 秒

100 个文件时差异并不明显也不令人信服。
但是当我们将数量提升到 10000 和 40000 个文件时,很明显共享内存是一个更好的竞争者。

脚本由 http://www.enhost.com 提供

<?php
set_time_limit
(0);

// 您的常规目录。确保它具有写入权限
$setting['regular_dir'] = '/home/user/regular_directory/';

// 您的共享内存目录。
$setting['shm_dir'] = '/shm_dir/';

// 要读取和写入的文件数量
$setting['files'] = 40000;

function
IO_Test($mode)
{
$starttime = time()+microtime();

global
$setting;

for(
$i = 0 ; $i< $setting['files'] ;$i++)
{
$filename = $setting[$mode].'test'.$i.'.txt';
$content = "Just a random content";

// 只是一些错误检测
if (!$handle = fopen($filename, 'w+'))
{
echo
"无法打开文件 ".$filename;
exit;
}

if (
fwrite($handle, $content ) === FALSE)
{
echo
"无法写入文件 : ".$filename;
exit;
}

fclose($handle);

// 读取测试
file_get_contents($filename);

}

$endtime = time()+microtime();

$totaltime = ($endtime - $starttime);

return
$totaltime;

}

echo
'<b>对 '.$setting['files']. ' 个文件进行 IO 测试</b><br>';
echo
'<b>常规</b> 目录的 IO 结果 : '.IO_Test('regular_dir') .' 秒<br>';
echo
'<b>共享内存</b> 目录的 IO 结果 : '.IO_Test('shm_dir') .' 秒<br>';

/* 删除文件以避免低估
#
# 无法删除文件将导致基准测试不准确
# 因为它会导致 IO_Test 函数不会重新创建现有的文件
*/
foreach ( glob($setting['regular_dir']."*.txt") as $filename) {
unlink($filename);$cnt ++;
}
foreach (
glob($setting['shm_dir']."*.txt") as $filename) {
unlink($filename);$cnt ++;
}

?>
hackie at prohost dot org
18 年前
提供锁定的功能不是 shmop 扩展的工作,有许多锁定方案可用,如果您需要某种原子操作,请选择适合您的锁定方案并使用它。
stoimenov at email dot com
22 年前
Windows 通过内存映射文件支持共享内存。查看以下函数以了解更多详细信息

* CreateFileMapping
* MapViewOfFile
Arikania
6 年前
在这个帮助页面中描述的 shmop 实现实际上仅仅是仅存在于 php 中的 ramdisk/tmpfs,甚至只存在于 linux 服务器上。或者我遗漏了什么吗?

在 windows 上,可以通过创建这样的磁盘轻松实现相同的功能。

事实上,在我的服务器上,我使用 tmpfs 磁盘而不是 - 就我看来 - 有限的 shmop 功能。

为什么不实现一个 $_SHARED 或 $_MUTUAL 超级全局变量,我们可以在其中随意创建变量,并且它由所有连接共享?

这将极大地提高许多 PHP 应用程序的性能,并可以节省服务器内存的负担。特别是如果这些变量可以是包含函数的类。

您可以实现它是由程序员来保证原子性。

这样的超级全局变量在 windows 服务器上也是可行的。
rei at prohost dot org
23 年前
SHMOP 背后的理念是易于使用的共享内存接口,
无需在共享内存段中添加任何额外的标头
或需要任何特殊的特殊控件来访问共享内存
段在 PHP 之外。SHMOP 从 C 的 shm api 中借鉴了它的 api,
这使得它非常易于使用,因为它将共享内存像 C 一样视为
一种文件。这使得它即使对于新手来说也非常容易使用,因为
功能。最重要的是 SHMOP 使用 shm 段来存储原始数据,
这意味着当您使用
C、perl 或其他编程语言来打开/创建/读取/写入 shm 段时,您无需担心匹配标头等
由 PHP 创建或将要由 PHP 使用。在这方面,它不同于
sysvshm,其 shm 接口使用一个专门的标头,它驻留在
共享内存段中,这在您
想要从外部程序访问 php shm 时增加了一层不必要的难度。
此外,从我在 Linux 2.2/2.4 和 FreeBSD 3.3 中的个人测试来看,SHMOP 比 sysvshm 快约
20%,主要是因为它不需要解析
专门的标头,并将数据存储为原始形式。
slavapl at mailandnews dot com
23 年前
您需要意识到的是,sysvshm 在其能力方面极度面向 php,它与其他非 PHP 实用程序的接口非常混乱。例如,您是否尝试过使用 sysvshm 来读取非 php 创建的 shm 段?这是不可能的,因为 sysvshm 使用一种专有格式,本质上它只能在 PHP 中使用,当然除非您花时间弄清楚这种格式。
因此,基本上,shmop 的目的是提供一个简单的共享内存接口,可以与其他非 php shm 创建器一起使用。

希望这能澄清。
To Top