进程学习篇
一、进程间通信(IPC)
进程间通信(IPC)是进程与进程之间交换信息的方式。
1. 常用IPC通信方式
- 无名管道(pipe)
- 有名管道(fifo)
- 信号(signal)
- 共享内存(mmap)
- 套接字(socket)
2. 过时的IPC通信方式
- System V IPC
- 消息队列
- 信号灯集
二、无名管道
1. 函数定义与使用
int pipe(int pfd[2]);
pfd[0]
为读描述符pfd[1]
为写描述符
2. 注意事项
- 只能用于亲缘关系的进程间通信(父子进程,兄弟进程)
- 管道通信是单工的,一端读,一端写
- 数据自己读不能自己写
- 管道可以用于大于2个进程共享
3. 读写特性
- 读管道:
- 管道中有数据,
read
返回实际读到的字节数 - 管道中无数据,且写端全部关闭,
read
返回0 - 写端没有全部被关闭,
read
阻塞等待
- 管道中有数据,
- 写管道:
- 读端全部被关闭,进程异常终止(可捕获
SIGPIPE
信号避免) - 管道已满,
write
阻塞(管道大小64K) - 管道未满,
write
将数据写入,并返回实际写入的字节数
- 读端全部被关闭,进程异常终止(可捕获
三、有名管道(FIFO)
1. 创建管道
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *filename, mode_t mode);
2. 打开方式
open(const char *path, O_RDONLY);
只读open(const char *path, O_RDONLY | O_NONBLOCK);
只读且非阻塞open(const char *path, O_WRONLY);
只写open(const char *path, O_WRONLY | O_NONBLOCK);
只写且非阻塞
3. 特点
- 允许非亲缘进程间通信
- 通过路径名操作,在文件系统中可见
- 文件IO操作有名管道
- 遵循先进先出规则
- 不支持
lseek
操作 - 单工读写
4. 注意事项
- 不能以
O_RDWR
模式打开FIFO文件进行读写操作 O_NONBLOCK
选项表示非阻塞- 只读方式打开时,阻塞与非阻塞的区别
- 只写方式打开时,阻塞与非阻塞的区别
- 数据完整性保证(
PIPE_BUF
大小)
四、内存映射(mmap)
1. 概念
使磁盘文件与内存中的缓冲区相映射,进程可以像访问普通内存一样对文件进行访问。
2. 函数定义
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
- 创建共享内存映射
3. 参数说明
addr
:映射内存地址,通常设置为NULLlength
:映射地址空间的字节数prot
:访问权限(如PROT_READ
、PROT_WRITE
等)flags
:映射类型(如MAP_SHARED
、MAP_PRIVATE
等)fd
:文件句柄,匿名映射写-1offset
:映射文件的偏移量
4. 注意事项
- 创建映射区时隐含读操作
MAP_SHARED
要求映射区权限小于等于文件打开权限MAP_PRIVATE
时,操作只影响内存,不写入磁盘- 映射区释放与文件关闭无关
- 文件大小必须大于0
- 文件偏移量必须是4K的整数倍
- 映射大小可以大于文件大小,但只能访问文件page的内存地址
5. 映射种类
- 基于文件的映射
- 匿名映射(适用于亲缘关系进程间通信)
6. 释放内存映射
int munmap(void *addr, size_t length);
- 成功返回0,失败返回-1
五、System V共享内存
1. 使用步骤
- 创建/打开共享内存
- 映射共享内存
- 读写共享内存
- 撤销共享内存映射
- 删除共享内存对象
2. 函数定义
key_t ftok(const char *path, int id);
生成IPC键值int shmget(key_t key, int size, int shmflg);
创建共享内存void *shmat(int shmid, const void *shmaddr, int shmflg);
映射共享内存int shmdt(void *shmaddr);
撤销共享内存映射int shmctl(int shmid, int cmd, struct shmid_ds *buf);
控制共享内存
六、信号机制
1. 概念
信号是在软件层次上对中断机制的一种模拟,是一种异步通信方式。
2. 信号产生
- 按键产生
- 系统调用函数产生
- 硬件异常
- 命令行产生
- 软件条件(如被0除,访问非法内存等)
3. 信号处理方式
- 缺省方式
- 忽略信号
- 捕捉信号
4. 常用信号
列出了如SIGHUP
、SIGINT
、SIGQUIT
等信号及其默认操作。
5. 信号命令与函数
kill
、killall
命令发送信号kill
、raise
函数发送信号alarm
、ualarm
、setitimer
函数实现定时器功能
6. 信号捕捉
定义信号处理函数,并使用signal
或sigaction
函数关联信号与处理函数。
7. 定时器的实现
使用SIGCHLD
信号实现子进程的回收。
8. 信号集与阻塞
- 信号集操作函数:
sigemptyset
、sigfillset
、sigaddset
、sigdelset
、sigismember
sigprocmask
设定信号集的处理方式pause
、sigsuspend
函数实现信号的阻塞