main content: Anonymous pipe, command pipeline. (Pipe, Popen, Mkfifo functions)
Pipe Introduction:
Pipelines are a way of communicating between processes, which is equivalent to having a tunnel between two processes that can pass the message through the tunnel; The pipe is located outside the address space of the process, and the pipe is divided into anonymous pipes and named pipes two kinds;
anonymous pipes are created by pipe, and named Pipes are created by Mkfifo;
#include <unistd.h>
int pipe (int pipefd[2]);
Returns two descriptors: Pipefd[0] is the read end of the pipe, pipefd[1] is the writing end of the pipe;
The following is an instance of a parent-child process using pipe communication: The main function creates two pipes and generates a subprocess with fork, which runs as a parent, and the server runs as a child process. The first pipe is used to send the pathname from the client to the server, and the second pipeline is used to send the contents of the file from the server to the client.
Client Write pipe1[1]-----pipe1[0] Server Read
Server Write pipe2[1]-----pipe2[0] Client Read
/************************************************************************* > File name:mainpipe.c > Author: &G T Mail: > Created time:2016 year April 20 Wednesday 22:25 15 seconds ****************************************************************** /* * Main function creates two pipes and generates a child process with fork * The client runs as a parent, and the server runs as a subprocess * The first pipe is used to send the pathname from the client to the server * The second pipeline is used to send the file from the server to the client * CIN --Client Write pipe1[1]-----pipe1[0] Server Read * server write pipe2[1]-----pipe2[0] Client Read * * * #include <stdio.h> #include <unistd.h>
; #include <sys/types.h> #include <sys/wait.h> #include <string.h> #include <sys/stat.h> #
Include <fcntl.h>//the server reads the name of the file from the RfD and writes the contents of the file to the WFD void server (int rfd, int wfd) {char filename[1024];
Char filecontent[2048];
memset (fileName, 0, 1024);
memset (filecontent, 0, 2048);
Read the name of the file from the rfd, int n = Read (RFD, fileName, 1024);
Filename[n] = 0;
printf ("Server receive the file name is%s\n", fileName); int filefd = open (FileName, o_rdonly);//Open TextPieces if (FILEFD < 0) {printf ("open error\n");
Return
else{//reads the contents of the file and writes it to the WFD//reads the contents of the file into filecontent int num = 0; while (num = Read (FILEFD, filecontent, 2048)) > 0} {printf ("server Read the Filecontent is:%s", Fileconten
T);
Writes the contents of the filecontent to the WFD write (WFD, filecontent, num);
} close (FILEFD);
Close (RFD);
Close (WFD);
}//Client reads the contents of the file from the RfD and writes the file to WFD in the name void client (int rfd, int wfd) {char filename[1024];
Char filecontent[2048];
memset (fileName, 0, 1024);
memset (filecontent, 0, 2048);
printf ("Input file name:");
The name of the input file from the standard input fgets (fileName, 1024, stdin);
int len = strlen (fileName);
if (filename[len-1] = = ' \ n ') len--;
Write the name of the file to the WFD (WFD, FileName, Len);
printf ("filename =%s\n", filename);
Reads the contents of the file from the RfD int n; while ((n = Read (RFD, filecontent, 2048)) > 0) {printf ("Client receive thE content is:%s ", filecontent);
Close (RFD);
Close (WFD);
}//main function int main () {//Create two pipes.
int pipe1[2], pipe2[2];
int ret = pipe (PIPE1);
if (Ret < 0) {printf ("pipe error\n");
return-1;
RET = pipe (PIPE2);
if (Ret < 0) {printf ("pipe error\n");
return-1;
//Create a subprocess as a server to read the filename in pipe 1 (pipe1[0]) and output the contents of the file to the pipe2[1 of pipeline 2 pid_t child_pid = fork ();
if (Child_pid < 0) {printf ("fork error\n");
return-1;
else if (Child_pid > 0) {//parent process//shutdown Pipe 1 Write, close pipe 2 read, pipe1[1], pipe2[0] Close (pipe1[1);
Close (pipe2[0]);
Server (Pipe1[0], pipe2[1]);
else if (Child_pid = = 0) {//subprocess/Shut down pipe 1 read, close pipe 2 write, pipe1[0], pipe2[1] Close (pipe1[0);
Close (pipe2[1]);
Client (Pipe2[0], pipe1[1]);
} waitpid (Child_pid, NULL, 0);/wait child process exit return 0;
}
The results of the operation are:
root@linux_ever:~/linux_ever/process_thread/ch4#./mainpipe
Input file name:./data
filename =./data
Server Receive the file name is./data
Server Read the filecontent is:file content linuxever
client receive the content Is:file content Linuxever
known pipes (also known as FIFO):A well-known pipe is created with the Mkfifo function.
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo (const char *pathname, mode_t mode)
Create named pipe successfully returned 0; parameter is a pathname is the name of the FIFO pipeline file created; Mode user right is the identity bit, for example, 0644;
Once you have created a pipe file, you need to open the file when you want to communicate with it and other processes.
open rule for Named Pipes if the current open operation is open FIFO for reading
1:o_nonblock disable: block until a corresponding process opens the FIFO for writing
2:o_nonblock enable: Immediately return to success
If the current open operation is open FIFO for write
1:o_nonblock disable: block until a corresponding process opens the FIFO for reading
2:o_nonblock enable: Immediately return failure, error code is ENXIO
OUTFD = open ("Fifop", O_wronly | O_nonblock);/Not blocking write
OUTFD = open ("Fifop", o_wronly); Blocking mode
For example:
1: A process opens the named pipe write, which is blocked by default, and if the pipe does not have another process open for reading, the process blocks on write until there is a process read open;
2: A process opens the named pipe read, which is blocked by default, and if the pipe does not have another process open to write, the process blocks on read until there is a process write open;
Usually open in blocking mode, if it is open in non-blocking mode, every time from the file to read data will return immediately, even if there is no data;
Named pipes and anonymous pipes difference: 1: One limitation of pipeline applications is that only communication between processes that have a common ancestor (a kinship).
2: If we want to exchange data between unrelated processes, you can use a FIFO file to do this work, which is often referred to as a named pipe.
3: Named pipe is a special type of file;
pipelines can pass data between parent-child processes
Pipelines can pass data between parent-child processes, taking advantage of the fact that two pipe file descriptors pipefd[0] and pipefd[1 are open after the fork call. This enables the parent process to pass data to the child process through pipelines, or the child process passes the data to the parent process through a pipe.
If you want to transfer data in both directions, you can create two pipes. You can also create a full-duplex pipe by Socketpair.
Example 1: The parent process communicates through anonymous and child processes, the parent process writes data to the anonymous pipe, and the subprocess reads the data from the anonymous pipe and outputs it to the standard output
/************************************************************************* > File Name:pipe1.cpp > Author: " ; Mail: > Created time:2015 year December 20 Sunday 19:48 57 seconds ****************************************************************** /#include <iostream> #include <unistd.h> #include <cstdlib> #include <fcntl.h> #include &
lt;string> #include <sys/wait.h> #include <string.h> using namespace std;
/* 1: The parent process creates a pipeline, 0-read, 1-write 2: The parent process creates a subprocess 3: Let the parent process write information to the pipeline, the subprocess reads the information from the pipe, and writes the message from the standard input to the pipe 4: The child process outputs the read information to the standard output/int main () {
int pipefd[2];
Char buff[1024];
memset (buff, 0, 1024);
int ret = pipe (PIPEFD);
if (ret!= 0) {cerr << "pipe error ..." << Endl;
Exit (-1);
pid_t pid = fork ();
if (PID < 0) {cerr << "fork error ..." << Endl;
Exit (-1);
else if (PID = = 0) {//Close the write end of the pipe (pipefd[1]);
int ret = 0; cout << "TThe ' child process ... ' << Endl;
while (1) {ret = read (pipefd[0], (void *) buff, 1024);
if (ret = 0) {cout << "end of Read ..." << Endl;
Exit (0);
} cout << "child read:";
cout << buff << Endl;
memset (buff, 0, 1024);
Close (pipefd[0]);
else if (PID > 0) {close (pipefd[0]);
cout << "This is parent process ..." << Endl;
while (Cin.getline (buff, 1024)) {cout << "parent write:";
cout << buff << Endl;
Write (pipefd[1], buff, 1024);
memset (buff, 0, 1024);
Close (pipefd[1]);
Wait (NULL);
} exit (0);
}
Example 2: Using a named pipe instance
Process 1 Creates a named pipe Myfifo and writes it open in blocking mode, and process 1 obtains data from standard input and writes to the named pipe;
Process 2 read in a blocking way open the named pipe file Myfifo, process 2 reads the data from the named pipe and outputs it to the standard output;
Process 1:write_fifo.cpp
/************************************************************************* > File Name:write_fifo.cpp > Author: > Mail: > Created time:2015 year December 20 Sunday 20:53 29 seconds ***************************************************** /#include <iostream> #include <sys/types.h> #include <sys/stat.h> #include <
cstdlib> #include <fcntl.h> #include <string.h> #include <unistd.h> using namespace std;
/* 1: Create named pipe 2: from standard input to buffer 3: Open named pipe, write contents of buffer into named pipe/int main () {int ret = MKFIFO ("Myfifo", 0666);
if (Ret < 0) {cerr << "Mkfifo error ..." << Endl;
Exit (-1);
} Char buff[1024];
memset (buff, 0, 1024);
int wrfd;
cout << "wating for another process open the Myfifo to Reading ..." << Endl;
WRFD = open ("Myfifo", o_wronly);
if (wrfd = = 1) {cerr << "open error ..." << Endl;
Exit (-1);
pid_t pid = Getpid (); cout<< "Process" << pid << "write:";
while (Cin.getline (buff, 1024)) {write (WRFD, buff, strlen (buff));
memset (buff, 0, 1024);
cout << "process" << pid << "write:";
Close (WRFD);
Exit (0);
}
Process 2:read_fifo.cpp
/************************************************************************* > File Name:write_fifo.cpp > Author: > Mail: > Created time:2015 year December 20 Sunday 20:53 29 seconds ***************************************************** /#include <iostream> #include <sys/types.h> #include <sys/stat.h> #include <
cstdlib> #include <fcntl.h> #include <string.h> #include <unistd.h> using namespace std;
/* 1: Create named pipe 2: from standard input to buffer 3: Open the named pipe, write the contents of the buffer into the named pipe/int main () {char buff[1024];
memset (buff, 0, 1024);
int RDFD;
int ret = 0;
RDFD = open ("Myfifo", o_rdonly);
if (RDFD < 0) {cout << "open error ..." << Endl;
Exit (-1);
} cout << "Waiting for reading...\n";
while (1) {ret = read (RDFD, buff, 1024);
if (ret = 0) {cerr << "end of Read ..." << Endl;
Break } cout << "process" << Getpid () << "read:" << buff << Endl;
memset (buff, 0, 1024);
Close (RDFD);
Exit (0);
}
The Myfifo file in the following figure is the named pipe you created, and you can see that its file type is P-start;
Popen Function Introduction: The standard I/O function library provides a popen function that creates a pipe and launches another process that either reads standard input from the pipe or writes standard output to the pipe.
#include <stdio.h>
FILE *popen (const char *command, const char *type);
int Pclose (FILE *stream);
If type is r, the process that calls the function reads the standard output of the command.
If Type is w, the process that calls the function writes the standard input of the command.
Instance:
/************************************************************************* > File name:popen.c > Author: > M AIL: > Created time:2016 year April 22 Friday 21:28 40 seconds *******************************************************************
/#include <stdio.h> #include <string.h> int main () {char buffer[1024];
Char command[1024];
memset (buffer, 0, 1024);
memset (command, 0, 1024);
Enter command printf ("Input the Command:");
Fgets (Command, 1024, stdin);
Remove newline symbol int n = strlen (command);
if (command[n] = ' \ n ') {//command[n] = 0;//must be assigned a value of 0, can not be ' 0 ' command[n] = '; '/must be assigned a value of 0, or ' yes ', cannot be ' 0 '}
Call Popen Execute command//type= ' r ', the standard output of the command is output to the pipeline, and the FP is used to draw the FILE * fp = popen (Command, "R");
if (fp = = NULL) {printf ("Popen error\n");
return-1;
printf ("Output command's standard output:");
The standard output of the command is read from FP while (fgets (buffer, 1024, FP)!= NULL) fputs (buffer, stdout);
Pclose (FP); return 0;
}
Run Result:
Standard output for output command: root@linux_ever:~/linux_ever/process_thread/ch4#./readpopen
Input the Command:cat data
Standard output for output command: file content linuxever
root@linux_ever:~/linux_ever/process_thread/ch4#./readpopen
Input
the standard output of the COMMAND:LS output command: Data
mainpipe
mainpipe.c
readpopen
readpopen.c
root@linux _ever:~/linux_ever/process_thread/ch4#./readpopen
Input the command:ls-l
output command standard output: Total dosage
- rw-r--r--1 root April 21:08 data
-rwxr-xr-x 1 root root 13377 April 22:12
mainpipe-rw-r --r--1 root 3499 April 22:12 mainpipe.c
-rwxr-xr-x 1 root root 9063 April 22:08 readpopen
-rw-r--r--1 root 1146 April 22:08 readpopen.c