专栏首页立权的博客进程通信方式总结

进程通信方式总结

1.管道(pipeline)

  优点:简单

  缺点:1.信息无边界

     2.只能单向写,读

     3.信息无优先级

     4.一般要阻塞,就算使用 O_NONBLOCK 标志位来达到不阻塞,也要一次性把管道写满才能不阻塞,但是无法知道管道可写空间是多少

     5.发送信息少的时候,使用管道效率低,因为需要从用户态转为内核态,进行上下文切换,而且要从用户空间拷贝内容到内核空间

     6.要占用打开文件号

     7.不能用 lseek() 改变读写指针的位置

     8.匿名管道只能在父进程创建,只有通过fork或clone等系统调用产生的子进程能获得这个管道的文件打开号读写管道,而且对管道的关闭和打开需要在C++语言层面自己调用close关闭

      命名管道的话能够,任何进程都可以通过相同的文件路径访问他(普通管道用pipe(文件打开号)创建,然后传给子进程 | 匿名管道用 open 打开,标志位可以设置只读,只写等属性或者O_NONBLOCK

      [是否是读的话没有数据直接退出,如果是写的话要一次写完能写的空间才退出])

     命名管道有一个 inode , 用open打开他的时候如果没有分配内存页就为他分配内存页(GFP_USER?)

2.信息(message)

     优点:相比管道,信息可以按照报文为单位传输数据

     缺点:发送还是需要拷贝用户空间数据到内核空间,接受还是要从内核空间拷贝到用户空间(put_user,store_msg)

        最大报文长度有限制,Linux有两个宏去限制最大报文长度

3.共享内存(shared memory)

     共享内存也使用ipc通用结构管理,每个进程只要找到特定的标识符就可以将某段共享内存和自己的虚拟内存映射挂钩

     实际依赖的是 do_mmap ,标识符是 SHARED 或 SHARED | FIXED , (FIXED是申请到的地址和需要的地址一样的时候设置的)

     具体的 no_page 函数是 shmem_nopapge, 这个函数会凭借 inode 持有的缓存结构 address_space 和地址对应的页面号去 缓存杂凑队列里找 page

     如果缓存队列里找不到,就要去看看inode的i_data结构,共享内存下是 shmem_inode_info , 里面保有文件一级,二级,三级 映射的数组,通过 页面号可以找到 swap_entry_t , 这个 swap_entry_t 相当于交换设备的块号,可以把页面找到并交换进来

     优点:效率高

     缺点:需要同步机制

4.软中断 或称信号(signal)

     task_struct 有四个最核心的和信号相关的域:

     1.signal_struct *sig   //这里面重要的是一个 action 数组,存有相当于硬中断中断向量的sigaction(其实是函数指针)

     2.sigset_t blocked  //对上面的sigset_t类型位图的掩码,sigset_t就是一个long型,信号投过来会把某一位置位1

     3.struct sigpending pending  //保存有一个 sigset_t 和 一个 sig_queue ,这个sigset_t 就是保存其他进程投递过来的信号的位图,这个sig_queue可以找到发信号过来的进程,貌似只要找到就行了,不用知道是谁发了什么信号

     一个进程发送信号给其他进程其实就是向 task_struct 里的 pending 里的 sigset_t 设置位,被投递进程从内核空间退出的时候,就会把这个位抹掉,并且调用相应的软中断函数(信号其实就是软中断),所以信号函数的产生可能有延时

     优点:软件实现的中断,可以记录同一中断信号具体有哪些进程发送来过,硬中断就算多个进程发送同一中断信号,最后只能扫描所有发送这种中断信号的信号源

     缺点:有延时,需要从内核空间退出才能调用中断函数

5.信号量(semaphore)

     也是使用 ipc 通用结构,代表结构是 sem_array ,其中比较重要的三个域:

    1.sem_base  // 实质上最根本的东西,就是用来记录信号量状态的,是一个 sem 结构数组,每个sem都是由 一个 代表信号量本身位图的 semval 和 最后操作进程的id 组合成的结构体

    2.sem_pending // 记录等待者的一条队列,假设一个进程A 想要同时获得 信号量a 的两个单位,信号量b的1个单位,如果不能原子性取得,则会睡眠,同时把自己挂在这条队列上。等到其他进程释放信号量,会尝试

