windows - Shared memory-fil i PHP

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg bruger openssl\_pkcs7\_sign og openssl\_pkcs7\_encrypt til at oprette krypterede data. Funktionerne accepterer kun filnavne. Jeg vil gerne gemme de midlertidige filer i delt hukommelse for at forbedre ydeevnen. Jeg forstår i Linux kan jeg file\_put\_contents('/dev/shm/xxx', data), men det er ikke muligt for Windows. Er der bærbar måde i PHP for at gøre dette? Vil shmop\_ funktion hjælpe her? Tak.


PS: Eller er der mulighed for at få disse funktioner til at acceptere datastrengen?


PS2: Foreslå ikke at påberåbe /usr/bin/openssl fra PHP. Det er ikke bærbart.

Bedste reference


Siden Windows 2000 er metoderne shmop (tidligere shm\_) tilgængelige.


shmop\_open bruger en unik heltalsnøgle til at dele hukommelsesområdet. ftok kan bruges til at producere et unikt indeks baseret på en filsti (typisk din scriptfilens fulde sti). Ethvert eksempel, der deler samme nøgle, kan dele samme hukommelse.


http://php.net/manual/en/ref.shmop.php[16]


Testet på PHP Version 5.3.3 fra 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 gemmer rå byte fra en streng, så du behøver ikke at serialisere det, men du skal skrive længden af ​​strengen et sted. Mit eksempel skaber et 16KB delt hukommelsesområde, du kan selvfølgelig størrelse det for at passe til openssl filen plus det rum, du har brug for til at gemme filstørrelsen.

Andre referencer 1


Ok, så måden jeg foreslår at gøre dette er med en fil stream wrapper. Lad mig piske et hurtigt eksempel: [17]


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

}


Nu skal du derefter registrere wrappen:


stream\_wrapper\_register('static', 'staticStreamWrapper');


Så du kan nu behandle det som en fil, selv om det aldrig rent faktisk forlader PHP (det gemmes som en statisk variabel)!


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