“Let’s go”
进程
进程同步
- 管道
- FIFO
- XSI IPC—(消息队列,信号量,共享内存)
- 消息队列
- 信号量
- 共享内存
- POSIX信号量
管道
- 半双工,父子进程使用
- 若写入的字节数小于等于PIPE_BUF,可保证是原子的
XSI IPC
缺点1. IPC结构是在系统范围内起作用的,没有引用计数。它们会一直留在系统中直到发生下列动作为止:
某个进程调用msgrcv或者msgctl读消息或者删除消息队列;或某个进程执行ipcrm命令删除消息队列;或正在自举的系统删除消息队列。
与管道相比,当最后一个引用管道的进程终止时,管道就被完全地删除了。对于FIFO而言,在最后一个引用FIFO的进程终止时,虽然
FIFO的名字仍保留在系统中,直至被显式地删除,但是保留在FIFO中的数据已被删除了。
缺点2. 这些IPC结构在文件系统中没有名字
优点:可靠的、流控制的以及面向记录的;它们可以用非先进先出次序处理
消息队列与全双工管道的时间比较
消息队列 全双工管道 UNIX域套接字
消息队列原来的实施目的是提供高于一般速度的IPC,但现在与其他形式的IPC相比,在速度方面已经没有什么差别了。 在新的应用程序中不应当再使用它们。
信号量、记录锁和互斥量的时间比较
如果在多个进程间共享一个资源,则可以使用这3种技术中的一种来协调访问。我们可以使用映射到两个进程地址空间中的信号量、记录锁或者互斥量
若使用信号量,则先创建一个包含一个成员的信号量集合,然后将该信号量值初始化为1.
若使用记录锁,先创建一个空文件,并且用该文件的第一个字节(无需存在)作为锁字节。为了分配资源,先对该字节获得一个写锁。释放该资源时,则对
该字节解锁。记录锁的性质确保了当一个锁的持有者进程终止时,内核会自动释放该锁
若使用互斥量,需要所有的进程将相同的文件映射到它们的地址空间里,并且用PTHREAD_PROCESS_SHARED互斥量属性在文件的相同偏移处初始化互斥量。
为了分配资源,我们对互斥量加锁,为了释放锁,我们解锁互斥量。如果一个进程没有释放互斥量而终止,恢复将是非常困难的,除非我们使用鲁棒互斥量
记录锁比信号量快,但是共享内存中的互斥量的性能比信号量和记录锁都要优越。如果我们能单一资源加锁,并且不需要XSI信号量的所有花哨功能,那么记录锁 将比信号量要好。除非特别考虑性能,才使用信号量
信号
不可靠信号和可靠信号
fork的影响
子进程继承父进程:
- 文件共享
- 世纪用户ID、实际组ID、有效用户ID、有效组ID
- 附属组ID
- 进程组ID
- 会话ID
- 控制终端
- 设置用户ID标志和设置组ID标志
- 当前工作目录
- 根目录
- 文件模式创建屏蔽字
- 信号屏蔽和安排
- 对任一打开文件描述符的执行时关闭标志
- 环境
- 连接的共享存储段
- 存储映像
- 资源限制
区别:
- fork的返回值不同
- 进程ID不同
- 这两个进程的父进程ID不同
- 子进程的tms_utime\tms_stime\tms_cutime和tms_ustime的值设置为0
- 子进程不继承父进程设置的文件锁
- 子进程的未处理闹钟被清除
- 子进程的未处理信号集设置为空集
exec的影响
从原有进程继承
- 进程ID和父进程ID
- 实际用户ID和实际组ID
- 附属组ID
- 进程组ID
- 会话ID
- 控制终端
- 闹钟尚余留的时间
- 当前工作目录
- 根目录
- 文件模式创建屏蔽字
- 文件锁
- 进程信号屏蔽
- 未处理信号
- 资源限制
- nice值
- tms_utime\tms_stime\tms_cutime以及tms_cstime值
线程
线程同步
- 互斥量
- 读写锁
- 条件变量
- 自旋锁
- 屏障
线程和信号
每个线程都有自己的信号屏蔽字,但是信号的处理是进程中所有线程共享的。这意味着单个线程可以阻止某些信号,但当某个线程修改了与某个给定信号相关的处理行为后,
所有的线程都必须共享这个处理行为的改变。
线程和fork
从父进程继承了每个互斥量、读写锁和条件变量的状态。如果父进程包含一个以上的线程,子进程在fork返回后,如果紧接着不是马上调用exec的话,就需要清理锁状体。
在子进程内部,只存在一个线程。
异步信号安全和线程安全函数
非异步信号安全: a. 已知它们使用静态数据结构 b. 使用malloc或free c. 它们是标准IO函数。标准IO库的很多实现都以不可重入方式使用全局数据结构
高级IO
记录锁
建议性锁:记录锁 强制性锁:对文件打开其设置组ID位,关闭组执行位
IO多路转接
异步IO
存储映射IO
附录
C程序的存储空间布局
高地址 | 命令行参数和环境变量
|------------------
| 栈
| 空
| 间
|------------------
| 堆
| 空
| 间
|------------------
| 未初始化的数据(bss) 由exec初始化为0
|------------------
| 初始化的数据 由exec
|------------------从程序文件
| 中读入
| 正文
|------------------
低地址