去遍历这个队列,以不更改上面 sem_base 的方式测试一下是否能满足当前遍历到的 进程的要求,如果能满足就唤醒这个进程

     这条队列每个节点包含两个重要信息:1.等待者,2.信号量操作集合(要对哪些信号量增减多少)

    3.undo

     也是一条队列,每当进程成功执行了一个信号量操作集合,就会在这条队列上记账,即把自己的信息和借走了多少信号量封装成一个节点,放进这个队列(同时放入task_struct的队列)。

     在释放信号量的时候会把这个节点出对,也就是销账。如果一个进程 exit 退出但是没有销账,那么内核代码会帮忙销账,task_struct 里有一个 semundo 指针,和上面的 undo 一样类型的队列(节点类型一样)

     只不过都是自己欠的账,内核代码会帮忙把这个节点欠的账还清。

 对信号量的操作集合是原子的,也就是要么全部操作,要么全部不操作,改变某个信号量的同时会记账,如果无法完成集合里所有信号量的操作,就会通过while循环遍历操作集合,回滚所有操作,并且销账

 优点:可以原子性执行一批信号量操作,是通过内核的 锁机制,具体还是要依赖硬件指令(cmpchg等)     

6.Socket

通用IPC结构:ipc_ids 里有一个 kern_ipc_perm 数组,并且用一个信号量去保障单进程修改,kern_ipc_perm保存了创建者的 用户信息,包括权限,perm是权限的缩写

       kern_ipc_perm 被放入 代表结构中,成为代表结构的域(比如报文队列的代表结构就是 msg_queue, 里面用list_head保存一条msg报文链表)

       每个 kern_ipc_perm 都有对应的 key,所以可以通过 key 找到对应的结构

       ipc_ids : 代表结构 = 1 : N 并且可以通过 key 找到代表结构

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Hadoop3.1.1源码Client详解 : Packet入队后消息系统运作之DataStreamer(Packet发送) : 处理异常

    该系列总览: Hadoop3.1.1架构体系——设计原理阐述与Client源码图文详解 : 总览

    执生
  • Hadoop3.1.1源码Client详解 : 写入准备-RPC调用与流的建立

    该系列总览: Hadoop3.1.1架构体系——设计原理阐述与Client源码图文详解 : 总览

    执生
  • 动态规划-最长回文串

      用一个二维数组,dp[ i ][ j ] 表示 下标 i ~ j 字符串是否是回文的,false or true

    执生
  • 进程间通信

    进程间通信(IPC,InterProcess Communication)是指在不同进程之间传播或交换信息。

    大学里的混子
  • 2020年造车新势力:几家欢喜,几家愁

    资本追捧、技术加持,加之在赛道上的坚守,这些原本只想活下去的造车新势力们,最终在年底收到了回报。

    镁客网
  • ApiBoot - ApiBoot Quartz 使用文档

    ApiBoot内部集成了Quartz,提供了数据库方式、内存方式的进行任务的存储,其中数据库方式提供了分布式集群任务调度,任务自动平滑切换执行节点。

    恒宇少年
  • 2019年后,Java岗面试快速突击指南

    大家好。这篇文章给大家分享一下如何获得一个可以去参加面试的最小可行知识(Minimal Viable Knowledge)!我自己在就基本上靠文章中的策略在找...

    Java码农那些事
  • Linux查看系统、核数、CPU、位数

    40 个核,处理器为 Intel(R) Xeon(R) CPU E7-8891 v4 @ 2.80GHz , 64 位

    机器学习和大数据挖掘
  • 关于PHP浮点数精度损失问题

    $f = 0.57; echo intval($f * 100); //56 结果可能有点出乎你的意外,PHP遵循IEEE 754双精度: 浮点数, 以64位...

    wangxl
  • “数据访问函数库”(DataAccessLibrary for .net2.0 )源代码下载 09.06.15更新

    最新下载地址: http://www.naturefw.com/nature/down.aspx DLL文件说明      Controls.dll 控件集...

    用户1174620

扫码关注云+社区

领取腾讯云代金券