Communication between processes
Each process has a different user address space, the global variables of any one process can not be seen in another process, so the exchange between the data must pass through the kernel, a buffer in the kernel, process 1 to copy data from the user space to the kernel buffer, process 2 and then read the data from the kernel buffer, This mechanism provided by the kernel is called interprocess communication (IPC)
Inter-process communication
1.pipe Pipe
Can be implemented in a ring queue. If the queue is full, it will block. Piping is the most basic IPC mechanism, created by the pipe function
#include <unistd.h>int pipe (int filedes[2]);
A pipe acts on a blood-related process, passing by fork.
After calling the pipe, the parent process creates the pipe, fd[1] pipe write end, fd[0] pipe read end, are the file descriptor, descriptor allocation is not the smallest unit used, if the smallest unused file descriptor is 3, then 3 records the read end of the pipeline, 4 records the end of the pipeline, the overall reading of the file descriptor is small, The write-side file descriptor is large. The parent process fork out the child process, the left side of the parent process, and the child process on the right. The child process processes the parent process's file description table, 3 still points to the read end of the pipeline, and 4 points to the write end. After the pipeline is created, to determine the direction of communication, there are two choices of parent write sub-read (Turn off parent read, close sub-write) and sub-write parent read (turn off sub-read, turn off parent write), which is simplex work. If you need two-way communication, you need to create a pipeline, still create the pipe first, then fork.
#include <stdio.h>#include<string.h>#include<unistd.h>#include<stdlib.h>#include<fcntl.h>#include<errno.h>intMainvoid){ intfd[2]; Charstr[1024x768] ="Hello Itcast"; Charbuf[1024x768]; pid_t pid; //fd[0] Read End//Fd[1] Write end if(Pipe (FD) <0) {perror ("Pipe"); Exit (1); } PID=Fork (); //Parent Write sub-read if(PID >0) { //parent process, close parent ReadClose (fd[0]); Sleep (5); Write (fd[1], str, strlen (str)); Close (fd[1]); Wait (NULL); } Else if(PID = =0) { intLen, flags; //Sub-process, close sub-writeClose (fd[1]); Flags= Fcntl (fd[0], F_GETFL); Flags|=O_nonblock; Fcntl (fd[0], F_SETFL, flags); Tryagain:len= Read (fd[0], buf,sizeof(BUF)); if(len = =-1) { if(errno = =Eagain) {Write (Stdout_fileno,"try again\n",Ten); Sleep (1); GotoTryagain; } Else{perror ("Read"); Exit (1); }} write (Stdout_fileno, buf, Len); Close (fd[0]); } Else{perror ("Fork"); Exit (1); } return 0;}
Operation Result:
There are 4 special cases that you need to be aware of in the pipeline (assuming all blocking I/O operations and not setting the O_NONBLOCK flag):
(1) If all the file descriptors pointing to the end of the pipe are closed (the reference count for the pipe write is equal to 0), and the process still reads the data from the read end of the pipeline, then read the remaining data in the pipeline, and read again returns 0, just like the end of the file.
(2) If there is a file descriptor pointing to the end of the pipe is not closed (the reference count of the pipe write end is greater than 0), and the process that holds the end of the pipeline does not write data to the pipeline, then there is a process reading the data from the pipe, then the remaining data in the pipeline is read, again read will block, The data is read and returned until the data in the pipeline is readable.
(3) If all the file descriptors pointing to the pipe read end are closed (the reference count of the pipe reads equals 0), then there is a process to write to the pipeline, then the process receives a signal sigpipe, which usually causes the process to terminate abnormally
(4) If the file descriptor pointing to the pipe read end is not closed (the reference count of the pipe read is greater than 0), and the process that holds the pipe read does not read the data from the pipe, then there is a process to write the data to the pipeline, then write again when the pipeline is full and then block until there is a blank position in the pipeline
In short: Write off, read the contents of the pipeline reading, read again, return 0, equivalent to read EOF, the writing end is not closed, the writing end of the data is temporarily read, read the pipeline in the information, read again will block; Read end, write end write pipeline, generate sigpipe signal, write process by default will terminate the process Read the end of the pipeline data, when the writing end is full of pipelines, write again, blocking.
These four special cases of pipelines have universal significance.
Non-blocking pipeline, Fcntl function set O_nonblock flag
fpathconf (int fd,int name) tests the pipe buffer size, _pc_pipe_buf.
2.fifo Famous Pipe
Create a well-known pipeline to resolve the unrelated process communication, FIFO:
FIFO is an index node that does not leave any size under the disk, so no myfifo size is 0;
Write pipeline
#include <stdio.h>#include<unistd.h>#include<stdlib.h>#include<sys/types.h>#include<fcntl.h>#include<sys/stat.h>#include<string.h>voidSys_err (Char*STR,intExitno) {perror (str); Exit (Exitno);}intMainintargcChar*argv[]) { intFD; Charbuf[1024x768] ="Hello xwp\n"; if(ARGC <2) {printf ("./a.out fifoname\n"); Exit (1); } //fd = open (argv[1], o_rdonly);FD = open (argv[1], o_wronly); if(FD <0) Sys_err ("Open",1); Write (FD, buf, strlen (BUF)); Close (FD); return 0;}
//Read Pipeline#include <stdio.h>#include<unistd.h>#include<stdlib.h>#include<sys/types.h>#include<fcntl.h>#include<sys/stat.h>#include<string.h>voidSys_err (Char*STR,intExitno) {perror (str); Exit (Exitno);}intMainintargcChar*argv[]) { intFD, Len; Charbuf[1024x768]; if(ARGC <2) {printf ("./a.out fifoname\n"); Exit (1); } FD= Open (argv[1], o_rdonly); if(FD <0) Sys_err ("Open",1); Len= Read (FD, BUF,sizeof(BUF)); Write (Stdout_fileno, buf, Len); Close (FD); return 0;}
GCC Fifo_w.c-o fifo_w
GCC Fifo_r.c-o fifo_r
./fifo_w Myfifo
./fifo_r Myfifo
function form, used in programming
#include <sys/types.h>#include<sys/stat.h>int mkfifo (constChar * pathname,mode_t mode);
3. Memory Sharing mapping
Mmap/munmap
Mmap can map a portion of a disk file directly to memory, so that the location of the file directly corresponds to the memory address, read and write to the file can be directly with the pointer without the need for the Read/write function.
Mmap
#include <sys/mman.h>
void *mmap (void *addr,size_t length,int prot,int flags,int fd,off_t offsize);
Specific parameter meaning
Addr: Points to the starting address of the memory to be mapped, usually set to NULL, which means that the system automatically selects the address, which is returned when the mapping succeeds.
Length: Represents how much part of the file is mapped to memory.
Prot: How the map area (memory) is protected. Can be combined in several ways:
Prot_exec map area can be executed
Prot_read map area can be read
Prot_write mapped area can be written
Prot_none map area cannot be accessed
Flags: Affects the various features of the mapped area. You must specify map_shared or map_private when calling Mmap ().
Map_fixed if the address that the parameter start refers to cannot successfully establish the mapping, discard the mapping and do not fix the address. This flag is generally discouraged.
Map_shared writes data to a mapped region is copied back into the file, and other processes that map the file are allowed to be shared.
Map_private writes to a mapped region will result in a copy of the mapping file, which means that any changes made to this area by the private copy on write will not be written back to the original file contents.
map_anonymous establish an anonymous mapping. The parameter FD is ignored, the file is not involved, and the mapped area cannot be shared with other processes.
Map_denywrite only allows write operations to the mapped region, and other operations that write directly to the file will be rejected.
map_locked locks the mapped area, which means that the region will not be displaced (swap).
FD: The file descriptor to map to memory. If anonymous memory mapping is used, MAP_ANONYMOUS,FD is set to-1 in flags. Some systems do not support anonymous memory mappings, you can use fopen to open the/dev/zero file.
The file can then be mapped to the same effect as an anonymous memory map.
Offset: File-mapped offsets, typically set to 0, represent the page_size from the front of the file, and offset must be an integer multiple of the size of the page.
return value:
If the mapping succeeds, it returns the memory start address of the mapping area, otherwise map_failed (-1) is returned, and the reason for the error is stored in errno.
Error code:
EBADF parameter FD is not a valid file description word
Eacces access rights are incorrect. If the file must be readable in the case of map_private, use map_shared to have prot_write and the file to be writable.
EINVAL parameter start, length, or offset has an illegal.
The Eagain file is locked, or too much memory is locked.
ENOMEM Insufficient memory.
The user layer of the call is very simple, its specific function is directly mapped to the physical memory directly to the user virtual memory, so that user space can be directly to the physical space operation. But for the kernel layer, its concrete implementation is more complicated.
#include <stdio.h>#include<unistd.h>#include<sys/stat.h>#include<sys/types.h>#include<fcntl.h>#include<sys/mman.h>#include<stdlib.h>intMainvoid){ intFD, Len; int*p; FD= Open ("Hello", O_RDWR); if(FD <0) {perror ("Open"); Exit (1); } Len= Lseek (FD,0, Seek_end); P= Mmap (NULL, Len, prot_read| Prot_write, map_shared, FD,0); if(p = =map_failed) {Perror ("mmap"); Exit (1); } close (FD);
The mapping has not been lifted
p[00x30313233return0;}
When you modify a disk file, the corresponding mapped memory also changes.
The realization principle of mmap
The process of learning Linux (iii)