Solved

PHP > Setting server-wide variables?

Posted on 2009-04-15
8
273 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
Comment Utility
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
Comment Utility
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
Comment Utility
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
 

Author Comment

by:Geoff Millikan
Comment Utility
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
Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 
LVL 11

Accepted Solution

by:
NoiS earned 500 total points
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Author Note: Since this E-E article was originally written, years ago, formal testing has come into common use in the world of PHP.  PHPUnit (http://en.wikipedia.org/wiki/PHPUnit) and similar technologies have enjoyed wide adoption, making it possib…
Password hashing is better than message digests or encryption, and you should be using it instead of message digests or encryption.  Find out why and how in this article, which supplements the original article on PHP Client Registration, Login, Logo…
The viewer will learn how to dynamically set the form action using jQuery.
The viewer will learn how to look for a specific file type in a local or remote server directory using PHP.

763 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

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now