Primary directory
Secondary directory
Tertiary directory
1. Pipeline
1. Anonymous pipeline
Anonymous pipes communicate with blood related processes
Anonymous pipeline communication steps:
1. A process opens the same file in read-write mode respectively, so there are two file descriptors, one pointing to the file in read mode and the other pointing to the file in write mode
2. The parent process fork creates a child process. Because the child process is created with the parent process as the template, the file of the child process_ FD of struct_ Array is the same as the parent process
3. Let the parent process read and the child process write, then close the write performed by the parent process and keep the read of the parent process open; Close the read of the subprocess and keep the write of the subprocess open
Test 1
1 #include <stdio.h> 2 #include <unistd.h> 3 4 int main() { 5 int pipe_fd[2] = {0}; 6 if (pipe(pipe_fd) < 0) { 7 perror("pipe"); 8 return 1; 9 } 10 printf("%d %d\n", pipe_fd[0], pipe_fd[1]); 11 return 0; 12 } ~
Test 2
1 #include <stdio.h> 2 #include <unistd.h> 3 #include <string.h> 4 #include <sys/types.h> 5 #include <sys/stat.h> 6 #include <stdlib.h> 7 8 9 int main() { 10 int pipe_fd[2] = {0}; 11 if (pipe(pipe_fd) < 0) { 12 perror("pipe"); 13 return 1; 14 } 15 printf("%d %d\n", pipe_fd[0], pipe_fd[1]); 16 pid_t id = fork(); 17 if (id < 0) { 18 perror("fork"); 19 } 20 if (id == 0) { //write 21 //child 22 close(pipe_fd[0]); W> 23 char *msg = "hello world, i am child process"; 24 int count = 5; 25 while (count) { 26 write(pipe_fd[1], msg, strlen(msg)); 27 sleep(1); 28 count--; 29 } 30 close(pipe_fd[1]); 31 exit(0); 32 }else { // read 33 //parent 34 close(pipe_fd[1]); 35 ssize_t size = 0; 36 char buf[64] = {0}; 37 while(1) { 38 size = read(pipe_fd[0], buf, sizeof(buf)-1); 39 if (size > 0) { 40 buf[size] = 0; 41 printf("parent get message from child#: %s\n", buf); 42 } else if (size == 0) { 43 printf("pipe file close, child quit!\n"); 44 break; 45 } 46 } 47 close(pipe_fd[0]); 48 int status = 0; 49 pid_t ret = waitpid(id, &status, 0); 50 if (ret == -1) { 51 perror("waitpid"); 52 return 1; 53 } 54 printf("child is waited, the exit code is %d\n", WEXITSTATUS(status)); 55 } 56 return 0; 57 }
Test 3: what happens to the write side when the read side does not read and the read side is turned off?
The system directly kill s the writer, because no one reads, writing is useless work, and the system does not allow any useless work
#include <stdio.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <stdlib.h> int main() { int pipe_fd[2] = {0}; if (pipe(pipe_fd) < 0) { perror("pipe"); return 1; } printf("%d %d\n", pipe_fd[0], pipe_fd[1]); pid_t id = fork(); if (id < 0) { perror("fork"); } if (id == 0) { //write //child close(pipe_fd[0]); char *msg = "hello world, i am child process"; int count = 5; while (count) { write(pipe_fd[1], msg, strlen(msg)); sleep(1); count--; } close(pipe_fd[1]); exit(0); }else { // read //parent close(pipe_fd[1]); ssize_t size = 0; char buf[64] = {0}; while(1) { size = read(pipe_fd[0], buf, sizeof(buf)-1); if (size > 0) { buf[size] = 0; printf("parent get message from child#: %s\n", buf); } else if (size == 0) { printf("pipe file close, child quit!\n"); break; }else{ break; } close(pipe_fd[0]); } //close(pipe_fd[0]); int status = 0; pid_t ret = waitpid(id, &status, 0); if (ret == -1) { perror("waitpid"); return 1; } printf("child is waited, the sig code is %d, the exit code is %d\n", (status & 0x7F), WEXITSTATUS(status)); } return 0; }
The life cycle of the pipeline follows the life cycle of the process, because if a process is closed, the files opened by the process will also be closed
2. Named pipes
Used for communication between two processes that are not related by blood
mkfifo: command for creating a named pipe. mkfifo filename can only create a named pipe file named filename on the command line.
However, when writing data to filename, our data will not be written to the disk, but will be written to the buffer of struct file structure. (ordinary files need to be refreshed to disk for persistent storage)
Test 1: after creating the named pipe file of myfifo
In bash1:
while :; do echo "hello world"; sleep 1; done > myfifo
In bash2:
cat < myfifo
You can see that "hello world" is printed in bash2
Test 2: code level named pipeline communication
int mkfifo(const char *filename, mode_t mode)
0 is returned for success and - 1 is returned for failure
Create a servre and a client. The client sends messages and the server receives messages
//server.c 1 #include "stdio.h" 2 #include <unistd.h> 3 #include <string.h> 4 #include <stdlib.h> 5 #include <sys/types.h> 6 #include <sys/stat.h> 7 #include <fcntl.h> 8 9 #define FIFO "./fifo" 10 11 int main() { 12 int ret = mkfifo(FIFO, 0644); 13 if (ret < 0) { 14 perror("mkfifo"); 15 } 16 int fd = open(FIFO, O_RDONLY); 17 if (fd < 0) { 18 perror("open"); 19 return 1; 20 } 21 22 char buf[64] = {0}; 23 24 while (1) { 25 ssize_t s = read(fd, buf, sizeof(buf)-1); 26 if (s > 0) { 27 buf[s] = 0; 28 printf("parent get message from client#: %s", buf); 29 }else if(s == 0) { 30 printf("client quit\n"); 31 break; 32 }else { 33 break; 34 } 35 } 36 close(fd); 37 return 0; 38 }
//client.c 1 #include "stdio.h" 2 #include <unistd.h> 3 #include <string.h> 4 #include <stdlib.h> 5 #include <sys/types.h> 6 #include <sys/stat.h> 7 #include <fcntl.h> 8 9 #define FIFO "./fifo" 10 11 int main() { 12 int fd = open(FIFO, O_WRONLY); 13 if (fd < 0) { 14 perror("open"); 15 return 1; 16 } 17 18 char buf[128]; 19 20 while (1) { 21 printf("please enter# "); 22 fflush(stdout); 23 buf[0] = 0; 24 ssize_t s = read(0, buf, sizeof(buf)-1); 25 if (s > 0) { 26 buf[s] = 0; 27 write(fd, buf, strlen(buf)); 28 }else if(s == 0) { 29 break; 30 }else { 31 break; 32 } 33 } 34 close(fd); 35 return 0; 36 }
2. Shared memory
There is no need for read/write interfaces, because they have been mapped to memory
Shared memory: a space applied in physical memory. The OS maps it to their virtual memory through the page tables of two processes (both processes see the same resource), and then returns the address to the user, so that communication can be carried out through this space.
The system will manage all shared memory: first describe and then organize
1. Create shared memory (man shmget)
shmflg can also be followed by permission: 0644, which is separated by |
grep -ER ‘IPC_CREAT '/ usr/include /: View IPC_CREAT
You can see that it is defined in VIM / usr / include / bits / IPC H medium
2. Get the unique key (man get)
As long as the ftok parameters of the two processes are filled in the same, the returned value key obtained is also the same, which can indicate the same shared memory (there is a key field identifying itself in the struct managing shared memory)
3. Delete shared memory (man shmctl)
In * ctl, you can view the structure describing its corresponding resources (shared memory / message queue / semaphore)
The first parameter is the shared memory identification code, and the second parameter is set to IPC_RMID means to delete the shared memory, and the last one is temporarily set to NULL
4. Associate process to shared memory / disassociate shared memory (man shmat)
The second and third parameters are temporarily set to NULL and 0
// Used to continuously view shared memory information while :; do ipcs -m | head -3 && ipcs -m | grep "xupeng";echo "###########"; sleep 1; done
5. Get the contents of shared memory
(because the address of the virtual memory has been obtained through shmat, it can be printed directly like the contents of the buffer, that is, the array)
6. Write content to shared memory
Shared memory life cycle varies with OS
Shared memory does not provide any synchronization and mutual exclusion and is independent of each other
Shared memory communication is the fastest; There is no operation to copy to the file, and there is no conversion from user state to kernel state
shim is the concept of user layer operation
key is the uniqueness of the system representation
grep -ER ‘struct ipc_perm '/ usr/include /: find ipc_perm
3. Message queue
1. Get message queue (man msgget)
The parameters are the same as shmget
2. Delete message queue (man msgctl)
The prefix of the signal is sem, semget/semctl
The type in the structure when sending a message. You can specify two processes to communicate. Only those with the same sending type and receiving type can communicate (type=0 means that any process can receive the message).
//client.c #include "stdio.h" #include "string.h" #include "stdlib.h" #include "unistd.h" #include "fcntl.h" #include "sys/ipc.h" #include "sys/msg.h" #define SIZE 100 struct Buf{ long type; char text[SIZE]; }; int main() { key_t key = ftok("/home/xupeng", 10); if (key < 0) { perror("ftok"); return 2; } int msgid = msgget(key, IPC_CREAT | 0644); if (msgid < 0) { perror("msgid"); return 2; } struct Buf bf; bzero(&bf, sizeof(bf)); bf.type = 1; bf.text[0] = 0; strcpy(bf.text, "hello world"); msgsnd(msgid, &bf, strlen(bf.text), 1); return 0; }
//server.c #include "stdio.h" #include "string.h" #include "stdlib.h" #include "unistd.h" #include "fcntl.h" #include "sys/ipc.h" #include "sys/msg.h" #define SIZE 100 struct Buf{ long type; char text[SIZE]; }; int main() { key_t key = ftok("/home/xupeng", 10); if (key < 0) { perror("ftok"); return 2; } int msgid = msgget(key, IPC_CREAT); if (msgid < 0) { perror("msgid"); return 2; } struct Buf bf; size_t size = msgrcv(msgid, &bf, SIZE, 1, 0); printf("msgrcv return : %d", size); bf.text[size] = 0; printf("i get meg from client : %s\n", bf.text); return 0; }