第19章 进程通信

1 管道

1.1 特点

  • 生产者/消费者模型
  • 半双工:双向,每次都能朝一个方向传输数据
  • 管道作为一组VFS对象,可以使用VFS通用结构访问(比如读写);管道被组织为pipefs这种特殊文件系统,在系统目录树没有安装点,用户看不到它们
  • 管道创建后,返回一对文件描述符,分别用来读和写;然后通过fork()系统调用把这对描述符传给子进程,实现父子进程的管道通信
  • 管道创建后,可以被任意进程使用,但是因为其半双工工作模式,如果有多个进程对其访问,必须加锁
  • 管道创建的系统调用为pipe(),C函数库中,popen()和pclose()封装了管道相关的系统调用,更加方便

 

1.2 典型应用

ls | grep xxx

“|”可以创建管道;第一个子进程ls的标准输出被“|”重定向管道中;第二个子进程grep从管道读取数据作为输入,以替代标准输入,完成grep操作;grep的输出默认为标准输出。

 

1.3 管道数据结构

管道也是文件,可以通过VFS系统调用来访问管道,因此对于每个管道,应该有:一个索引节点对象 + 两个文件对象(读写);

如果一个索引节点表示管道,其i_pipe成员指向struct pipe_inode_info结构:

  • struct wait_queue *wait:管道/FIFO 等待队列,里面是等待读写的进程
  • struct pipe_buffer[] bufs:管道缓冲区描述符数组,里面包含写入管道待读出的数据
  • unsigned int curbuf:待读数据所在的缓冲区索引
  • unsigned nrbufs:包含待读数据的缓冲区数量,curbuf + nrbufs得到首个可写缓冲区

 

1.4 从管道中读数据

从一个管道中读取n个字节(阻塞读)

管道大小p 有写进程 无写进程
p = 0 等待数据直到拷贝n个字节,返回n 返回0
0 < p < n 等待数据直到拷贝n个字节,返回n 拷贝p个字节并返回p,管道为空
p >= n 拷贝n个数据并返回n,管道还剩p-n个字节 拷贝n个数据并返回n,管道还剩p-n个字节

对于阻塞读,如果管道为空 && 没有写进程,会返回已经拷贝的字节数,不会等待;

对于非阻塞读,立刻拷贝并返回结果(拷贝的字节数),并不会关心有无写进程。

 

1.5 向管道中写数据

把n个字节写入管道(阻塞写)

可用缓冲区u 有读进程 无读进程
u <= n <= 4096 等待读,直到有n-u个字节被释放,才写入n个字节,返回n 发送SIGPIPE并返回-EPIPE
u >= n 写入n个字节,返回n 写入n个字节,返回n

如果管道缓冲区大小不足,且没有读进程,直接返回。

 

 

2 FIFO(命名管道)

1.2 特点

  • 生产者/消费者模型
  • 与管道不同的是:FIFO具有文件名且包含在系统目录树中;是一种全双工通信
  • 因为存在文件名,所以可以被任意进程通过文件名访问

 

 

3 System V IPC

  • Interprocess Communication,进程间通信
  • IPC资源包括信号量、消息队列和共性内存,可以由任一进程访问
  • 统一使用IPC数据结构,进程请求IPC资源时创建IPC数据结构

关于共享内存:

  • 最高效的进程通信形式
  • 允许多个进程共享内存
  • 进程访问共享内存时,需要在自己的地址空间新增内存区,该内存区将与共享内存物理页框映射
  • shmat()函数把一个共享内存区attach到进程上,返回内存区起始线性地址;shmat()不修改进程的页表
  • 共享内存区缺省限制:最大数量4096,每个共享内存块最大32MB,所有共享内存区的最大字节数8GB —— 这些限制可以调整
  • 每个IPC共享内存区属于shm特殊文件系统,在系统目录树没有安装点,因此用户不能通过VFS打开访问它的文件

 

 

4 POSIX消息队列

IPC属于内核提供给用户进程的进程间通信方法,其中包括消息队列;

POSIX消息队列属于基于POSIX标准接口的消息队列,基于消息队列实现,具有很多优点:

  • 更简单的基于文件的应用接口
  • 完全支持消息优先级
  • 完全支持消息到达的异步通知
  • 完善的超时机制

 

 

5 套接字

  • server-client模型
  • 适用于不同计算机通过网络交换数据

 

posted @ 2025-04-24 00:03  moonのsun  阅读(14)  评论(0)    收藏  举报