我使用openssl_pkcs7_sign
和openssl_pkcs7_encrypt
创buildencryption的数据。 这些function只接受文件名称。 我想将临时文件存储在共享内存中以提高性能。 我知道在Linux中我可以file_put_contents('/dev/shm/xxx', data)
,但它不可能为Windows。 有没有可移植的方式在PHP中做到这一点? 请问shmop_
函数在这里有帮助吗? 谢谢。
PS:还是有办法让这些function接受数据string?
PS2:请不要build议从PHP调用/usr/bin/openssl
。 这不是便携式的。
自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(Unknow 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文件加上你需要的空间来存储文件大小。
好的,所以我建议这样做的方式是使用文件流包装器 。 让我来举个简单的例子:
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...