Solved

PHP > Setting server-wide variables?

Posted on 2009-04-15
8
287 Views
Last Modified: 2012-05-06
I have a PHP web page that Internet users access.  I have a second PHP script running as a system script under the root user.  I need to be able to communicate small bits of information from the Apache script to the system script so my options are:

1. Write the info to a file on disk.
2. Write the info to MySQL
3. Write the info to memory

Options 1 and 2 are bad because they take a lot of overhead in spinning disks, etc.  

So is there a simple way to do Option #3?  Like can I write the info to a new environment variable which would be available across the whole server like:

$_ENV['php_shared_data'][]='foo';
0
Comment
Question by:Geoff Millikan
  • 5
  • 3
8 Comments
 
LVL 11

Expert Comment

by:NoiS
ID: 24150415
PHP have shared memory function (shmop) But I never use it before.

I can suggest this piece of code but don't know if will work.


// Create 100 byte shared memory block with system id if 0xff3
$shm_id = shmop_open(0xff3, "c", 0644, 100);
if(!$shm_id) {
    echo "Couldn't create shared memory segment\n";
}
 
// Get shared memory block's size
$shm_size = shmop_size($shm_id);
echo "SHM Block Size: ".$shm_size. " has been created.\n";
 
// Lets write a test string into shared memory
$shm_bytes_written = shmop_write($shm_id, "my shared memory block", 0);
if($shm_bytes_written != strlen("my shared memory block")) {
    echo "Couldn't write the entire length of data\n";
}
 
// Now lets read the string back
$my_string = shmop_read($shm_id, 0, $shm_size);
if(!$my_string) {
    echo "Couldn't read from shared memory block\n";
}
echo "The data inside shared memory was: ".$my_string."\n";
 
//Now lets delete the block and close the shared memory segment
if(!shmop_delete($shm_id)) {
    echo "Couldn't mark shared memory block for deletion.";
}
shmop_close($shm_id);

Open in new window

0
 

Author Comment

by:Geoff Millikan
ID: 24150520
The shmop() function doesn't appear to persist.  The tests I did showed that once the Apache script is done running it seems that whatever was put into memory cannot be retrieved.  Let me know if you have information otherwise.

Anyone else?
0
 
LVL 11

Expert Comment

by:NoiS
ID: 24150802
Weel... is strange cause you point to a memory address. Maybe when the script ends all values are cleaned like all PHP vars and objects.
I will make a test.
Remember that this functions are to be used on a Linux like system (will work on windows too but... ) and need PHP to be compile with --enable-shmop to activate it.

The persistence is the main trouble here.
I think that the only way to do what you want is using DB or File (if shmop cannot do it).
0
Announcing the Most Valuable Experts of 2016

MVEs are more concerned with the satisfaction of those they help than with the considerable points they can earn. They are the types of people you feel privileged to call colleagues. Join us in honoring this amazing group of Experts.

 

Author Comment

by:Geoff Millikan
ID: 24152309
My test was to run the below test via a HTTP call.  Then use the returned $shm_id value (which was "4" in my case) like the below at the command line:  Expected return was "100" but it threw errors instead.

shell prompt> php -r "var_dump(shmop_size(4));"

PS. I'm on Red Hat Linux 5 with PHP 5.1.6 (cli).
<?php
 
$shm_key = ftok(__FILE__, 't');
echo '$shm_key='.$shm_key."\r\n";
 
if ($shm_id = shmop_open($shm_key, "n", 0777, 100)) {
    echo '$shm_id='.$shm_id."\r\n";    
}
?>

Open in new window

0
 
LVL 11

Accepted Solution

by:
NoiS earned 500 total points
ID: 24157232
look... you are using ftok(__FILE__, 't') to generate a memory address
but you need the same address always.
Try changing __FILE__ to a fixed path to any file.

the code will be

#######################################################################
// To put the value on memory
 
// Create 100 byte shared memory block with system id if 0xff3
$shm_id = shmop_open(ftok('/path/to/file','t'), "c", 0666, 100);
if(!$shm_id) {
    echo "Couldn't create shared memory segment\n";
}
 
// Lets write a test string into shared memory
$shm_bytes_written = shmop_write($shm_id, "my shared memory block", 0);
if($shm_bytes_written != strlen("my shared memory block")) {
    echo "Couldn't write the entire length of data\n";
}
 
shmop_close($shm_id);
 
#######################################################################
// To read the value stored
$shm_id = shmop_open(ftok('/path/to/file','t'), "c", 0666, 100);
if(!$shm_id) {
    echo "Couldn't create shared memory segment\n";
}
 
