进程间通信——无名管道

        管道是(内核缓冲区,打开管道时会在内存中分配一块空间;伪文件--不占用磁盘空间)一个进程连接数据流到另一个进程的通道,它通常是用作把一个进程的输出通过管道连接到另一个进程的输入。例如在shell中输入命令:ls -l  | grep string,我们知道ls命令(其实也是一个进程)会把当前目录中的文件都列出来,但是它不会直接输出,而是把本来要输出到屏幕上的数据通过管道输出到grep这个进程中,作为grep这个进程的输入,然后这个进程对输入的信息进行筛选,把存在string的信息的字符串(以行为单位)打印在屏幕上。

      open可以打开一切类型的文件,写入管道的永远在内存中,关闭管道文件,内存中的信息将会丢失

      管道分为两部分:读端,写端,对应两个文件描述符。数据写端流入,读端流出;操作管道的进程被销毁之后,管道自动被释放;管道只读或只写打开时会阻塞,需要两个进程同时打开,一个读,一个写;当写端关闭时,读端不会阻塞
      管道的实现原理:内部实现方式:队列(环形队列)。管道中有头指针:负责写。管道中有尾指针:负责读。刚开始头尾指针都指向头。写数据是头指针不断向后移动,管道写满后又回头部循环写入,遇到尾指针(管道满,写阻塞)则无法写入。当尾指针读时遇到头指针(管道空,读阻塞)则读取结束。缓冲区大小:默认4k,内核会适当的调整,但有一定范围,不会无限放大
       基于队列的数据结构,管道数据只能读取一次,不能重复读取。半双工(双向,但不能同时工作)无名管道:适用于有血缘关系的进程
      有名管道和无名管道的区别:
       无名:只能在父子进程间进程通信。

       有名:可在任意两个进程间通信,可以通过打开同一个管道文件实现。

        数据在内存中存放,但是主要、有名的管道文件在磁盘

无名管道

# include <stdio.h>
# include <errno.h>
# include <unistd.h>
# include <stdlib.h>
# include <sys/types.h>
# include <sys/stat.h>
 
int main()
{
    int fd[2];
    int ret = pipe(fd);
 
 
    if(ret == -1)
    {
        perror("pipe error");
        exit(0);
    }
 
    printf("pipe[0] = %d\n",fd[0]);
    printf("pipe[1] = %d\n",fd[1]);
 
    close(fd[0]);
    close(fd[1]);
    return 0;
}

无名管道通信
         单个进程可以使用管道完成读写操作,先打开管道后fork子进程,在父子进程利用管道通信过程中,因为数据只能读取一次,如果某一进程执行写操作,则需关闭该进程的读端,如果某一进程执行读操作,则需关闭读端。
示例:父进程查询当前向管道中写入数据;子进程从管道中读取数据。

# include <stdio.h>
# include <errno.h>
# include <unistd.h>
# include <stdlib.h>
# include <sys/types.h>
# include <sys/stat.h>
 
int main()
{
    int fd[2];
    pipe(fd);//fd[0]读  fd[1]写    
    pid_t pid = fork();//创建子进程
    if(pid == -1)//子进程创建失败
    {
        printf("fork error");
        exit(0);
    }
    //子进程查询管道中数据  只读不写
    if(pid == 0)
    {
        char buff = {0};
        close(fd[1]);//不写,关掉写
        read(fd[0],buff,127);
        printf("child buff = "%s\n",buff);
        close(fd[0]);//读完关掉读
    }
    //父进程  只写不读
    else
    {
        close(fd[0]);//不读,关掉读
        sleep(1);
        write(fd[1],"hello",5);
        close(fd[1]);//写完关掉写
        exit(0);
    }
    //父子同时close才会关掉
    close(fd[0]);
    close(fd[1]);
    return 0;
}

 

猜你喜欢

转载自blog.csdn.net/Aspiration_1314/article/details/83066401