管道

我们先来说说管道时做什么用的?
所谓管道,就是指能够连续一个写进程和一个读进程,并允许它们以生产者-消费者的身份进行通信的一种共享文件,又称为pipe文件。由写进程在管道的写入段(0端)将数据写入管道,而读进程则是在管道的读出端(1端)将数据读出。
管道分为匿名管道和有名管道。


在说匿名管道之前,我们先来解决一下管道的一些小的问题。
一、pipe文件的建立
分配磁盘和内存索引结点、为读进程分配文件表项、为写进程分配文件表项、分配用户文件描述符。
二、读/写进程互斥
内核为地址设置一个读指针和一个写指针,按先进先出顺序读、写。为使读、写进程互斥地访问pipe文件,需使各进程互斥地访问pipe文件索引结点中的直接地址项。因此,每次进程在访问pipe文件前,都需检查该索引文件是否已被上锁。若是,进程便睡眠等待,否则,将其上锁,进行读/写。操作结束后解锁,并唤醒因该索引结点上锁而睡眠的进程。
三、一些管道会涉及到的函数先来了解一下。
1、pipe()
建立一无名管道。
系统调用格式:pipe(filedes)
参数定义:intpipe(filedes);int filedes[2];
其中,filedes[1]是写入端,filedes[0]是读出端。
2、read()
系统调用格式
read(int fd[0],char* buf,unsigned nbyte)
功能:从fd所指示的文件中读出nbyte个字节的数据,并将它们送至由指针buf所指示的缓冲区中。如该文件被加锁,等待,直到锁打开为止。
参数:fd[0]表示以读的形式进入,buf表示将读到的内容写在buf中,nbyte表示需要读取的字节数。
3、write()
系统调用格式
write(int fd[1],char* buf,unsigned nbyte)
功能:把nbyte个字节的数据,从buf所指向的缓冲区写到由fd所指向的文件中。如文件加锁,暂停写入,直至开锁。
参数:fd[1]表示以写的形式进入,buf表示将buf中的内容写入管道,nbyte表示需要写入的字节数。
参数定义同read()。


接下来,我们先来说说什么是匿名管道(无名管道)吧。
一个临时文件,利用pipe()建立起来的无名文件(无路径名),只有亲缘关系的进程之间才可以进行匿名管道的通信。
看一段代码了解一下:

#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
int main()
{
    int fd[2] = {0};
    if(pipe(fd) == -1)
    {
        perror("pipe");
        return 1;
    }

    pid_t pid = fork();
    if(pid < 0)
    {
        perror("fork");
        return 2;
    }
    else if(pid == 0)//child
    {
        close(fd[0]);
        const char* msg = "father, i am child";
        int i = 5;
        while(i--)
        {
            write(fd[1],msg,strlen(msg));

            sleep(1);
        }
    }
    else//father
    {
        close(fd[1]);
        char buf[1024];
        while(1)
        {
           // sleep(5);
            ssize_t s = read(fd[0],buf,sizeof(buf)-1);
            if(s > 0)
            {
                buf[s] = 0;
                printf("fathe: %s\n",buf);
            }
            else if(s == 0)
            {
                printf("child quit\n");
                break;
            }
            else
            {
                perror("read");
                break;
            }
        }
    }
    return 0;
}

我们接下来看看运行结果:

fathe: father, i am child
fathe: father, i am child
fathe: father, i am child
fathe: father, i am child
fathe: father, i am d
child quit

虽然运行结果是固定的码中可以看出

fathe: father, i am child

是一句一句出来的并不是一次性出来,最管道里没有内容了,就打
印出来了一句

child quit


最后,我们再来再来说说关于管道的四种情况(子进程写,父进程读):
1、子进程只写一次,直接跳出,父进程也只读一条。写端一直在写,突然写端关闭,读端就会一直在读,直到读到管道结尾类似于文件结尾,再读就到了0值。
2、子进程不写也不关闭读端,父进程就一直在等,直到等到文件结束。
3、写端一直在写,读端一直不读,写满了,写端就不写了,等读端读。(二者访问具有一致性)。当读端读时,管道是以字节流的形式往出读,并不是以你写的方式往出读,可能会一次性读出来一大片。
4、写进程一直在写,读进程不光不读还直接关掉。当读端关闭时,写端就会被立刻终止,被操作系统终止,属于,代码没有跑完退出了(进程异常)。由于,父进程是读进程,子进程是写进程,所以,父进程就可以得到子进程终止信息。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值