Linux process communication 1: Overview of process communication, principle of pipe communication (unnamed pipe, well-known pipe), actual pipe programming

Process communication overview, pipe communication principle (unnamed pipe, named pipe), pipe programming practice

1. Overview of inter-process communication:

Example 1:
Communication between your mobile phone WeChat and others' mobile phone WeChat
Example 2: For
example: the communication between wait and exit between parent and child processes

Inter-process communication (IPC) : Refers to the transmission or exchange of information between different processes

Inter-process communication (IPC) communication method:

IPC methods usually include pipes (including unnamed pipes and named pipes),
message queues,
semaphores,
shared storage,
sockets, streams, etc.,
among which sockets and streams support two processes IPC on different hosts

2. Principle of pipeline communication:

Pipe : usually refers toUnnamed pipe, Is the oldest form of IPC in UNIX system
Features:

Half-duplex (data can only flow in one direction), with fixed read and write ends can only be used for inter-process communication with kinship (father and son brothers),
it can be regarded as a file, for its read and write available read, Functions such as write,
but it is not an ordinary file, does not belong to any other file system, and only exists in memory

note: The data in the pipeline is gone after being read.

Pipe function prototype:

#include<unistd.h>
int pipe(int fd(2));//返回值:成功:0,失败:-1

When a pipeline is established, it creates two file descriptors:fd[0] is opened for reading, fd[1] is opened for writing. As shown below:

Insert picture description here
To close the pipe, just close these two file descriptors.

example:

Pipes in a single process are almost useless. Therefore, usually the process that calls pipe then calls fork, thus creating an IPC channel between the parent process and the child process. As shown below:

Insert picture description here
If the data flow flows from the parent process to the child process, close the reading end of the parent process (fd[0]) and the writing end of the child process (fd[1]); otherwise, you can make the data flow flow from the child process to the parent process .

Reference Code:

#include<stdio.h> 
#include<unistd.h>
int main() 
{
    
    
int fd[2]; // 两个文件描述符 
pid_t pid;
char buff[20]; 
if(pipe(fd) < 0) // 创建管道 
printf("Create Pipe Error!\n"); 
if((pid = fork()) < 0) // 创建子进程 
printf("Fork Error!\n"); 
else if(pid > 0) // 父进程 
{
    
     
close(fd[0]); // 关闭读端 
write(fd[1], "hello world\n", 12); 
} 
else 
{
    
     
close(fd[1]); // 关闭写端 
read(fd[0], buff, 20); 
printf("%s", buff); 
}  
return 0; 
}

operation result:

Insert picture description here

The read and write function prototypes included:

#include <unistd.h>
int pipe(int pipef d[2]);
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
ssize_t read(int fd, void *buf, size_t count);

3. Pipeline programming actual combat:

Reference Code:

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
//管道的原型:int pipe(int pipe fd[2]);
int main()
{
    
    
int fd[2];
int pid;//fork的返回值
char buf[128];
if(pipe(fd)==-1)
{
    
    
printf("创建管道失败\n");
}
pid=fork();//父进程会拷贝一个空间给子进程
if(pid<0)
{
    
    
printf("创建子进程失败\n");
}else if(pid>0)
{
    
    
sleep(3);//父进程睡3秒,保证子进程先运行,,子进程会阻塞
printf("进入了父进程id:%d\n",getpid());
close(fd[0]);//关掉父进程的管道读操作
write(fd[1],"hello from father",strlen("hello from father"));
wait(NULL);//不让父进程直接结束,子进程成孤儿
}else
{
    
    
printf("进入了子进程id:%d\n",getpid());
close(fd[1]);//关掉父进程的管道写操作
read(fd[0],buf,128);//读到buf里面,读wei字节
printf("read:%s\n",buf);
exit(0);
}
return 0;
}

Code: To achieve the communication between the child process and the parent process.

operation result:

Insert picture description here
4. Named pipe:

FIFO : Also known as named pipe, it is a file type

Features:

FIFO can exchange data between unrelated processes, unlike an anonymous pipe.
FIFO has a path name associated with it, and it exists in the file system in the form of a special device file

fifo function prototype:

#include <sys/types.h>  
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);//创建
// 返回值:成功返回0,出错返回-1  
//其中的 mode 参数与open函数中的 mode 相同。一旦创建了一个 FIFO,就可以用一般的文件I/O函数操作它。
//如果命名管道文件已经存在,则会创建失败

Demo code:

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <errno.h>
//int mkfifo(const char *pathname, mode_t mode);
int main()
{
    
    
int ret=mkfifo("./file",0600);//创建命名管道(文件),0600:可读可写的方式
if(ret==0)
{
    
    
printf("创建成功\n");
}
if(ret==-1)
{
    
    
printf("创建失败\n");
perror("why");//打印失败原因
}
}

operation result:
Insert picture description here

note:
If the file exists, the creation fails, indicating that it is not perfect

Modify the demo code as follows:

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <errno.h>
//int mkfifo(const char *pathname, mode_t mode);
int main()
{
    
    
if((mkfifo("./file",0600)==-1)&&errno!=EEXIST)//同时满足错误吗:文件已存在
{
    
    
printf("创建失败\n");
perror("why");
}else
{
    
    
if(errno==EEXIST)
{
    
    
printf("文件有啦\n");
}else
{
    
    
printf("创建成功\n");
}
}
return 0;
}

operation result:
Insert picture description here
5. Named pipe programming communication programming realization:

Open function prototype:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>       
int open(const char *pathname, int flags);

//当 open 一个FIFO时,是否设置非阻塞标志(O_NONBLOCK)的区别:
//默认没有设置,
//只读 open :要阻塞---到某个其他进程为写而打开此 FIFO文件。
//类似的,只写 open 要阻塞---到某个其他进程为读而打开它。

Demo code:

Open and read-only:

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
//int mkfifo(const char *pathname, mode_t mode);
int main()
{
    
    
char buf[30]={
    
    0};
if((mkfifo("./file",0600)==-1)&&errno!=EEXIST)//同时满足错误吗:文件已存在
{
    
    
printf("创建失败\n");
perror("why");
}
int fd=open("./file",O_RDONLY);//仅只读这个管道文件
printf("打开成功\n");
int nread=read(fd,buf,30);//一次读20个字节...返回字节数
printf("read %d byte from fifo\ncontext:%s\n",nread,buf);
close(fd);
return 0;
}

Open and write only:

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
//int mkfifo(const char *pathname, mode_t mode);
int main()
{
    
    
char *str="vnfvjdknvdrij";
int fd=open("./file",O_WRONLY);//仅只写这个管道文件
printf("写入打开成功\n");
write(fd,str,strlen(str));
close(fd);
return 0;
}

note: Reading and writing are opened at the same time to operate
. Results:
Insert picture description here
Description:

If O_NONBLOCK (non-blocking) is specified and has no meaning, then read-only open returns immediately. Writing only open will return -1 on error. If no process has opened the FIFO for reading, its errno is set to ENXIO.

Generally, when FIFO is used, it is opened in a non-blocking method

The above example can be extended to an example of client process-server process communication. The function of write_fifo is similar to that of a client, and multiple clients can be opened to send request information to a server. Read_fifo is similar to a server. It monitors the reading end of FIFO in time. When there is data, it is read and processed, but a key problem is that each client must know in advance the FIFO interface provided by the server. The following figure shows this arrangement:

Insert picture description here

Guess you like

Origin blog.csdn.net/weixin_40734514/article/details/109054988
Recommended