操作系统——进程和线程


进程五个状态:创建、就绪、阻塞、运行、结束(阻塞挂起状态、就绪挂起状态)

PCB(保存进程切换时的相关信息,以便进程重新执行从断点处执行)

进程和线程的区别:

(1)常见的说法。进程是资源分配的最小单位,线程是资源调度的最小单位。

(2)从资源角度。进程拥有一个完整的资源平台,线程只独享必不可少的资源,如寄存器和栈。

(3)从状态角度。线程同样有就绪、阻塞、运行三种基本状态,同样有状态转换。

(4)从时间和空间开销角度。线程能减少开销。线程创建时不涉及资源管理信息,而是共享他们。释放时释放的资源比较少。切换时不切换页表。通信时共享资源,无需经过内核耗时。

进程切换有非抢占式调度和抢占式调度。

进程通信问题如下。

(1)管道。匿名int pipe(int fd[2])只存在内存,不在文件系统中,只能在相关进程如父子间通信,只有单向通信,双向就要两个管道。父进程fork子进程才有两个f[0]和两个f[1]。有名mkfifo,可以在不相关通信。

效率低,不适合进程间数据频繁交换。

(2)消息队列:考虑用户态和内核态之间的数据拷贝耗时。

(3)共享内存:虚拟内存的一块,不用拷贝,但是带来数据混乱问题。

(4)信号量:解决数据混乱问题,整型计数器表示资源个数(PV操作),实现互斥1和同步0,不用于缓存通信之间的数据。

(5)信号:异常工作通知,SIG。

(6)socket:TCP字节流SOCK_STREAM,UDP数据包SOCK_DGRAM,本地socket。

线程同步问题如下。

互斥用锁或信号量,同步用信号量。

生产者消费者问题。需要互斥:任何时候只能有一个线程操作缓冲区,说明缓冲区时临界代码。需要同步:缓冲区为空的时候,消费者必须等待生产者生产数据;缓冲区满的时候,生产者必须等待消费者取出数据。使用互斥信号量实现。

哲学家就餐问题。方案一:使用信号量PV,有可能五位哲学家同时拿起叉子,死锁。方案二:一个哲学家进入临界区准确拿起筷子,另一些不能动,可以,但是不能两人同时进行。方案三:采用奇偶分支结构,偶数编号的哲学家先拿左边的叉子再拿右边的,奇数编号的哲学家先拿右边的叉子再拿左边的。

读者写者问题。读优先、写优先、公平读写策略。

死锁:互斥条件、占有并等待条件、不可剥夺条件、循环并等待条件(避免:资源有序分配)。

互斥锁、自旋锁:申请锁失败后的处理方式不同。互斥锁要上用户和内核之间下文切换,自旋锁适用于执行时间较短的。

读写锁:写锁是独占式的,类似互斥锁和自旋锁。读锁是共享式的。

上述都是悲观锁。悲观和乐观的区别在于多线程同时修改共享资源的概率不同。

乐观锁是无锁编程,多人在线文档编辑、SVN、git,通过版本号。

加锁时注意:加锁粒度小、执行速度快、加合适的锁。