进程间通信-管道

进程是一个独立的资源分配单元,不同进程之间资源是独立的,每个进程各自有不同的用户地址空间,进程的全局变量在另一个进程中看不到,不能在一个进程中直接访问另一个进程的资源,所以进程之间交换数据要通过内核,在内核中开辟一块缓冲区,进程1把数据写到内核的缓冲区,进程2再从内核的缓冲区把数据读走,称为进程间通信(IPC)。
这里写图片描述
管道(匿名管道PIPE)
管道是一种基本的IPC机制,它是调用pipe函数在内核中开辟一片缓冲区,该片缓冲区就是管道。它有一个读端和一个写端,然后int pipe(fd[2])通过fd参数给用户程序给用户程序两个文件描述符。fd[0]指向管道的读端,fd[1]指向管道的写端。管道就像打开文件一样,write(fd[1])往管道里写,read(fd[0])从管道里读。
特点
1.普通管道只能进行单向通信。因为开辟的管道只有一个读端和一个写端。
2.该管道只能用于具有血缘关系的进程(例如父子进程),因为是匿名管道,进行通信的两个进程具有公共祖先,才会具有共同的文件描述符信息,才会指向同一个管道。
3.该管道的生命周期随进程。随着进程的退出随即消失
4.管道以字节流的形式读写数据进行通信。
管道的管理
1.匿名管道的创建
这里写图片描述
如果执行成功,pipefd的文件描述符pipefd[0]指向管道的读端,用来执行读操作,pipefd[1]指向管道的写端,用来执行写操作。如果执行失败,则返回-1。
2.从管道里读数据
这里写图片描述
fd为打开的文件描述符,buf是读出数据的存储位置,count为读取的字节数。
3.往管道里写数据
这里写图片描述
fd为打开的文件描述符,buf指向向管道写入的缓冲区,count为读取的字节数。
父子间进程通信
1.创建父进程,父进程创建管道,得到两个文件描述符分别指向管道
这里写图片描述
2.创建子进程,子进程也有两个文件描述符指向管道的两端
这里写图片描述
3.利用管道进行通信,父进程close(fd[0]),write(fd[1])往管道里写数据。子进程close(fd[1]),read(fd[0])从管道中读取数据。
这里写图片描述
代码实现

#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
int main()
{
    pid_t id;
    int fd[2];
    int ret=pipe(fd);
    if(ret<0)
    {
        printf("pipe error!\n");
    }
    if(id=fork()<0)
    {
        printf("fork error!\n");
    }
    else if(id>0)//father
    {
        close(fd[0]);
        int i=0;
        char* mesg=NULL;
        while(i<10)
        {
            mesg="hello";
            write(fd[1],mesg,strlen(mesg)+1);
            sleep(1);
            i++;
        }
        close(fd[1]);
    }
    else//child
    {
        close(fd[1]);
        char mesg[256];
        int j=0;
        while(j<10)
        {
        ssize_t s=read(fd[0],mesg,sizeof(mesg));
        mesg[s-1]='\0';
        printf("%s\n",mesg);
        j++;
        }
        close(fd[0]);
    }
    return 0;
}

使用管道通信的四种特殊情况
1.所有指向通道的写端的文件描述符都关闭了,仍有进程从管道中读取数据,当管道到没有数据时,再次read就会返回0,就像读到文件结束一样。
2.如果指向管道写端的文件描述符没有关闭,但是写进程并没有向管道中写数据,
当剩下的数据被读完后,读进程再次read时会发生阻塞。直到管道有了数据读取后才返回。
3.如果所有指向管道读端的文件描述符都关闭了,这时有进程向管道中write,该进程会受SIGPIPE,通常会导致该进程终止。
4.如果指向管道读端的文件描述符没有关闭,但写进程并没有从进程中读取数据,当写进程把管道写满时,再次write就会发生阻塞,直到管道有了空位置才写数据bing返回。
命名管道(FIFO)
匿名管道没有名字,只能用于具有亲缘关系的进程之间,它是临时的,在完成通信后自动消失。 命名管道 它是存在一个特殊的文件,以FIFO的文件形式存储于文件系统中,只要访问该文件的路径,两个不同的进程之间就可以通过FIFO读写数据进行通信。
注:命名管道和普通文件一样具有文件路径,文件权限,存在于磁盘中,命名管道不能直接存储信息,它存储的信息再两个进程通信结束后就会自动丢失,但命名管道的文件本身还存在。
管道的管理
1.命名管道的创建
这里写图片描述
pathname为创建的命名管道名,mode为该文件的权限。
2.读写命名管道
这里写图片描述
这里写图片描述
用法和匿名管道一样。不一样的的是每次都写之前都需要open打开管道。
注:调用open()打开命名管道的进程可能会发生阻塞。如果同时有读写方式打开,则一定不会导致阻塞。如果以只读方式(O_RDONLY)打开,调用open()的进程直到写方打开管道,同样以写方式(O_WRONLY)打开,也会阻塞到有读方式打开。
代码实现

//write.c
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<string.h>
#include<fcntl.h>
#define _PATH_ "temp"
int main()
{
    int ret=mkfifo(_PATH_,0666|S_IFIFO);
    if(ret==-1)
    {
        printf("mkfifo error\n");
        return 1;
    }
    int fd=open(_PATH_,O_WRONLY);
    if(fd<0)
    {
        printf("open error\n");
        return 2;
    }
    char buf[100];
    memset(buf,0,sizeof(buf));
    int i=0;
    while(i<10)
    {
        scanf("%s",buf);
        write(fd,buf,sizeof(buf)+1);
        i++;
    }
    close(fd);
    return 0;



}
//read.c
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<fcntl.h>
#include<string.h>
#define _PATH_ "temp"
int main()
{
    int fd=open(_PATH_,O_RDONLY);
    if(fd<0)
    {
        printf("open file error\n");
        return 1;
    }
    char buf[100];
    memset(buf,'\0',sizeof(buf));
    int i=0;
    while(i<10)
    {
        ssize_t s=read(fd,buf,sizeof(buf));
        printf("%s\n",buf);
        fflush(stdout);
        i++;
    }
    close(fd);
    return 0;
}

最后在这里将匿名管道和命名管道对比下
1.匿名管道只能实现具有亲缘关系的进程的通信。命名管道以磁盘文件形式存在,可以实现任意进程间的通信。
2.命名管道在读写前需要open()打开。匿名管道创建后通过文件描述符直接读写。
3.匿名管道的生命周期随进程,命名管道一旦创建,在进程结束后文件本身任然存在。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值