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