NAME
Apache2::SSI::SharedMem - Apache2 SSI Notes Shared Memory Manipulation
SYNOPSIS
# Check if IPC::SysV is supported on this system
if( Apache2::SSI::SharedMem->supported )
{
my $shmem = Apache2::SSI::SharedMem->new( key => 'some_identifier' ) ||
die( Apache2::SSI::SharedMem->error );
}
my $shmem = Apache2::SSI::SharedMem->new(
# Create if necessary, or re-use if already exists
create => 1,
# Self-destroy upon end of object. Default to false
destroy => 0,
# make access exclusive
exclusive => 1,
key => 'some_identifier',
mode => 0666,
# 100K
size => 102400,
debug => 3,
) || die( Apache2::SSI::SharedMem->error );
# Check if it already exists
if( $shmem->exists )
{
# do something
}
$shmem->create(0);
$shmem->destroy(0);
$shmem->exclusive(0);
# Then get the bitwise flags based on those options set above:
my $flags = $shmem->flags;
# or specify overriding values:
my $flags = $shmem->flags({
create => 0,
destroy => 0,
exclusive => 0,
});
# Remove create bit
use IPC::SysV qw( IPC_CREAT );
$flags ^= IPC_CREAT;
my $s = $shmem->open || die( $shmem->error );
# Get the shared memory id
my $id = $s->id;
my $key = $s->key;
# Get the actual key used in interacting with shared memory
# You should not mess with this unless you know what you are doing
my $shem_key = $s->serial;
use Apache2::SSI::SharedMem qw( :all );
$s->lock( LOCK_EX ) || die( $s->error );
# Is it locked?
my $is_locked = $s->locked;
# example: 0666
my $mode = $s->mode;
my $s = $shmem->open || die( $shmem->error );
# Actually the process pid
my $owner = $s->owner;
# The semaphore pid
my $sempid = $s->pid;
# Get a random key to use to create shared memory block
my $random_key = $shmem->rand;
my $data = $s->read;
my $buffer;
$s->read( $buffer );
# or, if data is not a reference, trim data after 1024 bytes
my $len = $s->read( $buffer, 1024 ) || die( $s->error );
$s->remove;
my $semaphore_id = $s->semid;
# or $s->size;
my $shared_mem_size = $shmem->size;
# See Apache2::SSI::SemStat
my $stat = $s->stat;
# Remove lock
$s->unlock;
$s->write( $data ) || die( $s->error );
VERSION
v0.1.2
DESCRIPTION
Apache2::SSI::SharedMem provides an easy to use api to manipulate shared memory block. See perlipc for more information.
As stipulated in perlport, this is not supported on the following platforms: android, cygwin, dos, Microsoft Windows, OS2, VMS and Risc OS.
You can check if the system is supported with "supported"
if( Apache2::SSI::SharedMem->supported )
{
# do something
}
DEBUGGING
To list all used shared memory, at least on Unix type systems such as Linux or FreeBSD (including MacOSX), use:
ipcs -m
METHODS
new
This instantiates a shared memory object. It takes the following parameters:
- debug
-
A debug value will enable debugging output (equal or above 3 actually)
- create
-
A boolean value to indicate whether the shared memory block should be created if it does not exist. Default to false.
- destroy
-
A boolean value to indicate if the shared memory block should be removed when the object is destroyed. See perlmod for more about object destruction.
- exclusive
-
A boolean value to set the shared memory as exclusive. This will affect the flags set by "flags" which are used by "open".
- key
-
The shared memory key identifier to use. It defaults to
IPC::SysV::IPC_PRIVATE
If you provide an empty value, it will revert to
IPC::SysV::IPC_PRIVATE
.If you provide a number, it will be used to call "ftok" in IPC::SysV.
Otherwise, if you provide a key as string, the characters in the string will be converted to their numeric value and added up. The resulting id, called
project id
by IPC::SysV, will be used to call "ftok" in IPC::SysV and will produce an hopefully unique and repeatable value.Either way, the resulting value is used to create a shared memory segment and a semaphore by "open".
- mode
-
The octal mode value to use when opening the shared memory block.
Shared memory are owned by system users and access to shared memory segment is ruled by the initial permissions set to it.
If you do not want to share it with any other user than yourself, setting mode to
0600
is fine. - size
-
The size in byte of the shared memory.
This is set once it is created. You can create again the shared memory segment with a smaller size, but not a bigger one. If you want to increase the size, you would need to remove it first.
An object will be returned if it successfully initiated, or undef() upon error, which can then be retrieved with Apache2::SSI::SharedMem-
error>. You should always check the return value of the methods used here for their definedness.
my $shmem = Apache2::SSI::SharedMem->new(
create => 1,
destroy => 0,
key => 'my_memory',
# 64K
size => 65536,
) || die( Apache2::SSI::SharedMem->error );
addr
Returns the address of the shared memory segment once it has been attached to this address space.
attach
Attach the shared memory segment to this address space and returns its address.
Upon error, it returns undef
and sets an error that can be retrieved with the error method:
my $addr = $shem->attach || die( $shem->error );
A shared memory segment object must be first created with the "open" method, because "attach" calls "shmat" in IPC::SysV with the shared memory id and this id is returned upon using the "open" method.
create
Set or get the boolean value to true to indicate you want to create the shared memory block if it does not exist already. Default to false.
destroy
Set or get the boolean value to indicate that the shared memory should be automatically destroyed when the module object is destroyed. See perlmod for more information about module object destruction.
detach
Quoting the IPC documentation, this detaches the shared memory segment located at the address specified by "attach" from this address space.
It returns undef
if it is not attached anymore, but without setting an error.
exclusive
Set or get the boolean value to affect the open flags in exclusive mode.
exists
Checks if the shared memory identified with key exists.
It takes the same arguments as "open" and returns 1 if the shared memory exists or 0 otherwise.
It does this by performing a "shmget" in perlfunc such as:
shmget( $shared_mem_key, $size, 0444 );
This will typically return the shared memory id if it exists or undef()
with an error set in $!
by perl otherwise.
flags
Provided with an optional hash or hash reference and this return a bitwise value of flags used by "open".
my $flags = $shmem->flags({
create => 1,
exclusive => 0,
mode => 0600,
}) || die( $shmem->error );
id
Returns the id of the shared memory once it has been opened with "open"
my $s = $shmem->open || die( $shmem->error );
my $id = $s->id;
key
Sets or gets the shared memory key identifier.
$shem->key( 'some_identifier' );
lock
It takes an optional bitwise lock value, and defaults to LOCK_SH
if none is provided and issues a lock on the shared memory.
use Apache2::SSI::SharedMem qw( :all );
my $s = $shem->open || die( $shmem->error );
$s->lock( LOCK_EX );
# Do something
$s->unlock;
locked
Returns a positive value when a lock is active or 0 when there is no active lock.
The value is the bitwise value of the lock used.
mode
Sets or gets the mode for the shared memory as used by "open"
$shmem->mode( 0666 );
my $s = $shmem->open || die( $shmem->error );
op
Issue an opeation on the semaphore.
Provided value sould be a set of 3.
$s->op( @{$Apache2::SSI::SharedMem->{(SEMOP_ARGS)}} ) ||
die( $s->error );
open
Create an access to the shared memory and return a new Apache2::SSI::SharedMem object.
my $shmem = Apache2::SSI::SharedMem->new(
create => 1,
destroy => 0,
# If not provided, will use the one provided during object instantiation
key => 'my_memory',
# 64K
size => 65536,
) || die( Apache2::SSI::SharedMem->error );
# Overriding some default value set during previous object instantiation
my $s = $shmem->open({
mode => 0600,
size => 1024,
}) || die( $shmem->error );
If the "create" option is set to true, but the shared memory already exists, "open" will detect it and attempt to open access to the shared memory without the "create" bit on, which is IPC::SysV::IPC_CREAT
owner
Sets or gets the shared memory owner, which is by default actually the process id ($$
)
pid
Get the semaphore pid once the shared memory has been opened.
my $pid = $s->pid || die( $s->error );
rand
Get a random key to be used as identifier to create a shared memory.
read
Read the content of the shared memory.
You can optionally provide a buffer, and a maximum length and it will put the shared memory content in that buffer up to the maximum length, if it were provided.
It then return the length read, or 0E0
if no data was retrieved. 0E0
still is treated as 0, but as a positive value, so you can do:
my $len = $s->read( $buffer ) || die( $s->error );
But you really should more thoroughly do instead:
my( $len, $buffer );
if( !defined( $len = $s->read( $buffer ) ) )
{
die( $s->error );
}
If you do not provide any buffer, you can call "read" like this and it will return you the shared memory content:
my $buffer;
if( !defined( $buffer = $s->read ) )
{
die( $s->error );
}
The content is stored in shared memory as JSON encoded, but since it is shared, read do some minimal check to see if the data looks like JSON data. It it does not, the data is returned as-is.
remove
Remove entire the shared memory identified with "key"
removed
Returns true if the shared memory was removed, false otherwise.
semid
Return the semaphore id once the shared memory has been opened. See perlipc for more information about semaphore and perlfunc.
serial
Returns the serial number used to create or access the shared memory segment.
This serial is created based on the key parameter provided either upon object instantiation or upon using the "open" method.
The serial is created by calling "ftok" in IPC::SysV to provide a reliable and repeatable numeric identifier.
size
Sets or gets the shared memory block size.
This should be an integer representing bytes, so typically a multiple of 1024.
stat
Sets or retrieve value with semaphore.
If one parameter only is provided, it returns its corresponding value set.
It performs:
# Get the semaphore id
my $id = $s->semid;
my $value = semctl( $id, $sem, IPC::SysV::GETVAL, 0 );
When 2 parameters are provided, this is treated as a key-value pair and sets the value for the corresponding key.
It performs:
my $id = $s->semid;
semctl( $id, $sem, IPC::SysV::SETVAL, $val )
If no parameter is provided it returns a Apache2::SSI::SemStat object in scalar context or an array of value in list context.
supported
Returns true if IPC shared memory segments are supported by the system, and false otherwise.
unlock
Remove the lock, if any. The shared memory must first be opened.
$s->unlock || die( $s->error );
write
Write the data provided to the shared memory.
When doing so, this will encode the data as JSON text data. It supports data supported by JSON, so basically string, hash reference and array reference.
It returns the current object for chaining, or under if there was an error, which can then be retrieved with "error" in Module::Generic
JSON data are more portable across network and is a widely used technology.
AUTHOR
Jacques Deguest <jack@deguest.jp>
CPAN ID: jdeguest
https://gitlab.com/jackdeguest/Apache2-SSI
SEE ALSO
Apache2::SSI, Apache2::SSI::Notes, Apache2::SSI::SharedMem
perlipc, perlmod, IPC::Shareable
COPYRIGHT & LICENSE
Copyright (c) 2020-2021 DEGUEST Pte. Ltd.
You can use, copy, modify and redistribute this package and associated files under the same terms as Perl itself.