nameless pipes (pipe)
Pipelines can be used for communication between affinity processes, and well-known pipelines overcome the limitations of pipe without name, so that, in addition to having the functions of a pipeline, it allows communication between unrelated processes;
define function: int pipe (int filedes[2])
Filedes[0] is the read end in the pipe
FILEDES[1] is the write end of the pipeline.
Implementation mechanism:
A pipeline is a buffer that is managed by the kernel, which is the equivalent of a note we put into memory. One end of the pipeline connects to the output of a process. This process will put information into the pipeline. The other end of the pipeline connects to the input of a process that takes out the information that is put into the pipeline. A buffer does not need to be large, it is designed to be a circular data structure so that the pipeline can be recycled. When there is no information in the pipeline, the process read from the pipeline waits until the process at the other end puts the information. When the pipeline is filled with information, the process that tries to put it in will wait until the process on the other side takes out the information. When all two processes are terminated, the pipeline disappears automatically.
In principle, the pipeline is built using the fork mechanism, so that two processes can be connected to the same pipe. At the beginning, the two arrows above are connected to the same process 1 (two arrows connected to process 1). The two connections are also copied to the new process (process 2) when the fork is copied. Subsequently, each process closes itself without the need for a connection (two black arrows are turned off; Process 1 Closes the input connection from the pipe, process 2 closes the output to the pipe connection), so that the remaining red connections constitute the pipe
First, the pipeline reading and writing attention point
1. Pipe must be called before the system calls fork, otherwise the child process will not inherit the file descriptor
2. It makes sense to write to the pipe only when the pipe read-end is present; otherwise, you will receive an error signal from the kernel: sifpipe writing to a pipe is meaningful only if the pipe read is present; otherwise, you receive an error signal from the kernel: sifpipe
3. When writing data to a pipeline, there is no guarantee of the atomicity of the write, and the write process attempts to write to it when the pipeline buffer has an idle area. If the read process does not read the contents of the pipeline, the write process is blocked.
4. Parent-child processes are not guaranteed to be sequential when they are run. So here, to ensure that the parent process closes the read descriptor, you can add sleep (2) to the child process.
Second, examples
1. Nameless Pipes
/*pipe_rw.c*/#include<unistd.h>#include<sys/types.h>#include<errno.h>#include<stdio.h>#include<stdlib.h>intMain () {intpipe_fd[2]; pid_t pid; Charbuf_r[ -]; Char*P_wbuf; intR_num; memset (Buf_r,0,sizeof(Buf_r)); if(Pipe (PIPE_FD) <0) {printf ("Pipe Create error\n"); return-1; } if((Pid=fork ()) = =0)//if the child process{printf ("\ n"); /*closes the child process pipeline write end. Sleep 2 seconds to ensure that the parent process has closed the pipe read-side appropriately*/Close (pipe_fd[1]); Sleep (2); /*child process reads pipeline contents*/ if((R_num=read (pipe_fd[0],buf_r, -)) >0) {printf ("%d numbers read from the pipe is%s\n", R_num,buf_r); } /*Close the sub-process read*/Close (pipe_fd[0]); Exit (0); } Else if(pid>0) { /*Close Parent Process read- only*/Close (pipe_fd[0]); /*write data to the pipeline two times*/ if(Write (pipe_fd[1],"Hello",5)!=-1) printf ("Parent Write1 success!\n"); if(Write (pipe_fd[1],"Pipe",5)!=-1) printf ("Parent Write2 success!\n"); /*closes the parent process write and sleeps for 3 seconds, letting the child process read the data*/Close (pipe_fd[1]); Sleep (3); /*Collect child process exit information*/waitpid (Pid,null,0); Exit (0); }}
The results of the operation are as follows:
[Email protected] ipc]#./PIPE_RW
Parent Write1 success! Parent Write2 success! Ten from is Hello Pipe
2. Named pipes (named pipe)
Because of the fork mechanism, pipelines can only be used between parent and child processes, or between two child processes that have the same ancestor (between processes that are related to each other). To solve this problem, Linux provides a FIFO way to connect the process. FIFO is also called named pipe (named pipe).
FIFO (first in, first out) is a special type of file that has a corresponding path in the file system. When a process opens the file in a read (R) manner and another process opens the file in a write (w), the kernel creates a pipeline between the two processes, so the FIFO is actually managed by the kernel and does not deal with the hard disk. The FIFO is called because the pipeline is essentially a FIFO queue data structure, the first to be put into the first read out, thus guaranteeing the order of information exchange. FIFO just borrows the file system, named pipe is a special type of file, because everything in Linux is a file, and it exists as a file name in the filesystem. ) to name the pipeline. The write-mode process writes to the FIFO file, while the read-mode process is read from the FIFO file. When the FIFO file is deleted, the pipe connection disappears as well. The advantage of FIFO is that we can identify the pipeline through the path of the file, so that there is no affinity between the processes to establish a connection
Function Prototypes:
#include <sys/types.h><sys/stat.h>int mkfifo (constChar * FileName, mode_t mode); int mknode (constchar0 );
Where pathname is the name of the file being created,mode indicates the permission bit to be set on the file and the type of file that will be created (in this case , S_ififo). Dev is a value that is used when creating a special file for a device. Therefore, for FIFO files it has a value of 0.
FIFO read-write rules
1. Read data from FIFO: contract: If a process blocks open FIFO in order to read data from the FIFO, then the read operation in the process is called a read operation with the blocking flag set
2. Writing data from FIFO: convention: If a process blocks the open FIFO in order to write data to the FIFO, then the write operation in the process is called a write operation that sets the blocking flag.
Once the FIFO is created, it can be opened to open, you can use Open,read,close and so on to operate the FIFO when the FIFO is opened, the non-blocking flag (O_nonblock) will have the following effect on read and write:
1. O_nonblock is not used: The process will block when access requirements are not met. Attempts to read an empty FIFO will cause the process to block;
2, use O_nonblock: Access requirements can not be met without blocking, immediately error return, errno is Enxio;
/*fifo_write.c*/#include<sys/types.h>#include<sys/stat.h>#include<errno.h>#include<fcntl.h>#include<stdio.h>#include<stdlib.h>#include<string.h>#defineFifo_server "/tmp/myfifo"Main (intargcChar**argv) { intFD; Charw_buf[ -]; intNwrite; if(fd==-1) if(errno==Enxio) printf ("open error; no reading process\n"); /*Open a named pipe and set it to non-blocking*/FD=open (fifo_server,o_wronly| O_nonblock,0); if(argc==1) printf ("Please send something\n"); strcpy (w_buf,argv[1]); /*writing strings to pipelines*/ if(Nwrite=write (Fd,w_buf, -))==-1) { if(errno==eagain) printf ("The FIFO has not been read yet. Please try later\n"); } Elseprintf ("Write%s to the fifo\n", w_buf);}/*FIFO_READ.C*/#include<sys/types.h>#include<sys/stat.h>#include<errno.h>#include<fcntl.h>#include<stdio.h>#include<stdlib.h>#include<string.h>#defineFIFO "/tmp/myfifo"Main (intargcChar**argv) { Charbuf_r[ -]; intFD; intnread; /*Create a named pipe and set the appropriate permissions*/ if((Mkfifo (fifo,o_creat| O_EXCL) <0) && (errno!=eexist)) printf ("Cannot create fifoserver\n"); printf ("Preparing for reading bytes...\n"); memset (Buf_r,0,sizeof(Buf_r)); /*Open a named pipe and set the non-blocking flag*/FD=open (fifo,o_rdonly| O_nonblock,0); if(fd==-1) {perror ("Open"); Exit (1); } while(1) {memset (Buf_r,0,sizeof(Buf_r)); /*reading a string in a pipeline*/ if(Nread=read (Fd,buf_r, -))==-1){ if(errno==eagain) printf ("No data yet\n"); } printf ("read%s from fifo\n", Buf_r); Sleep (1); } pause (); Unlink (FIFO); //This who Mkfifo Create who releases
}
Operation Result:
Terminal 1:
123123 123123 to the FIFO
Terminal 2:
[Email protected] ipc]#. /For reading Bytes...read from fiforead from fiforead to fiforead from fiforead from 123123 from fiforead to FIFO
Summarize:
1.read no data read blocking, data is deleted after read reading
2. The order of the data is ordered and the installation is written
3. Open descriptor can read and write (two-way)
4. The data is not persisted after the pipeline file is closed
5. Pipeline data is buffered in the kernel
6. The name of the famous pipe is only the kernel to identify whether to put back the same FD identity
Linux inter-process communication pipeline (pipe), (FIFO)