2011-04-14 3 views
9

나는 openssl_pkcs7_signopenssl_pkcs7_encrypt을 사용하여 암호화 된 데이터를 생성합니다. 함수는 파일 이름 만 허용합니다. 성능을 향상시키기 위해 공유 메모리에 임시 파일을 저장하고 싶습니다. 나는 리눅스에서 file_put_contents('/dev/shm/xxx', data)을 할 수 있다고 생각 하나, Windows에서는 불가능합니다. PHP에서이 작업을 수행 할 수있는 이식 가능한 방법이 있습니까? shmop_ 기능 도움이 여기에 있습니까? 감사.PHP의 공유 메모리 파일

추신 : 아니면 이러한 함수가 데이터 문자열을 받아들이게하는 방법이 있습니까?

PS2 : PHP에서 /usr/bin/openssl을 호출하지 마십시오. 휴대용이 아닙니다.

+0

일단 저장하면 무엇을하고 싶습니까? 공유 메모리 대신 파일 스트림을 사용하는 것에 대해 생각해 보셨습니까? [StreamWrapper] (http://us2.php.net/manual/en/class.streamwrapper.php) – ircmaxell

+0

그냥 파일에 데이터를 저장하고 ('file_put_contents' 사용), 파일 이름을 OpenSSL 함수에 넘깁니다. 오버 헤드의 대부분은 OpenSSL 기능과 VFS 작업 (읽기, 쓰기, 링크 해제)에서 비롯됩니다. 스트리밍이 어떻게 다른가요? –

답변

3

Windows 2000 이후로 shmop (이전의 shm_) 방법을 사용할 수 있습니다.

shmop_open은 메모리 영역을 공유하기 위해 고유 한 정수 키를 사용합니다. ftok은 파일 경로 (일반적으로 스크립트 파일의 전체 경로)를 기반으로 고유 색인을 생성하는 데 사용할 수 있습니다. 동일한 키를 공유하는 모든 인스턴스는 동일한 메모리를 공유 할 수 있습니다. 젠드 서버 CE 체제 Windows NT CRYPE 6.1 빌드 7601 (알 수없는 Windows 버전 비즈니스 버전 서비스 팩 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 상점에서 PHP 버전 5.3.3에서 테스트

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

문자열에서 원시 바이트를 가져올 수 있으므로 직렬화 할 필요는 없지만 문자열의 길이를 어딘가에 작성해야합니다. 필자의 예는 16KB의 공유 메모리 영역을 생성합니다. 물론 openssl 파일과 파일 크기를 저장하는 데 필요한 공간에 맞게 크기를 조정할 수 있습니다.

+0

'shmop_' 함수를 이해합니다. 제 질문은 OpenSSL에 파일 이름을 어떻게 공급합니까? 메모리 블록에는 파일 이름이 없습니다. –

+0

대부분의 OpenSSL 함수가 파일 포인터를 받아들이는 것처럼 보이지 않습니다.이 함수는''php : // memory'' 메모리 파일을 사용할 수있게합니다. 당신은 임시 파일을 사용하여 데이터를 읽고 밖으로 내 의견에 공유 메모리의 장점을 무효화 할 것이다. 그러나 openssl_private_decrypt와 같은 일부 함수를 사용하면 공유 메모리에서 직접로드 및 언로드 할 수있는 파일 대신 문자열로 작업 할 수 있습니다. pkcs7 대신 작동하는 다른 MIME 기능이 있지만 익숙하지 않습니다. 그 중 어떤 기능이 귀하의 필요에 부합하는지 살펴보기를 권합니다. –

+0

또한 shmop_size를 사용하여 블록 크기를 복구 할 수 있습니다. – RafaSashi

6

좋아, 이렇게하는 것이 좋습니다. 파일은 stream wrapper입니다. (

stream_wrapper_register('static', 'staticStreamWrapper'); 

그래서 당신은 지금 실제로 PHP를 결코 떠나지 않는다하더라도 파일처럼 처리 할 수 ​​있습니다 : 당신이 다음 래퍼를 등록해야합니다, 지금

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; 
    } 

} 

: 나에게 간단한 예를 채찍질하자 정적 변수로 저장 됨)!

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... 
+0

스트림 정보를 보내 주셔서 감사합니다.필자는 PHP가 사용자 지정 스트림 래퍼 구현을 지원함을 이해합니다. 그러나 OpenSSL 확장은 대부분 OS API로 작성되며 함수는 PHP 스트림을 사용하지 않습니다. 'statics '스트림으로'openssl_pkcs7_encrypt'를 호출하면'error : 02001002 : system library : fopen : No such file or directory'라는 오류 메시지가 나타납니다. –