Module::Generic::SharedMem - Shared Memory Manipulation
# Check if IPC::SysV is supported on this system if( Module::Generic::SharedMem->supported ) { my $shmem = Module::Generic::SharedMem->new( key => 'some_identifier' ) || die( Module::Generic::SharedMem->error ); } my $shmem = Module::Generic::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( Module::Generic::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, mode => 0644, }); 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 Module::Generic::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 ); # You can control how much to read and allocate a buffer to put the read data onto # Data is automatically transcoded using Storable::Improved::thaw 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 Module::Generic::SemStat doc my $stat = $s->stat; # See Module::Generic::SharedStat doc my $stat = $s->shmstat; # Remove lock $s->unlock; # Data is automatically transcoded using Storable::Improved::freeze $s->write( $data ) || die( $s->error );
v0.4.0
Module::Generic::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, dos, MSWin32, OS2, VMS and Risc OS.
You can check if the system is supported with "supported"
if( Module::Generic::SharedMem->supported ) { # do something }
This module only works with reference data, such as array, hash or reference to scalar. Anything that CBOR::XS, Sereal. or Storable::Improved knows how to "freeze" in Storable::Improved and "thaw" in Storable::Improved
To list all used shared memory, at least on Unix type systems such as Linux or FreeBSD (including MacOSX), use:
ipcs -m
This instantiates a shared memory object. It takes the following parameters:
Provided with a value (true or false does not matter), and this will set CBOR::XS as the data serialisation mechanism when storing data to memory or reading data from memory.
A debug value will enable debugging output (equal or above 3 actually)
A boolean value to indicate whether the shared memory block should be created if it does not exist. Default to false.
A boolean value to indicate if the shared memory block should be removed when the object is destroyed upon end of the script process. See perlmod for more about object destruction.
A boolean value to indicate if the semaphore should be removed when the object is destroyed upon end of the script process. See perlmod for more about object destruction.
destroy_semaphore is automatically enabled if destroy is set to true.
Thus, one can deactive auto removal of the shared memory block, but enable auto removal of the semaphore. This is useful when there are two processes accessing the same shared memory block and one wants to give the first process the authority to create and remove the shared memory block, while the second only access and write to the shared memory block, but does not remove it. Still to avoid having semaphores surviving the process, by enabling this option and disabling destroy, it will remove the semaphore and leave the shared memory.
A boolean value to set the shared memory as exclusive. This will affect the flags set by "flags" which are used by "open".
Provided with a value (true or false does not matter), and this will set JSON as the data serialisation mechanism when storing data to memory or reading data from memory.
The shared memory key identifier to use. It defaults to IPC::SysV::IPC_PRIVATE
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.
project id
Either way, the resulting value is used to create a shared memory segment and a semaphore by "open".
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.
0600
Provided with a value (true or false does not matter), and this will set Sereal as the data serialisation mechanism when storing data to memory or reading data from memory.
You can provide the serialiser with this option. Possible values are: cbor, json, sereal, storable
cbor
json
sereal
storable
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.
Provided with a value (true or false does not matter), and this will set Storable::Improved as the data serialisation mechanism when storing data to memory or reading data from memory.
An object will be returned if it successfully initiated, or undef() upon error, which can then be retrieved with Module::Generic::SharedMem-error >. You should always check the return value of the methods used here for their definedness.
Module::Generic::SharedMem-
my $shmem = Module::Generic::SharedMem->new( create => 1, destroy => 0, key => 'my_memory', # 64K size => 65536, ) || die( Module::Generic::SharedMem->error );
Returns the address of the shared memory segment once it has been attached to this address space.
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:
undef
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.
When called, this will set CBOR::XS as the data serialisation mechanism when storing data to memory or reading data from memory.
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.
This is an alias for "remove"
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.
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.
Set or get the boolean value to affect the open flags in exclusive mode.
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.
undef()
$!
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 );
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;
When called, this will set JSON as the data serialisation mechanism when storing data to memory or reading data from memory.
Sets or gets the shared memory key identifier.
$shem->key( 'some_identifier' );
It takes an optional bitwise lock value, and defaults to LOCK_SH if none is provided and issues a lock on the shared memory.
LOCK_SH
use Module::Generic::SharedMem qw( :all ); my $s = $shem->open || die( $shmem->error ); $s->lock( LOCK_EX ); # Do something $s->unlock;
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.
Sets or gets the mode for the shared memory as used by "open"
$shmem->mode( 0666 ); my $s = $shmem->open || die( $shmem->error );
Issue an opeation on the semaphore.
Provided value sould be a set of 3.
$s->op( @{$Module::Generic::SharedMem::SEMOP_ARGS->{(LOCK_SH)}} ) || die( $s->error );
Create an access to the shared memory and return a new Module::Generic::SharedMem object.
my $shmem = Module::Generic::SharedMem->new( create => 1, destroy => 0, # If not provided, will use the one provided during object instantiation key => 'my_memory', # 64K size => 65536, ) || die( Module::Generic::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
IPC::SysV::IPC_CREAT
Sets or gets the shared memory owner, which is by default actually the process id ($$)
$$
Get the semaphore pid once the shared memory has been opened.
my $pid = $s->pid || die( $s->error );
Get a random key to be used as identifier to create a shared memory.
Read the content of the shared memory and decode the data read using JSON, CBOR, Sereal or "thaw" in Storable::Improved depending on your choice of serialiser upon either object instantiation or upon using the methods "json", "cbor", "sereal" or "storable" or even more simply "serialiser". For example:
my $s = Module::Generic::SharedMem->new( cbor => 1 ) || die( Module::Generic::SharedMem->error ); # or $s->cbor(1); # or my $s = Module::Generic::SharedMem->new( serialiser => 'cbor' ) || die( Module::Generic::SharedMem->error );
By default, if no serialiser is specified, it will default to storable.
You can optionally provide a buffer, and a maximum length and it will read that much length and put the shared memory content decoded in that buffer, 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:
0E0
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 decoded content:
my $buffer; if( !defined( $buffer = $s->read ) ) { die( $s->error ); }
Remove entire the shared memory identified with "key"
Remove the semaphore associated with the shared memory.
Returns true if the shared memory was removed, false otherwise.
Returns true if the semaphore has been removed, false otherwise.
Reset the shared memory value. If a value is provided, it will be used as the new reset value, othewise an empty string will be used.
Return the semaphore id once the shared memory has been opened. See perlipc for more information about semaphore and perlfunc.
When called, this will set Sereal as the data serialisation mechanism when storing data to memory or reading data from memory.
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.
Sets or gets the serialiser. Possible values are: cbor, json, sereal, storable
Returns an Module::Generic::SharedStat object representing the current shared memory properties.
Module::Generic::SharedStat
Sets or gets the shared memory block size.
This should be an integer representing bytes, so typically a multiple of 1024.
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.
my $id = $s->semid; semctl( $id, $sem, IPC::SysV::SETVAL, $val )
If no parameter is provided it returns a Module::Generic::SemStat object in scalar context or an array of value in list context.
When called, this will set Storable::Improved as the data serialisation mechanism when storing data to memory or reading data from memory.
Returns true if IPC shared memory segments are supported by the system, and false otherwise.
Remove the lock, if any. The shared memory must first be opened.
$s->unlock || die( $s->error );
Write the data provided to the shared memory, after having encoded it using JSON, CBOR, Sereal or "freeze" in Storable::Improved depending on your choice of serialiser. See "json", "cbor", "sereal" and "storable"
You can only store in shared memory reference, such as scalar reference, array or hash reference. You could also store module objects, but note that if you choose JSON as a serialiser for your shared data, JSON only supports encoding objects that are based on array or hash. As the JSON documentation states "other blessed references will be converted into null". Thus if you use other reference types, you might want to use CBOR, Sereal or Storable instead.
It returns the current object for chaining, or undef if there was an error, which can then be retrieved with "error" in Module::Generic
Serialisation by CBOR, Sereal and Storable::Improved (or the legacy Storable) is supported by this package. To that effect, the following subroutines are implemented: FREEZE, THAW, STORABLE_freeze and STORABLE_thaw
FREEZE
THAW
STORABLE_freeze
STORABLE_thaw
Jacques Deguest <jack@deguest.jp>
Module::Generic, Module::Generic::SemStat, Module::Generic::SharedStat
perlipc, perlmod, IPC::Semaphore
Copyright (c) 2021 DEGUEST Pte. Ltd.
You can use, copy, modify and redistribute this package and associated files under the same terms as Perl itself.
To install Module::Generic, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Module::Generic
CPAN shell
perl -MCPAN -e shell install Module::Generic
For more information on module installation, please visit the detailed CPAN module installation guide.