Basic Article 7: Chapter 15 Process Communication Pipeline supplement

Source: Internet
Author: User
Example 4:/* interaction between parent and child processes: the parent process writes from parent process to the child process, and the child process writes from child process to the parent process */

References

Http://kenby.iteye.com/blog/1166111 Linux Process Communication Pipeline 0. OrderInter-process communication IPC: inter-process communication actually refers to message transmission between processes. Pipelines can be used for communications between kinship-related processes. Famous pipelines overcome the restriction that pipelines do not have a name. Therefore, in addition to the functions of pipelines, it also allows communication between unrelated processes. The MPs queue is one of the original Unix IPC formats supported by Linux. It has the following features: the MPs queue is half duplex and data can only flow in one direction. Two MPs queues must be established when both parties need to communicate with each other; it can only be used between parent and child processes or brothers (kinship processes). It forms an independent File System: An MPs queue is a file for processes at both ends of the MPs queue, but it is not a common file, it does not belong to a certain file system, but a self-built portal, a separate file system, and only exists with memory. Data Reading and Writing: The content written by a process to the pipeline is read by the process at the other end of the pipeline. The written content is added at the end of the MPs queue buffer, and data is read from the buffer header each time. The two ends of the MPs queue are described by the descriptive characters FD [0] and FD [1]. The two ends of the MPs queue are fixed with tasks. FD [0] can only be used for reading. FD [1] is used for writing. FD [1] is used for writing. 1. Two important rules: When one end of the MPs queue is closedThe following two rules take effect: 1) when a write end is read and all data is read, read returns 0 to indicate that the end of the file is reached. 2) When writing a read-end closed pipeline, the sigpipe signal is generated. If this signal is ignored or captured and returned from its handler, write returns-1 and errno is set to epipe. 2. read data from the MPs queue1) if The write end does not exist.After reading all the existing data in the pipeline, it is deemed that the data has been read to the end, and the READ function returns Read wordsSection 0; 2) if the write end of the MPs queue has data, the current data bytes in the MPs queue or the requested bytes are returned. When the write end of the pipeline exists, if the number of bytes requested is greater than pipe_buf, the number of existing data bytes in the pipeline is returned. If the number of bytes requested is not greater than pipe_buf, return the number of existing data bytes in the MPs Queue (in this case, the data volume in the MPs queue is smaller than the requested data volume), or the number of returned bytes (in this case, the data volume in the MPs queue is not smaller than the requested data volume ). 3) If MPs queue has no dataAnd Write port is enabledStatus, read operation BlockedUntil data is written.
3. Write Data to the MPs queue: Write operations with blocking flag configured:(1) data volume to be written Not greaterWhen pipe_buf is used, Linux ensures the atomicity of writing. If the idle buffer of the pipeline is insufficient to accommodate the number of bytes to be written, the system goes to sleep until the buffer can accommodate the number of bytes to be written. (2) data volume to be written GreaterWhen pipe_buf is used, Linux will no longer guarantee the atomicity of writing. As soon as the FIFO buffer has an idle area, the write process will attempt to write data to the pipeline, and the write operation will return after writing all the data written by the request. For write operations without blocking flag set:(1) data volume to be written GreaterWhen pipe_buf is used, Linux will no longer guarantee the atomicity of writing. After the buffer is fully written into all the FIFO idle buffers, the write operation returns. (2) data volume to be written Not greaterWhen pipe_buf is used, Linux ensures the atomicity of writing. If the current FIFO idle buffer can accommodate the number of bytes written by the request, the result is returned successfully. If the current FIFO idle buffer cannot accommodate the number of bytes written by the request, the eagain error is returned, remind me to write it later. 4. Limitations of PipelinesThe main limitation of a pipeline is its characteristics: Only one-way data stream is supported; it can only be used between kinship-related processes; there is no name; the buffer of the MPs queue is limited (the MPs queue system exists in the memory and a page size is allocated to the buffer when the MPs queue is created). The MPs queue transmits a non-formatted byte stream, this requires that the reader and writer of the MPs queue have to specify the data format in advance, such as the number of bytes counted as a message (or command, or record; A famous pipeline exists in the file system as a FIFO file. In this way, even if there is no kinship between the Process and the FIFO creation process, as long as the path can be accessed, the process can communicate with each other through FIFO. 5. Learning cases:To fully understand the MPs queue, I have found some detailed example 1 on the Internet:
/* 1 only when the reference count of the MPs queue write end changes to 0 will the MPs queue write end be closed.
2. After the process ends, the opened files are automatically closed.
3 if the parent process exits first and does not call wait to wait for the child process, the child process will become a zombie process */
# Include <sys/Wait. H>
# Include <stdio. h>
# Include <unistd. h>
# Include <stdlib. h>

Int main (INT argc, const char ** argv)
{
Int Len;
Pid_t PID;
Int PFD [2];
Char buffer [1024] = {0 };

If (pipe (PFD) <0 ){
Printf ("pipe error \ n ");
Exit (0 );
}

If (pid = fork () <0 ){
Printf ("fork error \ n ");
Exit (0 );
}

If (pid = 0) {/* sub-process */
Write (PFD [1], "Hello \ n", 6 );
// Close (PFD [1]);
Sleep (2 );
} Else {/* parent process */
Close (PFD [1]);
While (LEN = read (PFD [0], buffer, 1023)> 0 ){
Buffer [Len] = '\ 0 ';
Printf ("Len = % d, % s", Len, buffer );
}
Printf ("read done \ n ");
Wait (0);/* wait until the sub-process exits to see the effect */
}
Return 0;
}
Example 2:
/* If the parent process does not close the write end of the pipeline, even if the child process closes the write end of the pipeline, it will still block the read
1) when reading a write end closed pipeline, all data is read, and read returns 0 to indicate that the end of the file is reached.
This program can describe this point well. When close (PFD [1]) in the parent is commented out, the program will be blocked */

# Include <stdio. h>
# Include <unistd. h>
# Include <stdlib. h>
# Include <sys/Wait. H>
Int main (INT argc, const char ** argv)
{
Int Len;
Pid_t PID;
Int PFD [2];
Char buffer [1024] = {0 };


If (pipe (PFD) <0 ){
Printf ("pipe error \ n ");
Exit (0 );
}

If (pid = fork () <0 ){
Printf ("fork error \ n ");
Exit (0 );
}

If (pid = 0) {/* sub-process */
Close (PFD [1]);
While (LEN = read (PFD [0], buffer, 1023)> 0 ){
Buffer [Len] = '\ 0 ';
Printf ("Len = % d, % s", Len, buffer );
}
} Else {/* parent process */
Close (PFD [0]);
Write (PFD [1], "Hello \ n", 6 );
// Close (PFD [1]);
Wait (0 );
}
Return 0;
}
Example 3:
/* When writing a read-end closed pipeline, the sigpipe signal is generated. If this signal is ignored or captured and returned from its handler, write returns-1 and errno is set to epipe.When running with GDB, it can be found that when writing a read end closed pipeline, the signal sigpipe */

# Include <sys/Wait. H>
# Include <stdio. h>
# Include <unistd. h>
# Include <sys/types. h>
# Include <fcntl. h>
# Include <stdlib. h>
# Define maxline 200
Int main (void)
{
Int N;
Int FD [2];
Pid_t PID;
Char line [maxline];
If (pipe (FD) <0)
Printf ("pipe error \ n ");
If (pid = fork () <0)
Printf ("fork error \ n ");
Else if (pid> 0 ){
Close (FD [0]);
While (1 ){
N = write (FD [1], "Hello, world", maxline );
If (n <= 0 ){
Printf ("n <= 0 \ n ");
Break;
}
Printf ("parent n: % d \ n", N );
}
Waitpid (PID, 0, 0 );
} Else {
Printf ("Child \ n ");
Close (FD [1]);
N = read (FD [0], line, maxline );
Write (stdout_fileno, line, N );
Close (FD [0]);
Printf ("close read end in child \ n ");
}
Exit (0 );
}

Example 4 of GDB running result:
/* Interaction between parent and child processes: the parent process writes from parent process to the child process, and the child process writes from child process to the parent process */

# Include <sys/Wait. H>
# Include <stdio. h>
# Include <unistd. h>
# Include <stdlib. h>
 
Int main (INT argc, const char ** argv)
{
Int pfd2 [2];
Pid_t PID;
Int pfd1 [2];
Int N;
Char buffer1 [1024] = {0}; char buffer2 [1024] = {0}
 
If (pipe (pfd1) <0) | (pipe (pfd2) <0 )){
Printf ("pipe error \ n ");
Exit (0 );
}
 
If (pid = fork () <0 ){
Printf ("fork error \ n ");
Exit (0 );
}
 
If (pid = 0) {/* sub-process */
Close (pfd1 [0]);
Write (pfd1 [1], "from child process", 1024 );
Close (pfd1 [1]);

Close (pfd2 [1]);
While (n = read (pfd2 [0], buffer1, 1024)> 0)
Write (stdout_fileno, buffer1, N );
Exit (1 );
} Else {/* parent process */

Close (pfd2 [0]);
Write (pfd2 [1], "from parent process", 1024 );
Close (pfd2 [1]);

Close (pfd1 [1]);

While (n = read (pfd1 [0], buffer2, 1024)> 0)
Write (stdout_fileno, buffer2, N );
Wait (0 );
}
Return 0;
}

