Hi, I've been toying with SysV Shared memory segments as of late, and in my previous post SysV shared memory --pure perl, one needed to pass the shmid as a arg to the listener scripts. Well that is kind of clumsy. So I wanted a way to "broadcast" the shmid to any script that had the "key". At first I though of using sockets, but that required a while loop running for the server....no good. I though of a temp file, which would be good, but no fun :-) . So I worked out a way using semaphores. It's neat. It's like a big billboard with the shmid on it, but needs no servicing from the init script, except to set it up. Only clients with the right $IPC_KEY can read the billboard( or root ).

So it dosn't do anything useful, except to demonstrate the "unconventional use of semaphores" to make some data available to all keyed clients.

First start the init script, then as many clients as you want( or cpu can handle). The clients will automatically find the right shared memory segment to attach to.

##################################################### ##################################################### ########### shmem-sem-init ########################## #!/usr/bin/perl use warnings; use strict; use IPC::SysV qw(IPC_STAT IPC_PRIVATE IPC_CREAT IPC_EXCL S_IRUSR S_IWU +SR IPC_RMID S_IRWXU); use IPC::Semaphore; my $IPC_KEY = 1234; #create 2 semaphores identified by $IPC_KEY, max is 4 digits my $sem = new IPC::Semaphore($IPC_KEY, 2, S_IRWXU | IPC_CREAT); #won't work with 8 digit shmids, unless split it on 2 semaphores $sem->setall( (0000) x 2); my @sem = $sem->getall; print "sem0->@sem\n"; my $go = 1; $SIG{INT} = sub{ $go = 0; &close_m(); #close up the shared mem exit; }; my $segment_hbytes = 0x640; # hex bytes, a multiple of 4k my ($segment_id, $segment_size) = &init_m($segment_hbytes); print "shmid-> $segment_id\tsize-> $segment_size\n"; my ($shval1,$shval2) = $segment_id =~ /(\d{4})(\d{4})/; $sem->setval(0, $shval1 ); $sem->setval(1, $shval2 ); @sem = $sem->getall; print "sem1->@sem\n"; my $i = 'a'; while($go){ &write_m($i); $i++; select(undef,undef,undef,.01); last if ! $go; } exit; ################################################################# sub init_m(){ my $segment_hbytes = shift; # Allocate a shared memory segment. my $segment_id = shmget (IPC_PRIVATE, $segment_hbytes, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR); # Verify the segment's size. my $shmbuffer = ''; shmctl ($segment_id, IPC_STAT, $shmbuffer); my @mdata = unpack("i*",$shmbuffer); return($segment_id, $mdata[9] ); } sub write_m() { # Write a string to the shared memory segment. my $message = shift; shmwrite($segment_id, $message, 0, $segment_size) || die "$!"; return 0; } sub close_m(){ # Deallocate the shared memory segment. shmctl ($segment_id, IPC_RMID, 0); $sem->remove; return 0; } __END__ ##################################################### ##################################################### ###########shmem-sem-listener######################## #!/usr/bin/perl use warnings; use strict; use IPC::SysV qw(IPC_STAT); use IPC::Semaphore; #see "perldoc perlfunc /shmget" and "perldoc perlipc /SysV" my $IPC_KEY = 1234; #key to be shared for apps to connect my $sem = new IPC::Semaphore($IPC_KEY, 2, 0); print "sem->$sem\n"; my $go = 1; #get shmid from semaphore 0 and 1 my $segment_id1 = $sem->getval(0); #first 4 digits my $segment_id2 = $sem->getval(1); #last 4 digits #hack for segment_id2 being 0000 or 0530, which Perl converts to 0 or +530 my $padded = '0' x ( 4 - length( $segment_id2 ) ) . $segment_id2; my $segment_id = $segment_id1.$padded; $SIG{INT} = sub{ $go = 0; exit;}; my $segment_size = &size_m($segment_id); print "segment_size = $segment_size\n"; while($go){ my $readm = &read_m(); print "$readm"; select(undef,undef,undef,.01); last if ! $go; } ############################################################# sub size_m(){ my $segment_id = shift; my $shmbuffer = ''; shmctl ($segment_id, IPC_STAT, $shmbuffer); my @mdata = unpack("i*",$shmbuffer); print "segment size: ", $mdata[9], "\n"; return($mdata[9]); } #################################################################3 sub read_m(){ my $buff; shmread($segment_id, $buff, 0, $segment_size) || die "$!"; return ($buff); }