Kevintz 2000.8.23
The Int pipe (int fd [2]) function generates an internal pipeline ,. Returned
FD [0] descriptor is used to read content from the pipeline, and FD [1] is used to write content to the pipeline.
---------------------
FD [0] ---------------------
When reading data, the read process is blocked if there is no data in the pipeline. If the pipeline is full at the time of writing,
Write process blocking. You can set FD [0] and FD [1] as non-blocking. In the above blocking situation,
Process no longer blocked and return immediately.
One end of an MPS queue can only be read-only or write-only. If you write to fd [0] and read to fd [1 ],
Error.-1 is returned.
In addition, the child process generated by fork () calls shares the same pipeline with the original parent process,
It does not generate another pipeline. :
+ ------------------------ +
|
------------- +------------ Parent | FD [0] | FD [0] | child
| ----------- |
| FD [1] | ------------------------ ++ --- | FD [1] |
| ...... |
In addition, for sub-processes, FD [0] is also used for read-only, FD [1] is also used for write, because
They point to the same as in the parent process.
Next, we will analyze the program written by Startrek and analyze the cause of the error.
Int main (){
Int FD [2];
Char Buf [200], Len;
Int status;
If (pipe (FD) = 0 ){
If (Fork () = 0 ){
Len = read (FD [0], Buf, sizeof (BUF ));
Buf [Len] = 0;
Printf ("[child]: % s/n", Buf );
Sprintf (BUF, "answer from child ");
Write (FD [1], Buf, strlen (BUF ));
}
Else {
Sprintf (BUF, "string from parent ");
Write (FD [1], Buf, strlen (BUF ));
Sleep (2 );
Len = read (FD [0], Buf, sizeof (BUF ));//***
Buf [Len] = 0;
Printf ("[Parent]: % s/n", Buf );
}
}
Wait (& status );
}
[Scenario 1]
If sleep (2) is commented out, the parent process receives
String, display
[Parent]: string from parent
The sub-process is blocked because there is no data read. This indicates that the parent process and child process are only
An MPs queue performs bidirectional transmission. After the parent process reads data, the MPs queue is empty.
Process blocking.
Kevintz analysis: in fact, this result is correct. The reason is as follows: when sleep (2) is removed
After writing FD [1], run read (...).
. When the sub-process is running, it is blocked because there is no data read. Note: MPS queue
Only one-way transmission is supported!
[Case 2]
However, if you change the sentence marked **
Len = read (FD [1], Buf, sizeof (BUF), and sleep (2); without comments, there will be
The following strange results are displayed:
[Child]: string from parent
[Parent]: string from parent
After the sub-process exits, the pipeline should only contain "answer from child ".
Kevintz analysis: The result is correct. In fact, the child process has read the content of the parent process,
It has been written back to the MPs queue. However, because both the parent process and the child process read FD [1,
All errors occur.-1 is returned, while the Buf still contains sprintf.
Buf [Len] indicates that Buf [-1] = 0 is potentially dangerous. Then you print the Buf
The original content. One end of the MPs queue can only be read-only or write-only!
[Case 3]
In the same way as Case 2, add the last three rows, that is, the parent process uses FD [0] For read.
The result is
[Child]: string from parent
[Parent]: string from parent
[Parent]: Answer from child
Kevintz analysis: In this example, situation 2 is parsed. It indicates that the child process does receive the parent process.
And write it back to the MPs queue. The parent process should read it using read (FD [0 ]...),
To read the information written back by the sub-process.
[Scenario 4]
If the parent process transmits a string "string 2 from parent" at the beginning, the result is
It is more complicated.
Kevintz analysis: haha :), upload another string and analyze the result ................
Summary:
In fact, two pipelines should be used to form a two-way communication pipeline, instead of one
MPs queues.
Of course, you can use semaphores to synchronize the use of pipelines, but they are too complicated and impractical. Bidirectional Pipeline
This can be achieved.
Int main ()
{
Int fd1 [2], fd2 [2], Len;
Char Buf [128];
Int status;
Pipe (fd1 );
Pipe (fd2 );
If (Fork () = 0)
{
Close (fd1 [0]);
Close (fd2 [1]);
Len = read (fd2 [0], Buf, 128 );
Buf [Len] = 0;
Printf ("[child]: % s/n", Buf );
Sprintf (BUF, "answer from child ");
Write (fd1 [1], Buf, strlen (BUF ));
Close (fd2 [0]);
Close (fd1 [1]);
}
Else
{
Close (fd1 [1]);
Close (fd2 [0]);
Sprintf (BUF, "hello from parent ");
Write (fd2 [1], Buf, strlen (BUF ));
Len = read (fd1 [0], Buf, sizeof (BUF ));
Buf [Len] = 0;
Printf ("[Parent]: % s/n", Buf );
Close (fd1 [0]);
Close (fd2 [1]);
}
Wait (& status );
Exit (0 );
}
--
※Modify:. kevintz modify this article at Aug 23 11:08:13. [from: 61.140.71.100]