Running result: I do not know why two from parent process examples appear. 5:
# Include <sys/Wait. H>
# Include <stdio. h>
# Include <unistd. h>
# Include <stdlib. h>
 
Int main (INT argc, const char ** argv)
{
Int pfd2 [2];
Pid_t PID;
Int pfd1 [2];
Int N;
Char buffer1 [1024] = {0}, buffer2 [1024] = {0 };
 
If (pipe (pfd1) <0) | (pipe (pfd2) <0 )){
Printf ("pipe error \ n ");
Exit (0 );
}
 
If (pid = fork () <0 ){
Printf ("fork error \ n ");
Exit (0 );
}
 
If (pid = 0) {/* sub-process */
Close (pfd1 [0]);
Write (pfd1 [1], "from child process", 1024 );

Close (pfd1 [1]);
Close (pfd2 [1]);
While (n = read (pfd2 [0], buffer1, 1024)> 0 ){
Buffer1 [N] = '\ 0 ';
Printf ("buffer1: % s \ n", buffer1 );
}
Exit (1 );
} Else {/* parent process */
Close (pfd1 [1]);
Close (pfd2 [0]);
Write (pfd2 [1], "from parent process", 1024 );
Close (pfd2 [1]);
While (n = read (pfd1 [0], buffer2, 1024)> 0 ){
Buffer2 [N] = '\ 0 ';
Printf ("buffer2: % s \ n", buffer2 );
}
Wait (0 );
}
Return 0;
}

6. SummaryPipe: used for inter-process communication. Pipelines have their own limitations: 1) Half Duplex 2) Only the read and write operations on the communication pipeline can be performed between processes with common ancestor: 1) pipeline read Operations :( 1) normal read (2) after reading all the data, the system returns 0, indicating the end Of the file. 2) pipeline write operations: (1) normal write (2) writing to the closed channel of the read end, the sigpipe signal is generated. If this signal is ignored or captured and returned from its handler, write returns-1 and errno is set to epipe.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.