andreas1234567 has asked for the wisdom of the Perl Monks concerning the following question:

Dearest Monks,
This is perl, v5.8.0 built for i386-linux-thread-multi $ uname -r => 2.4.21-37.EL Module id = IPC::Msg CPAN_VERSION 1.00
First, using IPC::Msg, I'd like to detect when a queue grows full. Typically this happens when there are no readers for a queue being written to.
#!/usr/bin/perl use strict; use warnings; use IPC::SysV qw(IPC_CREAT IPC_NOWAIT S_IRWXU S_IRWXG S_IRWXO IPC_SET); use IPC::Msg; my $msg = new IPC::Msg ("QUEUE_42", IPC_CREAT | S_IRWXU | S_IRWXG | S_IRWXO | IPC_ +SET); SEND: while (1) { # exit SEND if $msg->full(); # PSEUDO-CODE ONLY $msg->snd(1, pack("L a*", 1, "Hello World!")); }
Second, I would like to list the avaiable queues by name. ipcs(8) reports msqid only:
$ ipcs -q ------ Message Queues -------- key msqid owner perms used-bytes messages 0x00000000 163844 u92 777 16384 1024
How do i get "QUEUE_42" from msgid 163844?
--
Best regards
Andreas

Replies are listed 'Best First'.
Re: IPC::Msg - determine if queue is full
by zentara (Cardinal) on Jan 30, 2006 at 16:30 UTC
    The last time I played with it, I found it quite cumbersome to handle shared memory; mostly because of all the hex notation, dealing with lengths of variables in c terms, etc. You have to keep track of what portion of the shared memory corresponds to which of you variables, AND you have to make sure you don't get extraneous hex junk appended. Like I said, it was too cumbersome for my tastes.

    Here is an example set of scripts that may show you whats up, I hope they help. :-)

    #!/usr/bin/perl # this is the init script 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::Msg; # see "perldoc perlfunc /shmget" and "perldoc perlipc /SysV" # big difference from c is attach and detach is automatic in Perl # it attaches to read or write, then detaches my $IPC_KEY = 1234; my $msg = new IPC::Msg($IPC_KEY, S_IRWXU | IPC_CREAT); 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"; # put the shmid on the message queue # 1 message for each client to connect # since each read shifts one off my $msgout = $segment_id; my $numclients = 3; for(1..$numclients){ $msg->snd(1, $msgout, 0 ); } #check it ( will reduce the number of msgs available #my $msgin = ''; #$msg->rcv($msgin, 8 ,0); # 8 bytes for a Perl integer #print "msgin->$msgin\n"; #$msg->rcv($msgin, 8 ,0); # 8 bytes for a Perl integer #print "msgin1->$msgin\n"; my $i = 'a'; while($go){ &write_m($i); $i++; select(undef,undef,undef,.1); 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); $msg->remove; return 0; } __END__

    ####### and this is the listener ##########################

    #!/usr/bin/perl # this script will take data from shmem use warnings; use strict; use IPC::SysV qw(IPC_STAT IPC_NOWAIT); use IPC::Msg; #see "perldoc perlfunc /shmget" and "perldoc perlipc /SysV" my $IPC_KEY = 1234; my $msg = new IPC::Msg($IPC_KEY,0); #my $msg = new IPC::Msg($IPC_KEY, 1); print "msg->$msg\n"; my $go = 1; #get shmid from msg my $segment_id; $msg->rcv($segment_id, 8 , 0); # 8 bytes for a Perl integer print "shmid->$segment_id\n"; $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\n"; last if ! $go; select(undef,undef,undef,.1); } ############################################################# sub size_m(){ my $segment_id = shift; my $shmbuffer = ''; shmctl ($segment_id, IPC_STAT, $shmbuffer); my @mdata = unpack("i*",$shmbuffer); #not sure if that is right unp +ack? works :-) print "segment size: ", $mdata[9], "\n"; return($mdata[9]); } #################################################################3 sub read_m(){ my $buff; #the $buff is paaded with nulls \0 to fill it out shmread($segment_id, $buff, 0, $segment_size) || die "$!"; # the buffer of shmread is zero-character end-padded. #substr($buff, index($buff, "\0")) = ''; return ($buff); } __END__

    I'm not really a human, but I play one on earth. flash japh