Linux:进程通信、管道通信

目录

一、认识进程通信

二、管道通信

1.匿名管道

2.命名管道


一、认识进程通信

在了解进程之间的通信之前,我们知道进程具有独立性,不会干扰彼此的运行,但是进程是可以互相发送消息的,这种通信不会影响进程的独立。

  • 进程通信的目的

数据传输:一个进程需要将它的数据发送给另一个进程。
资源共享:多个进程之间共享同样的资源。
通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如子进程终止时要通知父进程)。
进程控制:有些进程希望完全控制另一个进程的执行(如 Debug 进程),此时控制进程希望能够拦截另一个进程的所有陷入和异常,并能够及时知道它的状态改变。

  • 进程通信的本质

进程之间通信的本质,就是让两个进程同时操作同一份资源。这份资源只能由操作系统提供,不能由进程之间的任何一方提供,否则,就会破坏进程的独立性。

  • 进程通信的分类

管道
匿名管道pipe
命名管道
System V IPC
System V 消息队列
System V 共享内存
System V 信号量
POSIX IPC
消息队列
共享内存
信号量
互斥量
条件变量
读写锁

二、管道通信

管道通信是Unix 中最古老的进程间通信的形式。
我们把从一个进程连接到另一个进程的一个数据流称为一个"管道"。

  • 管道分为匿名管道和命名管道。

1.匿名管道

匿名管道通常用于具有亲缘关系的进程之间,比如父子进程之间。

管道通信是半双工模式通信,即只能单方向通信。

匿名管道文件是内存级文件,即用即销毁,在磁盘中没有其对应的存储。

  • 从文件描述符角度理解匿名管道

一个进程的PCB关联着一张文件描述符表,0、1、2默认是被三个标准流占用的,如果一个进程以'r'的方式打开一个文件,又以'w'的方式打开同一个文件,在文件描述符表中是会占用两个文件描述符的。

在父进程fork创建子进程,发生浅拷贝,各自的fd指向的内容是相同的。

由于匿名管道是单向通信,因此通信时,只能有一个进程在读管道,也只能有一个进程在向管道写数据,所以,父进程和子进程管道通信之前,父子进程要各自关掉一个描述符,(由于此时的文件被多个进程打开,当其中一个进程关文件,则只是将文件的引用计数减一,并不是真的关掉文件)。

  • 父子进程管道通信的流程
  • 匿名管道通信时的4种情况

1.父进程阻塞:管道内没有数据,并且此时子进程不关闭写端文件fd,则读端(父进程)就要阻塞等待,直到管道中有数据。

2.子进程阻塞:管道大小被写满,此时父进程不关闭读端文件fd,则写端(子进程)就要阻塞等待

3.如果写端不再向管道中写数据,并且此时关闭了写端文件fd,则父进程读完管道中的数据后,最后会读到0,用来表示读到了文件尾。

4.如果读端不再从管道中读数据,并且此时关闭了读端文件fd,而写端文件还在向管道中写数据,则操作系统会直接终止写入的进程(子进程),通过发送信号13 SIGPIPE来杀掉子进程。

  • 管道通信的5种特性

1.由于管道通信时,要么是读端在读,要么是写端在写,不会出现一边读一边写的情况,所以管道自带同步机制。

2.管道通信常见于具有亲缘关系的进程,比如父子进程。

3.管道通信是面向字节流的。

4.父进程或者子进程退出,则管道自动释放,管道文件的生命周期是跟随进程的。

5.管道通信是半双工模式,并且是一种特殊的半双工模式,特殊指在一次通信中,写端只能写,读端只能读。

  • 匿名管道的实例
bash 复制代码
int main()
{

    //1.父进程创建管道
    int pipefd[2];
    int n = pipe(pipefd);

    if(n < 0)return 1;
    //管道规定,0为读,1为写
    printf("pipefd[0]:%d,pipefd[1]:%d\n",pipefd[0],pipefd[1]);

    //2.创建子进程
    pid_t id = fork();
    if(id == 0)
    {
        //子进程
        close(pipefd[0]);
        Pro_Wrte(pipefd[1]);
        exit(0);
    }    
    //父进程
    close(pipefd[1]);
    Pro_Read(pipefd[0]);
    wait(NULL);

    return 0;
}
  • 实现一个进程池

主进程有多个子进程。要求实现负载均衡,给每个进程均衡分配任务。

2.命名管道

命名管道和匿名管道唯一的区分就是,命名管道对应在磁盘上是有名称的特殊文件,但是作为内存中的管道来通信同样不需要和磁盘做IO。

需要我们记住的是,匿名管道常常用于具有亲缘关系的进程之间通信,而命名管道可以帮助两个毫不相干的进程通信。

管道通信的本质就是利用了多个文件描述符指向的多个文件结构体的缓冲区是同一份,**由于毫不相干的进程要利用管道通信,就必须要让这两个进程都能"看到"这同一个管道文件,**因此命名管道常常用于不相干的进程之间通信,而具有亲缘关系的进程只用匿名管道即可通信。

相关推荐
7yewh1 分钟前
嵌入式 linux Git常用命令 抽补丁 打补丁
linux·arm开发·git·嵌入式硬件·ubuntu·嵌入式·嵌入式软件
迷路爸爸18031 分钟前
如何在Windows与Linux(Ubuntu/CentOS)之间配置SSH免密登录
linux·windows·ubuntu
纪伊路上盛名在32 分钟前
生成式AI、大模型、多模态技术开发与应用学习清单
服务器·人工智能·笔记·学习·知识图谱·学习方法
自由且自律1 小时前
【经验分享】容器云运维的知识点
运维·经验分享
小乌龟不会飞1 小时前
操作系统的基本认识
linux
张声录12 小时前
【ETCD】【源码阅读】深入解析 raftNode.start方法实现
服务器·数据库·etcd
下雪了 ~2 小时前
HTTP和HTTPS的区别有哪些?
服务器·前端·笔记·网络协议·计算机网络
记得多喝水o2 小时前
docker环境部署zabbix
运维·网络·网络协议·tcp/ip·信息与通信
运维&陈同学2 小时前
【Elasticsearch01】企业级日志分析系统ELK之Elasticsearch单机部署
大数据·linux·elk·elasticsearch·微服务·云原生·jenkins
百川Cs3 小时前
【Linux】文件挂载系统-Filesystem mounting
linux·运维·服务器