// Now lets read the string back
$shm_size = shmop_size($shm_id);
$my_string = shmop_read($shm_id, 0, $shm_size);
if(!$my_string) {
    echo "Couldn't read from shared memory block\n";
}
echo "The data inside shared memory was: [".$my_string."]\n";
shmop_close($shm_id);
 
#######################################################################
// To release the address
$shm_id = shmop_open(ftok('/path/to/file','t'), "c", 0666, 100);
if(!$shm_id) {
    echo "Couldn't create shared memory segment\n";
}
//Now lets delete the block and close the shared memory segment
if(!shmop_delete($shm_id)) {
    echo "Couldn't mark shared memory block for deletion.";
}
shmop_close($shm_id);

Open in new window

0
 

Author Comment

by:Geoff Millikan
ID: 24159580
Output with test script below is:

From web browser:
12 $shm_id=2
20 $shm_bytes_written=22

From command line:
shell> php /home/t1shopper/www/dev/shared_memory.php
32 $shm_id=4
42 The data inside shared memory was: [my shared memory block]
bool(true)

NULL

<?php
if (php_sapi_name()=='apache2handler') {
    //Write memory with web browser
    $file_name='/home/t1shopper/www/dev/shared_memory.php';
    $shm_key = ftok($file_name, 't');
    $shm_id = shmop_open($shm_key, "c", 0777, 100);
 
    if (empty($shm_id)) {
        echo __LINE__." Couldn't create shared memory segment<br>";   
        exit(); 
    } else {
        echo __LINE__.' $shm_id='.$shm_id." <br>\n";   
    }
 
    $shm_bytes_written = shmop_write($shm_id, "my shared memory block", 0);
    if($shm_bytes_written != strlen("my shared memory block")) {
        echo "Couldn't write the entire length of data\n";
        exit();
    } else {
        echo __LINE__.' $shm_bytes_written='.$shm_bytes_written." <br>";   
    }
 
    shmop_close($shm_id);
} elseif (php_sapi_name()=='cli') {
    //Read out of memory using command line script.
    $file_name='/home/t1shopper/www/dev/shared_memory.php';
    $shm_key = ftok($file_name, 't');
    @$shm_id = shmop_open($shm_key, "w", 0777, 100);
    if (empty($shm_id)) {
        echo __LINE__." Couldn't access the shared memory segment\n";    
        exit();
    } else {
        echo __LINE__.' $shm_id='.$shm_id."\n";   
    }
     
    // Now lets read the string back
    $shm_size = shmop_size($shm_id);
    $my_string = shmop_read($shm_id, 0, $shm_size);
    if(empty($my_string)) {
        echo __LINE__." Couldn't read from shared memory block\n";
        exit();
    } else {
        echo __LINE__." The data inside shared memory was: [".$my_string."]\n";
        var_dump(shmop_delete($shm_id)); echo "\n";
        var_dump(shmop_close($shm_id));  echo "\n";
    }    
} 
?>

Open in new window

0
 

Author Comment

by:Geoff Millikan
ID: 24159600
P.S.  Running the below command show you everything that's in the shared memory.  Who the owner is, it's permissions and size.  Very helpful to confirm that your shared memory is created.

shell> ipcs
0
 

Author Comment

by:Geoff Millikan
ID: 24187756
Unfortunately, there's no way to incremental add and remove things from Shared memory like you would with a database.  Shared memory needs something like array_pop() and array_push().  As it is, in a threaded environment, I run the risk f overwriting something done on another thread.

Shared memory seems like its main purposes is mostly for times when the data you're reading is too big to fit in the disk cache so you're having to spin the disks each time you want to read the data.  In this case, it's faster to read it out of memory than spin the disks.  If you're reading just a small amount of data, then that will load out of the disk cache which should be in memory already.  It would be interesting to see benchmarking on this - it would differ greatly by operating system since each OS does file caching differently.

If you're needing to both read AND write data across page loads or threads, then shared memory probably isn't for you.  Look at MySQL's MEMORY table type as a better solution.
0

Featured Post

Announcing the Most Valuable Experts of 2016

MVEs are more concerned with the satisfaction of those they help than with the considerable points they can earn. They are the types of people you feel privileged to call colleagues. Join us in honoring this amazing group of Experts.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Developers of all skill levels should learn to use current best practices when developing websites. However many developers, new and old, fall into the trap of using deprecated features because this is what so many tutorials and books tell them to u…
This article discusses four methods for overlaying images in a container on a web page
Learn how to match and substitute tagged data using PHP regular expressions. Demonstrated on Windows 7, but also applies to other operating systems. Demonstrated technique applies to PHP (all versions) and Firefox, but very similar techniques will w…
This tutorial will teach you the core code needed to finalize the addition of a watermark to your image. The viewer will use a small PHP class to learn and create a watermark.

825 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question