进程与线程-复习笔记
进程与线程
进程
定义
是一个程序的实例化,再加上程序计数器,寄存器和变量的值。它是对CPU的虚拟化,让用户感觉可以多个进程“同时”运行,也就是伪并行。目的是方便用户使用。进程是系统调度的基本单位。
守护进程:停留在后台运行的进程,比如说电子邮件,web页面等。
进程的创建
在UNIX系统中,可以通过fork()来进行进程的创建。创建的时候子进程和父进程拥有相同的内存镜像,同样的打开的文件。然后子进程通过execve()或者一个类似的系统调用修改内存镜像来进行程序的运行。
在Windows系统中,则可以通过WIN32中的系统调用CreateProcess()来进行进程的创建和装入新的进程。
Unix系统中,父进程和子进程的可读部分地址空间是相同的,即是共享的,而可写的部分地址空间是不同的,不可共享。
Windows系统中,父进程和子进程的地址空间从一开始就是不同的。、
进程的终止
unix系统中,kill命令,exit()进程的结束
进程的状态
版本1:运行,就绪,阻塞
版本2:运行,就绪,阻塞,挂起(sleep()系统调用)
状态之间的转化(口述)
进程控制块(PCB)
包括程序计数器,堆栈指针,打开的文件状态,PID,所属的组别,父进程等等
中断发生的步骤
保存程序计数器的值,将中断向量压入程序计数器中;保存堆栈寄存器中的值,设置新的堆栈地址。等待操作系统调度
线程
定义
线程是资源分配的基本单位,同一进程下的线程共享地址空间,打开文件的状态等等,但是每个线程都拥有自己独立的堆栈,程序计数器,寄存器,线程状态。线程比进程更加轻量,更容易撤销,切换开销也没有进程的大。
线程的状态
和进程类似,有运行,阻塞,就绪和终止四个状态。
线程的创建
Unix系统中,pthread_create(),返回的是一个线程标识符,也可以理解为线程的名字。pthread_exit()表示线程的终止。pthread_join()则是对系统阻塞其它线程,直到指定的线程退出。还有一个就是pthread_yield(),此函数是让出CPU,让其它线程来占用CPU。
用户级线程和内核级线程
用户级线程将线程表(即程序计数器,堆栈指针,寄存器,线程状态等)中的数据存放在用户空间,而内核级线程是将线程表中的数据存放在内核空间。
用户级线程缺点:当页面发生缺页异常时,内核会将进程阻塞一直到I/O设备完成为止。
当一个线程正在运行时,其它线程不得抢占,必须等待正在运行的线程主动让出CPU,否则没有机会运行。
内核空间的优点:解决了部分用户级线程的缺点。
进程之间的通信(Inter Process Communication)(IPC)
竞争条件定义
两个或多个进程读写共享资源时,最后结果取决于进程的时序。
临界区定义
对共享区域的访问的数据片段称为临界区
忙等待的互斥
屏蔽中断
一个进程进入临界区时,设置中断屏蔽位,时钟中断也屏蔽,一直等到该进程运行结束
锁变量
严格轮转法(自旋锁,忙等待)
Peterson解法 >>>>> 生产者和消费者问题
TSL指令
睡眠与唤醒
信号量解决生产者和消费者问题:full,empty,mutex
主要还是顺序问题(以下伪代码)
producer:
{
down(empty);
down(mutex);
enter_critical_region();
up(mutex);
up(full);
}
consumer:
{
down(full);
down(mutex);
enter_critical_region();
up(mutex);
up(empty);
}
可以通过使用互斥量和条件变量来实现信号量的功能
互斥量就是简易版的信号量,不需要信号量的计数功能。进入临界区需要锁住相关的互斥量,成功了才得以进入临界区。
条件变量就是没有将满足条件的线程阻塞。通常和互斥量一起使用。条件变量不像信号量存储在内存中,信号量存储在内存中,有丢失的风险。
条件变量和信号量解决生产者消费者问题
以下为伪代码:
producer:
pthread_mutex_lock(&mutex); //只允许一个线程访问临界资源
if(false)
pthread_cond_wait(&producer,&mutex); //条件不满足,将该线程阻塞,并释放互斥量
else
{
pthread_cond_signal(&consumer,&mutex); //条件满足,发送信号给consumer(),并释放互斥量
pthread_mutex_lock(&mutex);
}
consumer:
pthread_mutex_lock(&mutex); //只允许一个线程访问临界资源
if(false)
pthread_cond_wait(&consumer,&mutex); //条件不满足,将该线程阻塞,并释放互斥量
else
{
pthread_cond_signal(&producer,&mutex); //条件满足,发送信号给producer(),并释放互斥量
pthread_mutex_lock(&mutex);
}
管程
管程是编程语言的组成部分,能够保证任意时刻只能有一个活跃进程,能够有效地完成互斥。当一个进程调用管程程序时,会检查有没有活跃进程,如果有则该进程则被挂起,直到活跃进程退出管程过程。
调度
定义
简单理解就是操作系统决定下一次哪个进程即将要被CPU运行,并保存相关的数据。
非抢占式调度算法
非抢占式调度算法就是挑选一个进程运行,然后直到该进程被阻塞,或者直到该进程自动释放CPU。
吞吐量:系统每小时完成的作业数
周转时间:作业提交时刻开始直到该作业完成时刻。
响应时间:从作业提交开始直到作业被CPU运行。
调度算法
批处理系统中的调度
先来先服务(FIFO)
最短作业优先(SJF)
最短剩余时间优先
交互式系统中的调度
轮转调度
优先级调度(低优先级的进程会出现“饿死”的情况)
多级队列:实际上是轮转调度和优先级调度的结合体。最高优先级的进程运行完指定的时间片以后,会降低一个优先级。
最短进程优先
线程调度
分为用户级线程和内核级线程
用户级线程:只要此进程还有时间片,因为内核不知道有线程这个概念,所以线程运行任意多少时间,直到该线程让出CPU。
内核级线程:和进程调度类似
两者最大的区别就是性能方面。
经典的进程间通信(IPC)问题
哲学家就餐问题
读者-写者问题

浙公网安备 33010602011771号