In the previous article--linux interprocess communication-Using anonymous pipelines, we saw how anonymous pipelines can be used to pass data between processes, as well as a flaw in the way that these processes are initiated by a common ancestor process, This makes it inconvenient for us to exchange data between unrelated processes. Here's another way to communicate the process-Named pipes-to address the communication issues between unrelated processes.
first, what is a named pipe
A named pipe is also known as a FIFO file, which is a special type of file that exists as a file name in the filesystem, but behaves like a previously unnamed pipe (anonymous pipe).
Since everything in Linux can be treated as a file, the use of named Pipes has become very consistent with file operations, makes it easy to use, and can be used in commands like normal file names.
Second, create a named pipe
We can use one of the two functions to create a named pipe whose prototype is as follows:
#include <sys/types.h>
#include <sys/stat.h>
int Mkfifo(const char *filename, mode_t mode);
int Mknod(const char *filename, mode_t mode | S_ififo, (dev_t) 0);
Both functions create a FIFO file, note that a file is created that is actually present in the file system, and filename specifies the file name, and mode specifies the read and write permissions for the files.
Mknod is an older function, and using the MKFIFO function is simpler and more prescriptive, so it is recommended to use MKFIFO instead of mknod whenever possible.
third, access Named Pipes
1. Open FIFO file
Like opening other files, FIFO files can also be opened using the open switch. Note that the MKFIFO function simply creates a FIFO file to use a named pipe or open it.
But there are two points to note :
1, is the program can not open the FIFO file in O_rdwr mode to read and write operations, and its behavior is not clearly defined, because if a pipe is opened in read/write mode, the process will read back to its own output, and we usually use FIFO just for one-way data transfer.
2, is passed to the open call is the FIFO path name, but not the normal file.
There are usually four ways to open a FIFO file,
Open (const char *path, o_rdonly); 1
Open (const char *path, O_RDONLY | O_nonblock); 2
Open (const char *path, o_wronly); 3
Open (const char *path, O_WRONLY | O_nonblock); 4
In the second argument of the Open function call, you see an unfamiliar option O_nonblock, the option O_nonblock represents non-blocking, plus this option indicates that the open call is non-blocking, and if this option is not, the open call is blocked.
What is the blocking of the open call ? Very simply, for FIFO files opened in read-only mode (o_rdonly), if the open call is blocked (that is, the second parameter is o_rdonly), it will not return unless there is a process that opens the same FIFO in write mode. If an open call is non-blocking (that is, the second argument is O_rdonly | O_nonblock), the open call succeeds and returns immediately, even if no other process opens the same FIFO file in write mode.
For FIFO files opened in write-only mode (o_wronly), if the open call is blocked (that is, the second parameter is o_wronly), the open call is blocked until a process opens the same FIFO file as read-only If the open call is non-blocking (that is, the second argument is O_wronly | O_nonblock), open always returns immediately, but if no other process opens the same FIFO file in read-only mode, the open call returns 1, and the FIFO is not opened.
Iv. using FIFO to achieve interprocess communication
Having said so much, here is an example program to illustrate how two processes can communicate through FIFO implementations. Here are two source files, one fifowrite.c, which creates a pipeline when needed, then writes data to the pipeline, the data is provided by the file Data.txt, the size is 10M, and the contents are all characters ' 0 '. Another source file is FIFOREAD.C, which reads data from the FIFO and saves the read data to another file DataFormFIFO.txt. To make the program more concise, it ignores the check that some function calls are successful.
The source code for FIFOWRITE.C is as follows:
#include <unistd.h> #include <stdlib.h> #include <fcntl.h> #include <limits.h> #include <sys /types.h> #include <sys/stat.h> #include <stdio.h> #include <string.h>int main () {const char *fifo_ Name = "/tmp/my_fifo"; int pipe_fd = -1;int DATA_FD = -1;int res = 0;const int Open_mode = O_wronly;int Bytes_sent = 0;char Buffer[pipe_buf + 1];if (Access (fifo_name, F_OK) = =-1) {//pipe file does not exist//create named pipe res = Mkfifo (fifo_name, 0777); if (res! = 0) {FP rintf (stderr, "Could not create FIFO%s\n", fifo_name); exit (exit_failure);}} printf ("Process%d opening FIFO o_wronly\n", Getpid ())//open FIFO file as write-only blocking, open data file as read-only pipe_fd = open (Fifo_name, Open_ mode);d ata_fd = open ("Data.txt", o_rdonly);p rintf ("Process%d result%d\n", Getpid (), PIPE_FD); if (pipe_fd! =-1) {int byte S_read = 0;//reads data to data file Bytes_read = Read (data_fd, buffer, pipe_buf); Buffer[bytes_read] = ' + '; while (Bytes_read > 0) {// Write data to FIFO file res = write (pipe_fd, buffer, bytes_read); if (res = =-1) {fprintf (stderr, "write Error on pipe\n "); exit (exit_failure);} Accumulate the number of bytes written and continue to read the data bytes_sent + = Res;bytes_read = Read (data_fd, buffer, pipe_buf); Buffer[bytes_read] = ' n ';} Close (PIPE_FD); close (DATA_FD);} Else{exit (exit_failure);} printf ("Process%d finished\n", getpid ()); exit (exit_success);}
#include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <fcntl.h> #include <sys/ types.h> #include <sys/stat.h> #include <limits.h> #include <string.h>int main () {const char *fifo_ Name = "/tmp/my_fifo"; int pipe_fd = -1;int DATA_FD = -1;int Res = 0;int Open_mode = O_rdonly;char Buffer[pipe_buf + 1];int Bytes_read = 0;int Bytes_write = 0;//empties the buffer array memset (buffer, ' ', sizeof (buffer));p rintf ("Process%d opening FIFO o_rdonly \ n ", Getpid ());//Open the pipe file as read-only blocking, note the same name as the FIFO in the fifowrite.c file PIPE_FD = open (Fifo_name, open_mode);//Create a file that holds the data in a write-only manner Data_ FD = open ("DataFormFIFO.txt", O_wronly | O_creat, 0644);p rintf ("Process%d result%d\n", Getpid (), PIPE_FD), if (pipe_fd! =-1) {do{//reads data from the FIFO, and save it in the file DataFormFIFO.txt file res = read (pipe_fd, buffer, pipe_buf); bytes_write = Write (data_fd, buffer, res); Bytes_read + = res;} while (res > 0); close (PIPE_FD); close (DATA_FD);} Else{exit (exit_failure);} printf ("Process%d finished,%d bytes read\n", Getpid (), bytes_reAD); exit (exit_success);}
The results of the operation are as follows:
Analysis: Two programs are using the FIFO of blocking mode, in order to let people see clearly what is blocking what is the matter, first we run Fifowrite.exe, and put it in the background to run. When you call the jobs command, you can see that it is actually running in the background, after 5 seconds, and then calling the Jobs command, you can see that the process Fifowrite.exe is not over yet and it continues to run. Because the open call of the Fifowrite.exe process is blocked and no other process has opened the same FIFO in read mode while the Fiforead.exe is not running, it has been waiting, open is blocked, and no return. Then, when our process Fiforead.exe run (in order to see performance, run in the time command), the open call in Fifowrite.exe returns, the process begins to work, and then the process ends. While Fiforead.exe's open call is blocking mode, the Fifowrite.exe is already running, that is, another process has opened the same FIFO in writing, so the open call returns immediately.
From the output of time, the pipeline efficiency is very high, because fiforead.exe both to read data, but also to write data to the file DataFormFIFO.txt, 10M of data only used a little more than 0.1 seconds.
In addition , if you enter the following command in the shell at this point, ls-l/tmp/my_fifo, you can see the following results:
To prove that the FIFO file is indeed a file that exists in the file system, the first character of the file attribute is ' P ', which indicates that the file is a pipe.
v. Security issues for Named Pipes
The previous example is a communication problem between two processes, that is, one process writes data to a FIFO file, while another process reads the data in a FIFO file. Imagine a problem, using only a FIFO file, if there are multiple processes simultaneously to the same FIFO file to write data, and only a read FIFO process in the same FIFO file to read data, what happens when the data block interleaving is normal? Moreover, it is common for individuals to think that multiple different processes are sending data to a FIFO read process.
In order to solve this problem, it is to let the atomization of the write operation. How can I make a write operation atomized? The answer is simple: In a FIFO opened in o_wronly (that is, blocking mode), if the length of the data being written is less than the waiting pipe_buf, either all bytes are written, or none of the bytes are written. If all of the write requests are destined for a blocking FIFO, and the data length of each write request is less than or equal to Pipe_buf bytes, the system ensures that the data will never be interleaved.
Vi. Comparison of Named pipes with anonymous pipelines
With anonymous pipes, the communication process requires a parent-child relationship, and the two processes that communicate must be initiated by a common ancestor process. But the anonymous pipeline does not have the data crossover problem mentioned above.
Compared to using anonymous pipelines, we can see that the two processes of Fifowrite.exe and fiforead.exe are not necessarily connected, if hard to say they have some kind of connection, they can only say that they all access the same FIFO file. It solves the problem that the two processes that previously appeared in the anonymous pipeline must be initiated by a common ancestor process. But for the sake of data security, we often have to use a blocking FIFO, which turns the write operation into an atomic operation.
Reference:
http://blog.csdn.net/ljianhui/article/details/10202699
Linux inter-process communication-Using named pipes