IPC(进程间通信)(上)

简介: IPC(进程间通信)

IPC(进程间通信)

进程是操作系统分配资源的基本单位,也就是说进程间的资源是独立的。一个进程无法直接访问另一个进程的资源。

但是进程并不是孤立存在的,进程间需要进行数据传输、进程控制、通知事件、资源共享,所以进程间需要通信。

进程的用户空间对于每个进程而言是独立的,所有内核空间都是共享的。进程的内核空间是所有进程共享的。其实是mmu映射的物理内存属于同一块。所以进程间通信其实是在内核中创建一块缓冲区,将用户空间中的数据拷贝到该缓冲区实现进程间通信的。

/*

内核空间:

   内核空间的线地址是所以进程共享的,但是只有在内核态的进程才能共享。用户进程可以通过系统调用切换到内核态    

*/

进程间通信方式

同一个主机:

匿名管道(只能在有血缘关系的进程间通信)

有名管道

内存映射

内存共享

消息队列

信号量

socket本地套接字

不同主机间:

socket套接字

管道

匿名管道

   匿名管道也成管道。管道实质上是一个在内核缓冲区中的开辟的缓冲区,管道的存储能力有限(Linux下默认情况下4K)。

管道具有文件的特性,可以像操作文件那样操作管道。管道的数据传输是字节流、通过管道的数据顺序的、半双工、一次性  操作。其实现是一个循环队列。

   匿名管道没有文件实体,有名管道有文件实体,但是不存储东西,只是用来不同进程间能够通过文件找到彼此。匿名管道只能用于具有血缘关系的进程间,因为父子进程件的文件描述符是一样的。

int pipe(int pipefd[2]);   //创建匿名管道

   pipfd[0]:读端

    pipefd[1]:写端

       

long fpathconf(int fd,int name);//参看管道缓冲区大小

   eg:fpathconf(pipefd[0],_PC_PIPE_BUF);



//使用一个匿名管道的流程

1.父进程创建一个管道

2.fork()

3.父进程关闭读端  close(pipefd[0]);

4.子进程关闭写端  close(pipefd[1]);

有名管道

   由于匿名管道没有名字,只能用于亲缘关系的进程间通信。为了客服这个缺点,提出了有名管道(FIFO)

   有名管道不同于匿名管道之处在于它提供了一个路径名,以FIFO的文件形式存在文件系统,并且使用起来于普通文件一样。一个进程可以通过访问FIFO文件的路径,就能去于另一个没有血源关系的管道通信。

   FIFO在文件系统中作为一个特殊的文件存在,但是FIFO不存东西,内容存在内存中。当使用FIFO的进程退出后,FIFO将以文件的方式保存在文件系统中。FIFO因为有名字,不相干的进行可以通过打开有名管道进行通信。

int mkfifo(const char*pathnaem,mode_t mode);

//使用注意事项

/*

   1.一个为只读而打开的有名管道会阻塞,直到另一个进程为只写打开该有名管道

   2.一个为只写而打开的有名管道会阻塞,直到另一个管道为只读打开该有名管道

*/

管道的读写行为

1.读管道

1).管道中有数据:read返回实际读到的字节数

2).管道中无数据:

(1).管道写端关闭:read返回0 有客户端退出....

(2).写端没有全部关闭:read阻塞,如果设置成非阻塞,通过返回值判断

2.写管道

1).管道读端关闭,进程终止(发送SIGFIFE信号 默认执行终止进程)

向一个读端关闭的管道写数据

2).读端没有全部关闭

(1).管道已满,write阻塞

(2).管道未满,write将数据写入,返回实际写入的字节数

内存映射(非阻塞的)

内存映射(Menrmory-mapped I/O)是将磁盘文件中的数据映射到内存,用户通过修改内存就能够修改磁盘文件。

/*   mmap函数    */

//在内存中建立内存映射区

void *mmap(void* adrr,size_t length,int port,int flags,int fd,off_t offset);

返回值:成功返回内存映射区的首地址,失败返回-1(宏MAP_FAILED)

参数:

   adrr:    建立的映射区的首地址,由Linux内核指定。传NULL

   length:    欲创建映射区的大小(由磁盘文件大小确定)--->分页的整数倍

   prot:   映射区的权限  PORT_READ   PROT_WRITE   PROT_READ|PROT_WRITE

   flags:  参数标志位    

           MAP_SHARED:将映射区的操作同步到磁盘文件

           MAP_PRIVATE:不将映射区的操作同步到磁盘文件

   fd:        用来建立映射区的文件描述符

   offset:  映射区文件的偏移量(4K整数倍)   文件大小不能为0

       

