?由于进程具有独立性,不同进程间如何通信呢?进程间通信首先需要让不同的进程看到同一份资源(某种形式的内存空间)。由于进程具有独立性的特性,一个进程不能在另一个进程中操作某种资源,因此该资源的提供者不能是进程,只能是操作系统,这也是进程间通信的核心。
进程间通信有两类通信方案——本地通信和网络通信;本地通信指的是在同一台主机同一个操作系统下,不同进程间的通信;本文主要讨论本地通信,网络通信将在后续学习。
匿名管道(Pipe):管道是一种半双工的通信机制,可以在同一个进程中的两个文件描述符之间传递数据。 命名管道(Named Pipe):命名管道也是一种半双工的通信机制,但可以在不同进程之间进行通信。 信号(Signal):信号是一种在进程之间传递简单消息的机制,主要用于进程之间的通知和同步。 消息队列(Message Queue):消息队列是一种通过消息传递进行通信的机制,可以在不同进程之间传递消息。 共享内存(Shared Memory):共享内存是一种进程间通信的高效机制,多个进程可以通过映射同一块内存区域来实现数据的共享。 信号量(Semaphore):信号量是一种用于进程之间同步和互斥的机制,可以用来控制对共享资源的访问。 套接字(Socket):套接字是一种可以在不同主机之间进行进程间通信的机制,可以实现分布式系统间的通信。 文件锁(File Lock):文件锁是一种用于进程之间同步和互斥的机制,可以通过锁定文件来控制对共享资源的访问。 根据具体的业务需求选择适合的进程间通信方式,每种通信方式都有其特点和适用场景。
父进程创建子进程后,子进程会拷贝父进程的task_struct,同样父进程在创建子进程之前打开了一个文件,子进程也会拷贝该文件的struct file,此时两个进程就指向同一个操作系统提供给该文件的内核缓冲区,所以就可以通过该文件的内核缓冲区进行通信了:
管道分为匿名管道pipe和命名管道。
创建匿名管道的思路如下:
父进程调用系统调用创建管道:父进程创建子进程:
如果父进程写入,子进程读取,那么就将父进程读取端关闭,子进程写入端关闭;如果父进程读取,子进程写入,那么就反之:
管道的通信是单向的,即父进程或子进程不能对一个管道同时读和写,只能选择一个,父进程读,子进程就写;子进程读,父进程就写。
在Linux系统中,可以使用以下系统调用接口创建匿名管道:
#include <unistd.h> int pipe(int pipefd[2]);
该函数会创建一个管道,并将相应的读取和写入文件描述符存储在pipefd数组中。pipefd[0]表示读取端文件描述符,pipefd[1]表示写入端文件描述符。
使用示例:
#include <unistd.h> #include <stdio.h> int main() { int pipefd[2]; int ret = pipe(pipefd); <pre class="brush:php;toolbar:false">if (ret == -1) { perror("pipe"); return 1; } printf("读取端文件描述符:%d\n", pipefd[0]); printf("写入端文件描述符:%d\n", pipefd[1]); return 0;
}
运行以上程序,会输出管道的读取和写入端文件描述符。
以下是一个通过匿名管道简单实现进程间通信的代码:
#include<iostream></p><h1>include<string></h1><h1>include<unistd.h></h1><h1>include <sys></h1><h1>include <sys></h1><h1>include <stdlib.h></h1><p>//子进程写,父进程读 int main(){ //1.创建管道 int pipefd[2]; int n = pipe(pipefd); if(n == -1) { std::cerr << "pipe error" << std::endl; exit(1); } //2.创建子进程 pid_t pid = fork(); if(pid < 0) { std::cerr << "fork error" << std::endl; exit(1); } else if(pid == 0) { //子进程 close(pipefd[0]); //关闭读取端 std::string message = "Hello from child!"; write(pipefd[1], message.c_str(), message.size()); close(pipefd[1]); //关闭写入端 exit(0); } else { //父进程 close(pipefd[1]); //关闭写入端 char buffer[1024]; int count = read(pipefd[0], buffer, sizeof(buffer) - 1); if(count > 0) { buffer[count] = 0; std::cout << "Message from child: " << buffer << std::endl; } close(pipefd[0]); //关闭读取端 } return 0; }
将该代码编译为可执行文件后运行结果如下:
在进程间通信时,可能会出现以下场景:
管道为空,read会阻塞管道为满,write会阻塞管道写端关闭,读端最终会读到0,表示已经读到文件结尾管道读端关闭,操作系统会直接杀掉写入的进程匿名管道特性:
面向字节流 只能通过具有血缘关系比如父子/兄弟的进程使用,常用于父子进程间通信 文件的生命周期随进程,管道也是 管道通信是单向的管道自带同步互斥等机制,也就是说管道在写的时候不能读取,读的时候不能写入
以上就是【Linux】进程间通信——匿名管道的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号