2011-04-14 34 views
9

Tôi sử dụng openssl_pkcs7_signopenssl_pkcs7_encrypt để tạo dữ liệu được mã hóa. Các hàm chỉ chấp nhận tên tệp. Tôi muốn lưu trữ các tệp tạm thời trong bộ nhớ dùng chung để cải thiện hiệu suất. Tôi hiểu trong Linux tôi có thể file_put_contents('/dev/shm/xxx', data), nhưng không thể cho Windows. Có cách di động trong PHP để làm điều này? shmop_ có trợ giúp về chức năng ở đây không? Cảm ơn.Tệp bộ nhớ dùng chung trong PHP

PS: Hoặc có cách nào để làm cho các hàm này chấp nhận chuỗi dữ liệu không?

PS2: Vui lòng không đề xuất gọi /usr/bin/openssl từ PHP. Nó không phải là xách tay.

+0

bạn muốn làm gì với nó khi bạn lưu? Bạn có nghĩ về việc sử dụng luồng tệp thay vì bộ nhớ dùng chung không? xem [StreamWrapper] (http://us2.php.net/manual/en/class.streamwrapper.php) – ircmaxell

+0

Tôi chỉ lưu dữ liệu vào tệp (sử dụng 'file_put_contents') và nạp tên tệp vào các hàm OpenSSL. Phần lớn chi phí là từ các hàm OpenSSL và các hoạt động VFS (đọc, viết, bỏ liên kết). Làm cách nào để tạo sự khác biệt? –

Trả lời

3

Kể từ Windows 2000, các phương thức shmop (trước đây là shm_) khả dụng.

shmop_open sử dụng khóa số nguyên duy nhất để chia sẻ vùng bộ nhớ. ftok có thể được sử dụng để tạo chỉ mục duy nhất dựa trên đường dẫn tệp (thường là đường dẫn đầy đủ của tệp tập lệnh của bạn). Bất kỳ cá thể nào chia sẻ cùng một khóa đều có thể chia sẻ cùng một bộ nhớ.

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

Thử nghiệm trên PHP Version 5.3.3 từ Zend Server CE hệ thống Windows NT CRYPE 6.1 build 7601 (phiên bản của Windows Unknow 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 cửa hàng byte thô từ một chuỗi, vì vậy bạn không cần phải serialize nó, nhưng bạn sẽ cần phải viết chiều dài của chuỗi ở đâu đó. Ví dụ của tôi tạo ra một khu vực bộ nhớ chia sẻ 16KB, bạn có thể kích thước của nó để phù hợp với tệp openssl cộng với không gian bạn cần để lưu trữ kích thước tệp.

+0

Tôi hiểu các hàm 'shmop_'. Câu hỏi của tôi là làm thế nào để bạn cung cấp tên tệp cho OpenSSL? Các khối bộ nhớ không có tên tệp. –

+0

Có vẻ như hầu hết các chức năng OpenSSL đều chấp nhận các con trỏ tệp, điều này sẽ cho phép bạn sử dụng các tệp bộ nhớ '' php: // memory''. Bạn sẽ phải sử dụng các tệp tạm thời để đọc dữ liệu vào và ra, điều này sẽ phủ nhận bất kỳ lợi ích nào của bộ nhớ dùng chung theo ý kiến ​​của tôi. Tuy nhiên, một số chức năng như openssl_private_decrypt cho phép bạn làm việc với các chuỗi thay vì tệp, mà bạn có thể tải và dỡ trực tiếp từ bộ nhớ dùng chung. Có các hàm MIME khác có thể hoạt động thay vì pkcs7 nhưng tôi không quen thuộc. Tôi khuyên bạn nên xem xét xem có bất kỳ chức năng nào trong số đó sẽ hoạt động cho nhu cầu của bạn hay không. –

+0

Ngoài ra, bạn có thể sử dụng shmop_size để khôi phục kích thước khối. – RafaSashi

6

Ok, vì vậy cách tôi đề xuất thực hiện việc này là với tệp stream wrapper. Hãy để tôi whip lên một ví dụ nhanh:

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

} 

Bây giờ, sau đó bạn sẽ cần phải đăng ký wrapper:

stream_wrapper_register('static', 'staticStreamWrapper'); 

Vì vậy, bây giờ bạn có thể đối xử với nó như một tập tin mặc dù nó không bao giờ thực sự rời khỏi PHP (nó được lưu trữ dưới dạng biến tĩnh)!

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

Cảm ơn thông tin về luồng.Tôi hiểu rằng PHP hỗ trợ triển khai trình bao bọc dòng tùy chỉnh. Tuy nhiên, phần mở rộng OpenSSL rất có thể được viết bằng API OS và các chức năng không sử dụng các luồng PHP. Gọi 'openssl_pkcs7_encrypt' với kết quả luồng' static' trong thông báo lỗi sau: 'error: 02001002: thư viện hệ thống: fopen: Không có tập tin hoặc thư mục nào'. –

Các vấn đề liên quan