1. The inter-process communication Overview
(1 Overview
① Data transfer: a process needs to transmit its data to another process, an amount of data transmitted in bytes to several megabytes.
② share data: operating multiple processes want to share data, a process to modify the shared data, other process should be seen immediately.
③ notification events: a process needs to send a message to another (group) process, notifying them of the occurrence of a certain event (to be notified when the parent process as the process is terminated).
④ resource sharing: sharing the same resources among multiple processes. To do this, we need to provide the kernel lock and synchronization mechanisms.
⑤ Process Control: Some want to completely control the process of execution of another process (such as Degub process), and the control will process all want to be able to intercept and exceptions into another process, and be able to timely know its status changed.
(2) the process of modern means of communication
① conduit (pipe) and naming management (FIFO) ② signal (signal) ③ ④ message queue shared memory semaphore ⑤ ⑥ socket (Socket)
2. The pipe communication
2.1 Overview
(1) is a conduit for the local computer communication method for communication between two processes designed, created a pipeline, is actually obtained , both file descriptors : one for reading and one for writing .
(2) The most common IPC mechanism, by calling pipe system
(3) pipes are simplex , data can only flow in one direction , two-way communication when required, need to establish two pipes.
Reading and writing (4) data: a process to write the contents of the pipeline process is read out of the other end of the pipe. Written content every time the buffer added to the end of the pipe , and each time from the head of the read data buffer (i.e., should be consistent with a sequential write of sequentially read !)
2.2 pipes classification and write
Category (1) pipeline
① anonymous pipes:
A. In relation process process (between parent and child, brother process)
B. a call pipe systems , pipelines built by the parent process
C. pipes in the kernel space, in fact, a cache
② named pipe (FIFO):
A. two without any relationship between the processes of the communication for data transfer via a named pipe, the kernel is essentially a cache, the other in the file system is present in a particular design file (pipe file) .
B. By calling mkfifo system created.
(2) pipeline to create:
head File |
#include <unistd.h> |
function |
int pipe(int fd[2]); |
Features |
Waiting for one or more designated signal generating |
return value |
Successful return 0, otherwise -1 |
Remark |
①fd [0]: is the read end of the pipe, the pipe for reading. ②fd [1]: a write pipe end, the pipe for writing. |
Write (2) of the pipe
① pipeline is mainly used for communication between different processes. In fact, usually the first to create a pipeline, and then creates another child process by fork function .
② Note simplex pipe, so to turn off some of the parent and child fd therein (shown above). If you need two-way communication, you need to create two pipes.
[Programming] experiment written parent, the child process reads
//cal_pipe.c
View Code
[Programming] simulation experiment Pipe command
① a child process execution command, the command execution result into the pipeline
② another sub-process reads the results of command execution from the pipe, and then filtered (grep) keyword
③ analysis command: cat / etc / passwd | grep root. When this command is executed, in fact, there are three processes: the child process parent shell, cat child process and execution of grep! This simulation scenario in this case is the same, the execution result into the pipeline by the child's cat, grep child process reads out from the pipe!
//cmd_pipe.c
#include <unistd.h> #include <stdio.h> #include <stdlib.h> char* cmd1[3] = {"/bin/cat", "/etc/passwd", NULL}; char* cmd2[3] = {"/bin/grep", "root", NULL}; // char * cmd2 [3] = { "wc", "-l", NULL}; // count the number of users int main(void) { you fd [2] if(pipe(fd) < 0){ perror("pipe error"); exit(1); } int i = 0; pid_t pid; // create a process fan: a parent process and sub-process 2 for(; i<2; i++){ pid = fork(); if(pid < 0){ perror("fork error"); exit(1); }else if(pid == 0){ //child process if (i == 0) {// first sub-process responsible for writing data to the pipeline close (fd [0]); // Close the read end // Note that the default output is a standard cat command output (screen), and therefore need to redirect output to the write end of the pipe // The standard output is redirected to the write end of the pipe, cat execution results are written to the pipeline if (dup2 (fd [1], STDOUT_FILENO)! = STDOUT_FILENO) {// the fd [1] as a weight to the standard output perror("dup2 error"); } close (fd [1]); // hexyl standard output is redirected to a write pipe end, fd [1] may be closed // call the exec function executes the cat command if (execvp (cmd1 [0], cmd1) <0) {// v array, p absolute or relative path perror("execvp error"); exit(1); } } if (i == 1) {// the second sub-process is responsible for reading data from the pipeline close (fd [1]); // Close the write end // redirects standard input to the read end of the pipe, so that grep read from the conduit rather than from the standard input if(dup2(fd[0], STDIN_FILENO) != STDIN_FILENO){ perror("dup2 error"); } close (fd [0]); // standard input hexyl redirected to the read end of the pipe, fd [0] can be closed // call the exec function to execute grep command if(execvp(cmd2[0], cmd2) < 0){ perror("execvp error"); exit(1); } } break; }else{ //parent process if (i == 1) {// Create a sub-process to be completed, step 2 // parent process to wait until the child process is completed before going to create all recovery close(fd[0]); close(fd[1]); wait (0); // recovered two sub-processes wait(0); } } } if(pid = fork() < 0){ } return 0; } / * Output: root:x:0:0:root:/root:/bin/bash operator:x:11:0:operator:/root:/sbin/nologin */
[Experimental] collaborative programming process (two two-way communication process through two pipes)
① parent x and y to write the first one pipeline.
② sub-process reads x and y from a pipeline. And calls add is added.
③ The child process writes the result to the second conduit.
④ parent process reads the calculation result from the second conduit, and outputs.
//add.c ==> to be compiled into a single executable file add.o
#include <unistd.h> #include <stdio.h> #include <stdlib.h> int main(int argc, char* argv[]) { int x = 0, y = 0; if(read(STDIN_FILENO, &x, sizeof(int)) < 0){ perror("read error"); } if(read(STDIN_FILENO, &y, sizeof(int)) < 0){ perror("read error"); } int result = x + y; if(write(STDOUT_FILENO, &result, sizeof(int)) != sizeof(int)){ perror("write error"); } return 0; }
//co_process.c ==> compiled into an executable file
#include <unistd.h> #include <stdio.h> #include <stdlib.h> int main(void) { int fda[2], fdb[2]; // Create two pipes in order to achieve duplex operation if( (pipe(fda) < 0) || (pipe(fdb) <0) ){ perror("pipe error"); exit(1); } pid_t pid; pid = fork(); if(pid < 0){ }else if(pid == 0){//child process /* * (1) the parent child process is responsible for reading the writing from a pipe parameters x and y * (2) to call bin / add are accumulated by the program exec function * (3) The accumulated results are written to the pipe b. */ close (fda [1]); // can only be read from a pipe close (fdb [0]); // b can be written to the pipe // redirected to the standard input of the read end of a pipe, then // (add a program read from the pipe end of the accumulated read parameters x and y) if(dup2(fda[0], STDIN_FILENO) != STDIN_FILENO){ perror("dup2 error"); } // write the standard output to the end of the pipe b, the // (accumulated result of the program is written to add in the duct b) if(dup2(fdb[1], STDOUT_FILENO) != STDOUT_FILENO){ perror("dup2 error"); } close (fda [0]); // redirection is complete, it can be closed close(fdb[1]); if(execlp("bin/add", "bin/add", NULL) < 0){ perror("execlp error"); exit(1); } }else{ //parent process /* * (1) x and y parameters read from stdin * (2) x and y write a conduit * (3) is read from the pipe b, and outputs the accumulated result */ close(fda[0]); close(fdb[1]); int x, y; // (1) read the parameters x and y accumulated printf("please input x and y: "); scanf("%d %d", &x, &y); @ (2) the x and y write a conduit if(write(fda[1], &x, sizeof(int)) != sizeof(int)){ perror("write error"); } if(write(fda[1], &y, sizeof(int)) != sizeof(int)){ perror("write error"); } @ (3) from the pipe b, the reading result (note that block the pipeline when no data!) int result; if(read(fdb[0], &result, sizeof(int)) < 0){ perror("read error"); }else{ printf("add result is %d\n", result); } close(fda[1]); close(fdb[0]); wait(0); } return 0; }
2.3 Characteristics of the pipe
(1) to create a two-way pipe by opening the two pipes
(2) pipes are obstructive when the process data is read from the pipe, the process will be blocked if there is no data.
(3) When a process constantly write data to the pipeline, but there is no process to read data, when this time as long as the pipe is not full of it, but if the pipeline will be filled with data error.
(4) incomplete pipeline
① When reading a write terminal already closed when the pipe after all of the data is read, read return 0 to indicate the end of the file reaches.
② If writing a terminal has been read off of the pipe, the generation SIGPIPE signal , if the signal is ignored or capture the signal and returns to the processing program , the write returns -1 , errno is set while EPIPE.
[Experiment] read a write programming has closed end conduit
//broken_pipe_r.c
#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> /* * Incomplete pipe: reading a write pipe end has closed */ int main () { you fd [2] if(pipe(fd) < 0){ perror("pipe error"); exit(1); } pid_t pid; if((pid = fork()) < 0){ perror("fork error"); exit(1); }else if (pid > 0){ //parent process Never complete pipeline // parent process read data close(fd[1]); sleep (5); // wait for the child to write end of the pipe is closed while(1){ char c; if(read(fd[0], &c, 1) == 0){ printf("\nwrite-end of pipe closed.\n"); break; }else{ printf("%c", c); } } close(fd[0]); wait(0); }else{ //child process // child process negative writes the data pipeline close(fd[0]); char* s = "12345"; write(fd[1], s, strlen(s)*sizeof(char)); // shut down the pipeline after writing data write end -> becomes incomplete // pipeline, but be sure to read the pipe before the pipe in the parent write end is closed! close(fd[1]); } return 0; } / * Output 12345 write-end of pipe closed. */
[Experiment] Programming a read-write terminal already closed conduit
//broken_pipe_w.c
#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <signal.h> #include <errno.h> /* * Incomplete pipeline: the end of the pipeline had been shut down to write a read */ // signal handler void sig_handler (int signo) { if(signo == SIGPIPE){ printf("SIGPIEP occured\n"); } } int main(void) { // Register signal processing function if (signal (SIGPIPE, sig_handler) == SIG_ERR) { perror("signal sigpipe error"); exit(1); } you fd [2] if(pipe(fd) < 0){ perror("pipe error"); exit(1); } pid_t pid; if((pid = fork()) < 0){ perror("fork error"); exit(1); }else if(pid > 0){ //parent process // parent process registration signal processing function if (signal (SIGPIPE, sig_handler) == SIG_ERR) { perror("signal sigpipe error"); exit(1); } // The parent process is responsible for writing data to the incomplete pipeline (read end closed) in sleep (5); // let the child process to run, in order to ensure that the read end closed close(fd[0]); char* s = "12345"; int len = strlen(s) * sizeof(char); if(write(fd[1], s, len ) != len){ fprintf(stderr, "%s, %s\n", strerror(errno), (errno == EPIPE) ? "EPIPE": ", unknow"); } close(fd[1]); wait(0); }else{ //child process close(fd[0]); close(fd[1]); } return 0; } / * Output: SIGPIEP occured Broken pipe, EPIPE */
2.4 Pipelining standard library
head File |
#include <stdio.h> |
function |
FILE* popen(const char* cmdstring, const char* type); |
parameter |
cmdstring : command-line parameters to be executed. type:r或w。 ① If type is r, is represented by the child exec (cmdstring), the result is written duct (sub-process will be internal standard output to the write end of the pipe), the parent process execution result read command from the pipe. ② If the type is w, it means that the parent process to write data to the pipe, the child process to read data from the pipe as the input command (internal standard input to the re-read to the end of the pipe). |
return value |
Successful return file pointer, NULL on error |
Features |
By creating a pipeline, calling fork () generates a child process, then execute the command cmdstring by the child. |
function |
int pclose(FILE* fp); |
return value |
cmdstring termination status, error -1 |
Features |
Close pipeline |
Remark |
① use popen () to create a pipeline must be used pclose () is closed. In fact, popen / pclose and standard file input / output streams fopen / fclose very similar. Common packaging operation ② conduit. |
[Experiment] programming library using standard read and write operations conduit
//popen_rw.c
#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <memory.h> / * File using the pipeline operator * / int main(void) { FILE* fp; // command execution result is placed in the cache structure pointed to by fp fp = popen("cat /etc/passwd", "r"); char buf[512]; memset(buf, 0, sizeof(buf)); while(fgets(buf, sizeof(buf), fp) != NULL){ printf("%s", buf); } pclose(fp); printf("-----------------------------------------\n"); // provide statistical data for the wc command fp = popen("wc -l", "w"); // write data to the cache fp points (since the type is "w", so that data is written to the pipeline) fprintf (fp, "line1 \ nline2 \ nline3 \ n"); // 3 provides data lines, as wc to statistical data sources! pclose(fp); return 0; }
2.5 Command pipe (FIFO)
(1) FIFO creation
head File |
#include <sys/types.h> #include <sys/stat.h> |
function |
int mkfifo(const char* pathname, mode_t mode); |
parameter |
Pipeline file name to be created: ①pathname ②mode: Permissions (mode% ~ umask) |
return value |
(1) return 0 if successful, -1 error (2) FIFO -related error messages ①EACCES (no access) ②EEXIST (specified file does not exist) ③ENAMETOOLONG (pathname too long) ④ENOENT (directory contains does not exist) ⑤ENOSPC (enough space left on the file system) (invalid file path) ⑥ENOTDIR ⑦EROFS (specified file exists in the read-only file system) |
Remark |
|
(2) Notes
① As long as there is adequate access to the FIFO, FIFO can be used in any process two have nothing to communicate.
② essentially a cache in the kernel , which is present in a special device file (pipe) file system .
③ in the file system is only one index block to store the file path, there is no data block , all the data stored in the kernel.
④ named pipe must be open simultaneously read or write , or read or write individual alone can cause obstruction .
⑤ command mkfifo create a named pipe (Command mkfifo internal call function)
⑥ operation is the same as ordinary files to the FIFO.
Once created mkfifo ⑦ has a FIFO used, it can be opened by Open, a general file I / O functions (close, read, write and unlink the like) can be used FIFO.
[Programming] literacy test pipe file
(1) Before running this example of two processes, you must first create a named pipe mkfifo file (such as s.pipe)
(2)不管先运行读还是写的进程。如果命名管道只被打开一端(读或写),则另一个进程会被阻塞。可以通过先运行读或写进程来观察进程被阻塞的现象。
//fifo_write.c ==>编译成单独的可执行文件
#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> /*向命名管道写入数据*/ int main(int argc, char* argv[]) { if(argc < 2){ printf("usage: %s fifo\n", argv[0]); exit(1); } printf("open fifo write...\n"); //打开命名管道 int fd = open(argv[1], O_WRONLY); if( fd < 0 ){ perror("open error"); exit(1); }else{ printf("open fifo success: %d\n", fd); } char* s = "1234567890"; size_t size = strlen(s); if(write(fd, s, size) != size){ perror("write error"); } close(fd); return 0; } /*输出结果: [root@localhost]# bin/fifo_write s.pipe //要先mkfifo s.pipe创建命名管道文件 open fifo write... open fifo success: 3 */
//fifo_read.c ==>编译成单独的可执行文件
#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <memory.h> /*从命名管道中读取数据*/ int main(int argc, char* argv[]) { if(argc < 2){ printf("usage: %s fifo\n", argv[0]); exit(1); } printf("open fifo read...\n"); //打开命名管道 int fd = open(argv[1], O_RDONLY); if(fd < 0){ perror("open error"); exit(1); }else{ printf("open file sucess: %d\n", fd); } //从命名管道中读取数据 char buf[512]; memset(buf, 0, sizeof(buf)); while(read(fd, buf, sizeof(buf)) < 0){ perror("read error"); } printf("%s\n", buf); close(fd); return 0; } / * Output: [root@localhost]# bin/fifo_read s.pipe open fifo read... open file sucess: 3 1234567890 */
2.6 write command pipeline and anonymous
(1) anonymous pipes and named pipes to read and write the same point
Same point |
Explanation |
Blocking characteristics |
The default is obstructive to read and write |
Telecommunication |
Apply to the network communication socket |
Incomplete obstruction pipeline |
① when read alone, after all the data is read, read returns 0, to indicate that reached the end of the file. ② When the simple write SIGPIPE signal is generated, if the signal is ignored or capture the signal and returns to the processing program, write returns -1 errno set EPIPE. |
Complete blockage pipeline |
① when read alone, either blocking or read data ② simply write, write to errors when the pipeline is full |
Non-blocking is not complete pipeline |
① direct error when reading simple ② When the simple write SIGPIPE signal is generated, if the signal is ignored or capture the signal and returns to the processing program, write returns -1 errno set EPIPE. |
Non-blocking full pipeline |
① when simply reading directly error. ② simple when written, is written to be wrong when the pipeline is full. |
(2) anonymous pipes and named pipes to read and write different
difference |
Explanation |
Open |
Open inconsistent |
Set blocking properties |
①pipe set O_NONBLOCK fcntl by non-blocking system call to read. ②FIFO call or open function is provided by a non-blocking system fcntl read. |
Original connection: https://www.cnblogs.com/5iedu/p/6579907.html