[comp.unix.questions] Questions regarding PIPES and SHARED MEMORY.

ashraf@maccs.dcss.mcmaster.ca (Ashraf Mahmoud) (06/15/91)

Hello every Body,

    I would like first to thank all the unix-group readers who responded to   
my previous question about reading from pipes and how to make it nonblocking.
I have two more questions, the first is really a consequence of the solution I
have received: 
Q1. The following code makes child read from pipe in a nonblocking manner. But
    it seems, when I run the code, that not all messages sent by parent are 
    received by child. Some are lost. The child is supposed to receive five 
    messages (i=0,1,..,4). Sometimes it receives those for i = 0,2,4, and
    sometimes different messages, it differs each execution. How to fix it?
 
 Code:
   ------------------------------------------------------------
#include<stdio.h>
#include<string.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>


void main ()
{
 int pid1 , fdes[2];
 int FLAGMINE ;
 int status, i ;
 char buf[80];

 pipe(fdes) ;

 fcntl( fdes[0], F_GETFL, &FLAGMINE );
 FLAGMINE = O_NDELAY;
 fcntl( fdes[0], F_SETFL, &FLAGMINE );

 if ((pid1 = fork()) == 0 ) {
                           child1(fdes);
                           exit (0);
                           }
 close(fdes[0]) ;
 for(i=0; i<5; i++) 
 { 
  sprintf(buf,"Parent Calling Child %d Itr = %d",pid1,i);
  write(fdes[1],buf,strlen(buf)+1);
 }
 wait(&status) ;
}

child1( fdes ) 
int fdes[2] ;
{
 int i;
 char buf[80];
 
 close(fdes[1]) ;
 for(i=0; i<1500; i++){
     strcpy(buf,"");
     read(fdes[0],buf,80);
     printf("\n Read succeeded i = %d ",i);
     printf("\nChild> %s",buf);
    
 }
}
          ------------------------------------------------------------


Q2. Any idea about how to declare a certain area ( variables or structures ) 
    in memory where more than one process ( or agent ) can have access to it?
    What type of control ( regarding setting semiphores and other things) is
    required? And how to do it? A simple code for a small example would be    
    appreciated.

    Thank you all out there in advance. Any useful response is greatly welcomed.

    

Ashraf S. Mahmoud
McMaster U.

rickert@mp.cs.niu.edu (Neil Rickert) (06/15/91)

In article <285926A1.13114@maccs.dcss.mcmaster.ca> ashraf@maccs.dcss.mcmaster.ca (Ashraf Mahmoud) writes:
>Q1. The following code makes child read from pipe in a nonblocking manner. But
>    it seems, when I run the code, that not all messages sent by parent are 
>    received by child. Some are lost. The child is supposed to receive five 

  --- segment of code for parent ---

> for(i=0; i<5; i++) 
> { 
>  sprintf(buf,"Parent Calling Child %d Itr = %d",pid1,i);
>  write(fdes[1],buf,strlen(buf)+1);
> }

  --- segment of code for child ---

> close(fdes[1]) ;
> for(i=0; i<1500; i++){
>     strcpy(buf,"");
>     read(fdes[0],buf,80);
>     printf("\n Read succeeded i = %d ",i);
>     printf("\nChild> %s",buf);

 You are reading 80 bytes each time.  Since your writes are for less than
80, your first read may include part of the second write string.  However
when processing the data you read, you are ignoring everything past the
'\0' which terminates the first string written.

 I believe you are confused about the meaning of "non blocking".  This only
means that your process will not wait if there is nothing to read.  It
does not guarantee that your process will always be scheduled (i.e. given
CPU time) as soon as there is data to read.  It is quite conceivable that
the writing process may do two or more write operations during its time
slice, before relinquishing control of the CPU.  In this case your read
could read up to 80 bytes, which might contain parts of 2 or more written
records.

 It is, in principle, possible also for the writing process to write only
part of its output before losing its time slice.  In practice Unix
implementations do not permit this with such small buffers, but depending
on that behavior is bad programming.  If, for example, the writing process
were to write 10K bytes at one shot, it would surely be interrupted in the
middle, and the reading process would read only a partial record at the
next read.

 To properly handle this the reading process must keep track of how many
bytes have been read but not yet processed.  It should expect that any
record read may not be complete in which case the next successful read
will begin with the continuation of that record, and even that continuation
need not be complete.  It should also expect that following the end of one
record the same read operation may have retrieved part or all of the next
record.  (By "record" here, I just mean the data output in a single "write"
in the parent process).

--
=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
  Neil W. Rickert, Computer Science               <rickert@cs.niu.edu>
  Northern Illinois Univ.
  DeKalb, IL 60115                                   +1-815-753-6940
-- 
=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
  Neil W. Rickert, Computer Science               <rickert@cs.niu.edu>
  Northern Illinois Univ.
  DeKalb, IL 60115                                   +1-815-753-6940