[LINUX]管道的实现

管道,管道分为命名管道和无名管道,他们的区别主要是初始化的方式不同。

  • ①管道的存取:命名管道是一个实际存在于文件系统的特殊类型文件对应了内存索引节点,这中间会维护一个读偏移量和写偏移量。当一个进程以读的方式打开管道后(系统调用read),如果此时还没有任何其他进程试图往该管道里面写数据,那么内核会让这个读进程进入睡眠状态,直到另一个进程以写的方式打开该管道,并往里面写入数据(写的方式和写普通文件完全一样,先写到内核的高速缓冲区中,然后再延迟写到对应的磁盘上。在内核中会维护一个固定大小的环形队列来处理写入的磁盘块缓冲,即管道其实是有大小限制的。当试图写入的字节数小于容量时,内容被写入到环形队列中,同时向后移动写偏移量,便于下一次写入。当写入的进程操作完毕后(关闭了对应的fd),内核会唤醒因等待读管道而被睡眠的进程,如果有多个进程在等待读取,则都会被唤醒,采用竞争的方式,最终有一个进程会读到管道内的内容,而其他读进程再次被内核睡眠。
  • ②管道的清除:当完成了一次写入和读取后,如果此时没有正在睡眠的等待写入的进程的话,内核就会默认管道已不被需要,而唤醒所有等待读的进程,返回读到了0个字节,并清除管道对应的内存索引节点中的信息,将管道大小初始化。即在操作管道的时候,必须确保连续的写入和读取,如果中间有断层,那么这个管道很有可能被系统回收。比较典型的例子是python的多线程,会根据时间片进行任务的切换,如果时间片到的时候,正在写入,此时被切换到其他线程的话,很有可能再切换回来的时候,已经无法再往管道中写入数据了,管道可能已经被内核回收了。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux管道是一种进程间通信方式,可以用于实现一个进程将数据传递给另一个进程。它是一种半双工的通信方式,即数据只能在一个方向上流动,而且只能在建立了父子进程关系的进程之间使用。 下面是使用管道实现进程间通信的基本步骤: 1. 创建管道 首先需要使用系统调用pipe()创建一个管道。这个函数会返回两个文件描述符,一个用于读取管道数据,一个用于写入管道数据。 2. 创建子进程 接下来需要使用系统调用fork()创建一个子进程。这个函数会返回两次,一次在父进程中返回子进程的PID,另一次在子进程中返回0。 3. 父进程写入数据 在父进程中,可以通过写入管道文件描述符来将数据传递给子进程。可以使用系统调用write()将数据写入管道。 4. 子进程读取数据 在子进程中,可以通过读取管道文件描述符来获取父进程传递的数据。可以使用系统调用read()从管道中读取数据。 5. 关闭管道 当通信结束后,需要关闭管道。可以使用系统调用close()关闭管道的读取和写入端。 下面是一个简单的代码示例,演示了如何使用管道实现进程间通信: ``` #include <stdio.h> #include <unistd.h> int main() { int fd[2]; pid_t pid; char buf[256]; // 创建管道 if (pipe(fd) < 0) { fprintf(stderr, "pipe error\n"); return -1; } // 创建子进程 if ((pid = fork()) < 0) { fprintf(stderr, "fork error\n"); return -1; } else if (pid > 0) { // 父进程写入数据 close(fd[0]); // 关闭读取端 write(fd[1], "hello world\n", 12); close(fd[1]); // 关闭写入端 } else { // 子进程读取数据 close(fd[1]); // 关闭写入端 read(fd[0], buf, sizeof(buf)); printf("received data from parent: %s", buf); close(fd[0]); // 关闭读取端 } return 0; } ``` 在这个示例中,我们首先创建了一个管道,然后使用fork()创建了一个子进程。在父进程中,我们通过write()将数据写入管道中;在子进程中,我们通过read()从管道中读取数据。最后,我们分别关闭了管道的读取和写入端。 注意,管道的缓冲区大小是有限的,如果写入的数据超过了缓冲区的大小,写入操作会被阻塞,直到有足够的空间。同样地,如果读取的数据为空,读取操作也会被阻塞,直到有数据可读取。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值