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); }

In reply to Connecting to shared memory thru semaphores by zentara

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.