//释放建立的内存映射区

int munmap(void *adrr,size_t length);  //adrr一定要内存映射区的首地址

匿名映射

映射区来完成文件读写操作十分方便,父子进程间通信有很方便。但是每次建立映射区都要依赖一个文件。

通过建立匿名映射可以不通过文件就可以实现父子进程间通信。

Linux中指定将第三个参数:flags设定为 MAP_SHARED | MAP_ANONYMOUS

int *adrr = mmap(NULL,4,PORT_READ|PORT_WRITE,MAP_SHARED|MAP_ANONYMOUS,-1,0);

内存映射区实现进程间通信的过程

 

有关系的进程(父子进程)
    -在fork()之前通过唯一的父进程,先创建内存映射区(可以建立匿名映射区)
    -创建成功后,fork()创建子进程
    -父子进程共享创建的内存映射区(fork()之后就可以通信了)
无关系的进程
  -准备一个大小不是0的磁盘文件
  -进程1:通过磁盘文件建立内存映射区,得到一个映射区首地址
  -进程2:通过磁盘文件建立内存映射区,得到一个映射区首地址
  -使用内存映射区进行通信

 

信号

信号是一种信息的载体,是一种重要的通信方式。信息具有简单、不能携带大量信息、满足某种条件才能发送、优先级比较高(软中断)。信号是由内核负责发送、内核处理。信号具有延时性。

//信号相关事件和状态
引发内核产生信号的事件:
  1.对于前台进程,用户在终端输入特殊字符  ctrl+c  ctrl+/
    2.硬件异常 eg:非法访问内存(段错误)  除0  内存对齐出错(总线错误)
    3.进程状态的改变  eg:子进程退出给父进程发送 SIGCHLD
    4.运行相关的命令/函数
递达:
    信号递送并到达进程
未决:
    信号产生到被处理的这段时间
阻塞:
    阻塞信号被处理,而不是阻止信号产生。让系统暂时保留信号待以后发送。
信号处理方式:
    执行默认动作
    忽略
    捕捉(回调用户的捕捉函数)

 

Linux内核中的进程控制块PCB包含了与信号相关的信息,主要是未决信号集和阻塞信号集。内核使用位图机制来实现的,但是操作系统不允许我们直接对这两个信号集直接位操作。需自定义另一个信号集,借助该信号集来影响阻塞信号集,阻塞信号集影响未决信号集。

阻塞信号集:将某些信号加入阻塞信号集后,该信号的位置被设置为1,设为屏蔽。当屏蔽之后,再收到该信号,该信号 的处理将推后(解除屏蔽后)。

未决信号集:当信号产生,未决信号集中描述该信号的位翻转为1,表示该信号处于为决状态。当信号被处理翻转回0。

从内核产生信号后由于某些原因不能到达(阻塞)。这类信号的集合称为未决信号集。在屏蔽解除之前一直 处于未决状态。

信号编号

常规信号:1~31号

实施信号:31~63号

信号的四要素:

1.编号 2.名称 3.事件 4.默认处理动作

