我使用openssl_pkcs7_sign
和openssl_pkcs7_encrypt
来创建加密数据。这些函数只接受文件名。我想将临时文件存储在共享内存中以提高性能。我在Linux中理解我可以file_put_contents('/dev/shm/xxx', data)
,但Windows不可能。 PHP中是否有可移植的方式来执行此操作?这里有shmop_
功能帮助吗?感谢。
PS:或者有没有办法让这些函数接受数据字符串?
PS2:请不要建议从PHP调用/usr/bin/openssl
。它不便携。
答案 0 :(得分:6)
好的,我建议这样做的方法是使用文件stream wrapper。让我举一个简单的例子:
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...
答案 1 :(得分:3)
自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版商业版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文件调整大小以及存储文件大小所需的空间。