西安那里做网站,wordpress 设置关键字,新浪微博登录网页版,163域名注册一、管道介绍 管道#xff08;Pipe#xff09;是一种在UNIX和类UNIX系统中用于进程间通信的机制。它允许一个进程的输出直接成为另一个进程的输入#xff0c;从而实现数据的流动。管道是一种轻量级的通信方式#xff0c;用于协调不同进程的工作。 1. 创建和使用管道#…一、管道介绍 管道Pipe是一种在UNIX和类UNIX系统中用于进程间通信的机制。它允许一个进程的输出直接成为另一个进程的输入从而实现数据的流动。管道是一种轻量级的通信方式用于协调不同进程的工作。 1. 创建和使用管道 创建 管道可以通过在Shell命令中使用竖线符号 | 来创建也可以在程序中使用系统调用 pipe 来创建。使用 管道通过将一个进程的标准输出stdout连接到另一个进程的标准输入stdin从而实现两者之间的数据传输。2. 匿名管道类型 管道分为匿名管道Anonymous Pipe和命名管道Named Pipe。匿名管道 由操作系统动态创建用于具有亲缘关系的进程之间的通信其句柄仅在创建时有效。3. 命名管道FIFO类型 命名管道是一种特殊的文件也称为FIFOFirst In, First Out。命名 在文件系统中具有唯一名称不限于亲缘关系的进程可以在不同进程之间共享数据。4. 进程间通信IPC目的 管道用于实现进程间通信允许一个进程的输出成为另一个进程的输入。特点 管道是半双工的数据流只能单向传输需要两个管道来实现双向通信。5. Shell中的管道语法 在Shell中使用 | 将一个命令的输出传递给另一个命令形成管道。示例 ls | grep pattern这会将 ls 的输出传递给 grep 进行过滤。6. 程序中的管道系统调用 在C语言等编程语言中可以使用 pipe 系统调用创建管道使用 dup2 复制文件描述符最后使用 exec 执行其他程序。7.关闭和错误处理关闭 使用管道时需要确保在合适的时候关闭不需要的文件描述符以避免资源泄漏。错误处理 对于管道的创建和使用需要进行错误处理以处理可能发生的异常情况。8.限制和注意事项有限性 管道的缓冲区有限可能导致阻塞特别是在没有足够空间来容纳数据时。同步问题 管道的使用可能涉及到进程间的同步问题需要谨慎处理。 图1 匿名管道 ls |wc -l 这是一种典型的使用匿名管道的情况用于连接两个进程其中一个进程的输出成为另一个进程的输入。在这里ls命令用于列出目录中的文件而wc -l命令则用于统计行数因此可以用于统计目录中文件的数量。 二 、管道特点 匿名管道工作 内核内存中的缓冲器 管道是在内核内存中维护的缓冲器用于在两个进程之间传递数据。这个缓冲器是有限的因此管道的容量是有限的当管道达到容量上限时写操作可能会阻塞。 匿名管道与有名管道的特性 匿名管道没有文件实体它是通过系统调用 pipe 创建的。有名管道则是在文件系统中有唯一名称的文件通过 mkfifo 创建。有名管道可用于不同进程之间的通信而匿名管道通常用于有亲缘关系的进程。 管道的读写操作 管道的读写操作与文件相似可以使用标准的文件I/O操作如read和write。进程通过向管道写入数据或从管道读取数据来进行通信。 消息边界的缺失 与消息队列不同管道是一个字节流不存在消息边界的概念。进程可以读取任意大小的数据块而不受写入数据块大小的限制。这种特性使得管道在流式数据传输场景中非常灵活。 数据的顺序性 管道传递的数据是顺序的即数据的读取顺序与写入顺序保持一致。这确保了在管道中传递的数据在接收端是按照正确的顺序被处理。 单向传递 管道是单向的即数据的传递方向是确定的。一端用于写入数据另一端用于读取数据。这使得管道成为半双工的通信机制。 一次性读取 从管道中读取数据是一次性的操作即一旦数据被读取它就从管道中被移除。这也意味着如果某个进程没有读取所有写入管道的数据这些数据将被丢弃。 无法随机访问 与文件不同管道中的数据不能通过 seek() 等操作进行随机访问。由于管道是一个流式的通信机制数据只能按顺序读取。 匿名管道的限制 匿名管道通常限制在具有公共祖先的进程之间使用。这通常是父子进程之间的通信或者通过其他方式具有亲缘关系的进程之间的通信。匿名管道是在 pipe() 系统调用时创建的。
三、 为什么可以使用管道进行进程间通信 在父子进程或兄弟进程之间使用匿名管道进行通信时理解文件描述符表的概念是非常重要的。文件描述符表是每个进程内部维护的一张表用于跟踪打开的文件和其他I/O资源。以下是匿名管道在进程间通信中与文件描述符表的关系 文件描述符的创建 当调用 pipe 系统调用创建匿名管道时会返回两个文件描述符这两个文件描述符分别代表管道的读端和写端。 父子进程之间的文件描述符继承 在调用 fork 创建子进程时子进程将会继承父进程的文件描述符表。这意味着子进程也会获得父进程的管道文件描述符。 关闭不需要的文件描述符 通常在使用管道进行通信时需要关闭不需要的文件描述符。例如在子进程中关闭管道的写端在父进程中关闭管道的读端以确保每个进程只使用它需要的文件描述符。 数据流动 当一个进程向管道写入数据时数据通过管道流向另一个进程。这是通过在一个进程中使用 write在另一个进程中使用 read 来完成的而这些操作使用文件描述符。 匿名管道通信父子进程、兄弟进程 四、管道的数据结构 五、 父子进程之间使用匿名管道通信 /*#include unistd.hint pipe(int pipefd[2]);功能创建一个匿名管道用来进程通信参数int pipefd[2] 这个数组是一个传出参数pipefd[0] 对应管道的读端文件描述符)pipefd[2] 对应管道的写端返回值成功0失败-1注意 匿名管道只能用于具有关系的进程之间的通信父子进程、兄弟进程*/#include stdio.h
#include unistd.h
#include stdlib.h
#include sys/types.h
// 子进程发送数据给父进程父进程输出
int main(){// 在fork之前创建管道int pipefd[2];int ret pipe(pipefd);if(ret-1){perror(pipe);exit(0);}// 创建子进程pid_t pid fork();if(pid0){printf( i am a parent,pid : %d\n,getpid());char buf[1024]{0};while(1){//读int len read(pipefd[0],buf,sizeof(buf));printf(parent recv :%s,pid: %d\n,buf,getpid());char * str heloo ,i am your parent;// 想管道写数据write(pipefd[1],str, strlen(str));sleep(1);}}else if(pid0){//sleep(10);printf( i am a child process, pid: %d\n,getpid());char buf[1024]{0};while (1){char * str heloo ,i am your grandfaher;// 向管道写数据write(pipefd[1],str, strlen(str));sleep(1);// 读int len read(pipefd[0],buf,sizeof(buf));printf(parent recv :%s,pid: %d\n,buf,getpid());}}return 0;
} 六、fpathconf查看管道大小 fpathconf 是一个用于获取文件路径配置值pathconf values的函数。通过这个函数可以获取与文件或文件描述符相关联的一些运行时配置信息包括管道的大小。 要查看管道的大小可以通过 fpathconf 函数来获取相应的配置值。对于管道的大小我们关注的是 PIPE_BUF它表示一个原子的写入或读取操作的最大字节数。注意PIPE_BUF 并不一定反映实际管道的大小而是表示每次写入或读取的最大字节数它是一个限制不同系统可能有不同的值 #include stdio.h
#include unistd.h
#include stdlib.h
#include sys/types.hint main(){int pipefd[2];int ret pipe(pipefd);//获取管道大小long size fpathconf(pipefd[0],_PC_PIPE_BUF);printf(pipe size : %ld\n,size);return 0;
}