//我们在使用信号的时候,尽量使用名称。一些信号可能有三个值,在不同的操作系统中使用的值不一样,LINUX使用中间值
/*
  默认执行动作:
    Term:终止进程
    lgn:忽略信号
    Core:终止进程,产生Core文件(通过Core可以查看进程死亡的原因,用于GDB调试)
    Stop:停止(暂停)进程
    Cont:继续运行进程
*/
//9)SIGKILL    19).SIGSTOP信号 不能被忽略和捕捉,只能执行默认动作(终止进程)。甚至不能设置阻塞。
相关文章
|
消息中间件 API Go
微服务的进程间通信(IPC)
微服务的进程间通信(IPC)
208 6
|
消息中间件 存储 Linux
|
消息中间件 Linux API
Linux c/c++之IPC进程间通信
这篇文章详细介绍了Linux下C/C++进程间通信(IPC)的三种主要技术:共享内存、消息队列和信号量,包括它们的编程模型、API函数原型、优势与缺点,并通过示例代码展示了它们的创建、使用和管理方法。
302 0
Linux c/c++之IPC进程间通信
|
消息中间件 程序员 数据处理
探究操作系统中的进程间通信(IPC)机制及其在现代软件开发中的应用
本文深入探讨了操作系统中的核心概念——进程间通信(IPC),揭示了其在现代软件开发中的关键作用。通过对各种IPC机制如管道、消息队列、共享内存等的详细分析,本文旨在为读者提供一个清晰的理解框架,帮助他们掌握如何在实际应用中有效利用这些技术以实现进程间的协同工作。此外,文章还将探讨IPC在高并发环境下的性能优化策略,以及如何避免常见的IPC编程错误。通过结合理论与实践,本文不仅适合希望深入了解操作系统原理的技术人员阅读,也对那些致力于提升软件质量和开发效率的程序员具有重要参考价值。
374 12
|
消息中间件 存储 网络协议
操作系统的心脏:深入理解进程间通信(IPC)机制
在现代计算机系统中,操作系统扮演着至关重要的角色,而进程间通信(IPC)作为操作系统的核心功能之一,极大地影响着系统的性能和稳定性。本文将通过浅显易懂的语言,详细探讨进程间通信的基本原理、主要类型及其实际应用,旨在为读者提供一个清晰且全面的理解和认识。 ##
807 1
|
消息中间件 安全 Kafka
Python IPC机制全攻略:让进程间通信变得像呼吸一样自然
【9月更文挑战第12天】在编程领域,进程间通信(IPC)是连接独立执行单元的关键技术。Python凭借简洁的语法和丰富的库支持,提供了多种IPC方案。本文将对比探讨Python的IPC机制,包括管道与消息队列、套接字与共享内存。管道适用于简单场景,而消息队列更灵活,适合高并发环境。套接字广泛用于网络通信,共享内存则在本地高效传输数据。通过示例代码展示`multiprocessing.Queue`的使用,帮助读者理解IPC的实际应用。希望本文能让你更熟练地选择和运用IPC机制。
282 10
|
安全 开发者 Python
Python IPC大揭秘:解锁进程间通信新姿势,让你的应用无界连接
【9月更文挑战第11天】在编程世界中,进程间通信(IPC)如同一座无形的桥梁,连接不同进程的信息孤岛,使应用无界而广阔。Python凭借其丰富的IPC机制,让开发者轻松实现进程间的无缝交流。本文将揭开Python IPC的神秘面纱,介绍几种关键的IPC技术:管道提供简单的单向数据传输,适合父子进程间通信;队列则是线程和进程安全的数据共享结构,支持多进程访问;共享内存允许快速读写大量数据,需配合锁机制确保一致性;套接字则能实现跨网络的通信,构建分布式系统。掌握这些技术,你的应用将不再受限于单个进程,实现更强大的功能。
180 6
|
消息中间件 Python
深入理解操作系统的进程间通信(IPC)机制
本文将探讨操作系统中的核心概念——进程间通信(IPC),揭示其在系统运作中的重要性及实现方式。通过分析不同类型的IPC手段,如管道、信号、共享内存等,帮助读者更好地理解操作系统的内部工作原理及其在实际应用中的表现。
634 1
|
消息中间件 Kafka 数据安全/隐私保护
Python IPC实战指南:构建高效稳定的进程间通信桥梁
【9月更文挑战第11天】在软件开发中,随着应用复杂度的提升,进程间通信(IPC)成为构建高效系统的关键。本文通过一个分布式日志处理系统的案例,介绍如何使用Python和套接字实现可靠的IPC。案例涉及定义通信协议、实现日志发送与接收,并提供示例代码。通过本教程,你将学会构建高效的IPC桥梁,并了解如何根据需求选择合适的IPC机制,确保系统的稳定性和安全性。
196 5
|
Python
惊!Python进程间通信IPC,让你的程序秒变社交达人,信息畅通无阻
【9月更文挑战第13天】在编程的世界中,进程间通信(IPC)如同一场精彩的社交舞会,每个进程通过优雅的IPC机制交换信息,协同工作。本文将带你探索Python中的IPC奥秘,了解它是如何让程序实现无缝信息交流的。IPC如同隐形桥梁,连接各进程,使其跨越边界自由沟通。Python提供了多种IPC机制,如管道、队列、共享内存及套接字,适用于不同场景。通过一个简单的队列示例,我们将展示如何使用`multiprocessing.Queue`实现进程间通信,使程序如同社交达人般高效互动。掌握IPC,让你的程序在编程舞台上大放异彩。
144 3