PHP 中的共享内存文件

发布于 2024-11-01 01:52:29 字数 360 浏览 1 评论 0原文

我使用 openssl_pkcs7_signopenssl_pkcs7_encrypt 创建加密数据。这些函数仅接受文件名。我想将临时文件存储在共享内存中以提高性能。据我了解,在 Linux 中我可以 file_put_contents('/dev/shm/xxx', data),但在 Windows 中则不可能。 PHP 中有可移植的方法来做到这一点吗? shmop_ 函数在这里有帮助吗?谢谢。

PS:或者有没有办法让这些函数接受数据字符串?

PS2:请不要建议从 PHP 调用 /usr/bin/openssl。它不便于携带。

I use openssl_pkcs7_sign and openssl_pkcs7_encrypt to create encrypted data. The functions only accept file names. I would like to store the temporary files in shared memory to improve performance. I understand in Linux I can file_put_contents('/dev/shm/xxx', data), but it is not possible for Windows. Is there portable way in PHP to do this? Would shmop_ function help here? Thanks.

PS: Or is there way to make these functions accept data strings?

PS2: Please do not suggest invoking /usr/bin/openssl from PHP. It is not portable.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

泛滥成性 2024-11-08 01:52:29

好的,所以我建议这样做的方法是使用文件 流包装器。让我举一个简单的例子:

class staticStreamWrapper {
    public $context;
    protected static $data = array();

    protected $path    = '';
    protected $pointer = 0;
    protected $writable = false;

    public function stream_close() {}

    public function stream_eof() {
        return $this->pointer >= strlen(static::$data[$this->path]);
    }

    public function stream_flush() {}

    public function stream_open($path, $mode, $options, &$opened_path) {
        switch ($mode[0]) {
            case 'r':
                if (!isset(static::$data[$path])) return false;
                $this->path = $path;
                $this->writable = isset($mode[1]) && $mode[1] == '+';
                break;
            case 'w':
                static::$data[$path] = '';
                $this->path = $path;
                $this->writable = true;
                break;
            case 'a':
                if (!isset(static::$data[$path])) static::$data[$path] = '';
                $this->path = $path;
                $this->writable = true;
                $this->pointer = strlen(static::$data[$path]);
                break;
            case 'x':
                if (isset(static::$data[$path])) return false;
                $this->path = $path;
                $this->writable = true;
                break;
            case 'c':
                if (!isset(static::$data[$path])) static::$data[$path] = '';
                $this->path = $path;
                $this->writable = true;
                break;
            default:
                return false;
        }
        $opened_path = $this->path;
        return true;
    }
   
    public function stream_read($count) {
        $bytes = min(strlen(static::$data[$this->path]) - $this->pointer, $count);
        $data = substr(static::$data[$this->path], $this->pointer, $bytes);
        $this->pointer += $bytes;
        return $data;
    }

    public function stream_seek($offset, $whence = SEEK_SET) {
        $len = strlen(static::$data[$this->path]);
        switch ($whence) {
            case SEEK_SET:
                if ($offset <= $len) {
                    $this->pointer = $offset;
                    return true;
                }
                break;
            case SEEK_CUR:
                if ($this->pointer + $offset <= $len) {
                    $this->pointer += $offset;
                    return true;
                }
                break;
            case SEEK_END:
                if ($len + $offset <= $len) {
                    $this->pointer = $len + $offset;
                    return true;
                }
                break;
        }
        return false;
    }

    public function stream_stat() {
        $size = strlen(static::$data[$this->path]);
        $time = time();
        return array(
            0 => 0,
            'dev' => 0,
            1 => 0,
            'ino' => 0,
            2 => 0777,
            'mode' => 0777,
            3 => 1,
            'nlink' => 1,
            4 => 0,
            'uid' => 0,
            5 => 0,
            'gid' => 0,
            6 => '',
            'rdev' => '',
            7 => $size,
            'size' => $size,
            8 => $time,
            'atime' => $time,
            9 => $time,
            'mtime' => $time,
            10 => $time,
            'ctime' => $time,
            11 => -1,
            'blksize' => -1,
            12 => -1,
            'blocks' => -1,
        );
    }

    public function stream_tell() {
        return $this->pointer;
    }

    public function stream_write($data) {
        if (!$this->writable) return 0;
        $size = strlen($data);
        $len = strlen(static::$data[$this->path]);
        if ($this->stream_eof()) {
            static::$data[$this->path] .= $data;
        } else {
            static::$data[$this->path] = substr_replace(
                static::$data[$this->path],
                $data,
                $this->pointer
            );
        }
        $this->pointer += $size;
        return $size;
    }

    public function unlink($path) {
        if (isset(static::$data[$path])) {
            unset(static::$data[$path]);
        }
        return true;
    }

}

现在,您需要注册包装器:

stream_wrapper_register('static', 'staticStreamWrapper');

所以您现在可以将它视为一个文件,即使它从未真正离开 PHP(它存储为静态变量)!

file_put_contents('static://foo.txt', 'this is my data');
file_get_contents('static://foo.txt'); // "this is my data"
$f = fopen('static://foo.txt', 'r'); // should return a resource
// etc...

Ok, so the way I would suggest doing this is with a file stream wrapper. Let me whip up a quick example:

class staticStreamWrapper {
    public $context;
    protected static $data = array();

    protected $path    = '';
    protected $pointer = 0;
    protected $writable = false;

    public function stream_close() {}

    public function stream_eof() {
        return $this->pointer >= strlen(static::$data[$this->path]);
    }

    public function stream_flush() {}

