分页:每一页的大小由硬件决定,或硬件支持多种大小的页,由操作系统决定页的大小。同一时刻只能选择一种页大小,所以对整个系统来说,页就是固定大小的。目前大部分是4KB页。
线程thread、有时也称轻量级进程lightweightprocess LWP,是程序执行流的最小单位,一个标准的线程由线程功、当前指令指针(pc)、寄存器集合和堆栈组成
一般把频繁等待的线程称为IO密集型(IObound thread)线程,而把很少等待的线程称为CPU密集型线程,IO密集型总是比CPU密集型容易得到优先级的提升
Linux将所有的执行实体(无论线程、进程)都称为任务(task),每个任务类似于一个单线程的进程,具有内存空间、执行实体、文件资源等。Linux用以下方式可以得到一个新任务:
系统调用 作用
Fork 复制当前进程
Exec 使用新的可执行映像覆盖当前可执行映像
Clone 创建子进程并从指定位置开始执行
Fork产生新任务速度非常快,因为fork不复制原任务的生存空间,而是与原任务共享一个写时复制(copy on write,cow)的内存空间,所谓写时复制,指的是两个任务可同时自由的读取内存、但任一任务试图对内存修改时,内存会复制一份供其使用
Fork只能产生任意的镜像,因此须配合exec才能启动别的新任务
在fork产生新人物后,新任务可调用exec来执行新的可执行文件
Fork、exec通常用于产生新任务,要产生新线程可以使用clone
我们把单指令的操作称为原子的(atomic),因为单指令的执行不会被打断
为避免出错,许多体系结构提供操作的原子指令,如i386有inc指令可以直接增加一个内存单位值。Windows有一套api专门用于进行原子操作,称为interlocked api
二元信号量(binary semaphore)是最常见的一种锁,只有两种状态:占用与非占用
对于有许多个线程并发访问的资源,多元信号量简称信号量(somaphore)。一个初始位为N的信号量允许N个线程并发访问
互斥量(Mutex)和二元信号量类似,不同点在于同一个信号量可以被A线程获取,B线程释放,而互斥量要求获取和释放的是同一个线程
临界区(critical section)是比互斥量更严格的同步手段。区别在于,互斥量和信号量在系统的任何进程里都是可见的,而临界区的作用范围仅限于本进程
读写锁(read-write lock)致力于一种更加特定的场合的同步。对于同一个锁,读写锁有两种获取方式,共享的(shared)或独占的(exclusive)
条件变量(condition variable)作为一种同步手段,作用类似于栅栏,当条件变量被唤醒时,所有的线程可以一起恢复执行
可重入(reentrant):一个函数可重入,表示这个函数的有执行完成,由于调用有一次进入函数执行,可重入是并发安全的保障,一个可重入的函数可以在多线程环境下放心使用,因为可重入函数重入之后不会产生任何不良后果
过度优化:CPU发展出了动态调度,在执行程序的时候为了提高效率有可能交换指令的顺序;编译器在进行优化时,也可能为了效率交换不相干的两条相邻指令的执行顺序
可以用关键字volatile阻止过度优化,使得:
1. 阻止编译器为了提高速度将一个变量缓存到寄存器内而不写回
2. 阻止编译器调整操作volatile变量的指令顺序
现在不存在可移植的阻止换序的方法,通常情况下调用CPU提供的一条指令(常被称为barrier)一个barrier指令会阻止CPU将该指令之前的指令交换到barrier之后
多线程内部情况:
用户实际使用的线程并不是内核线程,而是处于用户态的用户线程
用户态线程不一定在操作系统内核里对应同等数量的内核线程