【问题标题】:How to clear shared memory using php?如何使用 php 清除共享内存?
【发布时间】:2014-06-20 04:37:56
【问题描述】:

我想问一下,为什么我使用了 shmop_delete($shmid) 和 shmop_close($shmid) 之后什么都没有发生?第一个字符串仍然附加。

这是我的 php 代码: $key = 864; $模式 = 'c'; $权限 = 0644; $size = 1024;

$shmid = shmop_open($key, $mode, $permission, 1024);

$string = "Hello World !!!";

shmop_write($shmid, $string, 0);

$size = shmop_size($shmid);
echo shmop_read($shmid, 0, $size);

shmop_delete($shmid);
shmop_close($shmid);

第一个结果:Hello World !!!

然后我更改 $string = "TEST"。

之后,我再次运行代码,结果为:TESTo World !!!(不需要的结果)。 我想要的结果是:TEST

为什么是 'o World !!!'虽然我已经做了 shmop_delete 和 shmop_close,但它仍然是附加的?以及如何从共享内存中删除它?谢谢...

【问题讨论】:

    标签: php shared-memory


    【解决方案1】:

    当您第一次编写“Hello World”时,它会写入这 11 个字符的长度。写入“Test”时,只会将“Test”的长度写入共享内存。这就是为什么其余的字符串仍然连接着的原因。一种可能的解决方案是采用如下所示的长度:

    $shm_bytes_written = shmop_write($shmid, $string, 0);

    并将下一个字符串填充到该长度。或者我猜你可以写出整个共享块的大小,但这可能不是你想要的。

    编辑:

    代码应该是这样的(未经测试或编译)。这是针对 ASCII 的。如果您使用的是 UTF-8,则需要以稍微不同的方式获取字符串长度。希望你能明白

    $shmid = shmop_open($key, $mode, $permission, 1024);
    
    $string = "Hello World !!!";
    
    $s1bytes = strlen( $string );
    
    $shm_bytes_written = shmop_write($shmid, $string, 0);
    
    $string2 = "Test";
    
    $padLen = strlen( $string ) - strlen( $string2 );
    
    $s2Pad = str_pad( "Test", $padLen );
    
    $shm_bytes_written = shmop_write($shmid, $s2Pad, 0);
    
    $size = shmop_size($shmid);
    echo shmop_read($shmid, 0, $size);
    
    shmop_delete($shmid);
    shmop_close($shmid);
    

    【讨论】:

    • 实际上我想要做的是用第二个字符串覆盖共享内存中的第一个字符串。但问题是如果第一个字符串长度大于第二个字符串长度,如何用第二个字符串覆盖共享内存中的第一个字符串?如何覆盖它而不留下第一个字符串的任何痕迹。谢谢。
    【解决方案2】:

    我从php.net shmop_read's comment by Craig Manley得到了一个解决方案

    演示代码,“hello”覆盖“helloworld”:

    $shmid = shmop_open(10014, "c", 0755, 2048);
    $size = shmop_size($shmid);
    $write = "helloworld";
    $writeStr = str_to_nts($write);
    shmop_write($shmid,$writeStr, 0);
    $str = shmop_read($shmid, 0, $size);
    $rawStr =  str_from_mem($str);
    $oldLengh = mb_strlen($rawStr, '8bit');
    echo $rawStr . "\n";
    echo $oldLengh . "\n";
    
    $writeStr = "hello";
    shmop_write($shmid, str_to_nts($writeStr), 0);
    $str = shmop_read($shmid, 0, $size);
    $rawStr =  str_from_mem($str);
    $newLengh = mb_strlen($rawStr, '8bit');
    echo $rawStr . "\n";
    echo $newLengh . "\n";
    shmop_delete($shmid);
    shmop_close($shmid);
    

    定义:

    function str_from_mem(&$value) {
        $i = strpos($value, "\0");
        if ($i === false) {
            return $value;
        }
        $result =  substr($value, 0, $i);
        return $result;
    }
    function str_to_nts($value) {
        return "$value\0";
    }
    

    正如 Craig Manley 的评论:shmop_read() 读取并返回整个内存段的数据。如果您只是使用字符串,这将没有用。

    【讨论】:

    • 但此解决方案仍然“从第一个字符串中留下任何痕迹”。但是,您可以通过 '\0' 结尾获得正确的字符串。
    猜你喜欢
    • 2011-11-11
    • 1970-01-01
    • 2013-05-21
    • 1970-01-01
    • 2014-04-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-14
    相关资源
    最近更新 更多