    public function stream_open($path, $mode, $options, &$opened_path) {
        switch ($mode[0]) {
            case 'r':
                if (!isset(static::$data[$path])) return false;
                $this->path = $path;
                $this->writable = isset($mode[1]) && $mode[1] == '+';
                break;
            case 'w':
                static::$data[$path] = '';
                $this->path = $path;
                $this->writable = true;
                break;
            case 'a':
                if (!isset(static::$data[$path])) static::$data[$path] = '';
                $this->path = $path;
                $this->writable = true;
                $this->pointer = strlen(static::$data[$path]);
                break;
            case 'x':
                if (isset(static::$data[$path])) return false;
                $this->path = $path;
                $this->writable = true;
                break;
            case 'c':
                if (!isset(static::$data[$path])) static::$data[$path] = '';
                $this->path = $path;
                $this->writable = true;
                break;
            default:
                return false;
        }
        $opened_path = $this->path;
        return true;
    }
   
    public function stream_read($count) {
        $bytes = min(strlen(static::$data[$this->path]) - $this->pointer, $count);
        $data = substr(static::$data[$this->path], $this->pointer, $bytes);
        $this->pointer += $bytes;
        return $data;
    }

    public function stream_seek($offset, $whence = SEEK_SET) {
        $len = strlen(static::$data[$this->path]);
        switch ($whence) {
            case SEEK_SET:
                if ($offset <= $len) {
                    $this->pointer = $offset;
                    return true;
                }
                break;
            case SEEK_CUR:
                if ($this->pointer + $offset <= $len) {
                    $this->pointer += $offset;
                    return true;
                }
                break;
            case SEEK_END:
                if ($len + $offset <= $len) {
                    $this->pointer = $len + $offset;
                    return true;
                }
                break;
        }
        return false;
    }

    public function stream_stat() {
        $size = strlen(static::$data[$this->path]);
        $time = time();
        return array(
            0 => 0,
            'dev' => 0,
            1 => 0,
            'ino' => 0,
            2 => 0777,
            'mode' => 0777,
            3 => 1,
            'nlink' => 1,
            4 => 0,
            'uid' => 0,
            5 => 0,
            'gid' => 0,
            6 => '',
            'rdev' => '',
            7 => $size,
            'size' => $size,
            8 => $time,
            'atime' => $time,
            9 => $time,
            'mtime' => $time,
            10 => $time,
            'ctime' => $time,
            11 => -1,
            'blksize' => -1,
            12 => -1,
            'blocks' => -1,
        );
    }

    public function stream_tell() {
        return $this->pointer;
    }

    public function stream_write($data) {
        if (!$this->writable) return 0;
        $size = strlen($data);
        $len = strlen(static::$data[$this->path]);
        if ($this->stream_eof()) {
            static::$data[$this->path] .= $data;
        } else {
            static::$data[$this->path] = substr_replace(
                static::$data[$this->path],
                $data,
                $this->pointer
            );
        }
        $this->pointer += $size;
        return $size;
    }

    public function unlink($path) {
        if (isset(static::$data[$path])) {
            unset(static::$data[$path]);
        }
        return true;
    }

}

Now, you would then need to register the wrapper:

stream_wrapper_register('static', 'staticStreamWrapper');

So you now can treat it like a file even though it never actually leaves PHP (it's stored as a static variable)!

file_put_contents('static://foo.txt', 'this is my data');
file_get_contents('static://foo.txt'); // "this is my data"
$f = fopen('static://foo.txt', 'r'); // should return a resource
// etc...
跨年 2024-11-08 01:52:29

从 Windows 2000 开始,可以使用 shmop(以前的 shm_)方法。

shmop_open 使用唯一的整数键来共享内存区域。 ftok 可用于根据文件路径(通常是脚本文件的完整路径)生成唯一索引。共享相同密钥的任何实例都可以共享相同的内存。

http://php.net/manual/en/ref.shmop.php

在 Zend Server CE 的 PHP 版本 5.3.3 上进行测试
系统 Windows NT CRYPE 6.1 build 7601(未知 Windows 版本 Business Edition Service Pack 1) i586

<?php
$key = ftok(__FILE__, 't');
$memory = shmop_open($key, "c", 0600, 16 * 1024);
$data = array('data' => 'value');
$bytes = shmop_write($memory, serialize($data), 0);
$return = shmop_read($memory, 0, $bytes);
print_r(unserialize($return));
?>

shmop_read/shmop_write 存储字符串中的原始字节,因此不需要序列化它,但您需要在某处写入字符串的长度。我的示例创建了一个 16KB 共享内存区域,您当然可以调整它的大小以适合 openssl 文件加上存储文件大小所需的空间。

Since Windows 2000, the shmop (previously shm_) methods are available.

shmop_open uses a unique integer key to share the memory area. ftok can be used to produce a unique index based on a file path (typically your script file's full path). Any instance that shares the same key can share the same memory.

http://php.net/manual/en/ref.shmop.php

Tested on PHP Version 5.3.3 from Zend Server CE
System Windows NT CRYPE 6.1 build 7601 (Unknow Windows version Business Edition Service Pack 1) i586

<?php
$key = ftok(__FILE__, 't');
$memory = shmop_open($key, "c", 0600, 16 * 1024);
$data = array('data' => 'value');
$bytes = shmop_write($memory, serialize($data), 0);
$return = shmop_read($memory, 0, $bytes);
print_r(unserialize($return));
?>

shmop_read/shmop_write stores raw bytes from a string, so you don't need to serialize it, but you will need to write the length of the string somewhere. My example creates a 16KB shared memory area, you can of course size it to fit the openssl file plus the space you need to store the file size.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文