前引
本系列为博主更深入学习OS,做一些初步的理论铺垫,主要针对一些比较难的点
操作系统内核
内核是真正与硬件交互的那部分软件,与硬件交互包括读写硬盘、读写网盘、读写内存以及任何连接到系统中的硬件。除了与硬件交互外,内核还负责分配资源,比如CPU时间、内存、IO等等,这些都是资源。
内核的职责就是以进程的形式来分配CPU时间,以虚拟内存的形式来分配物理内存,以文件的形式来管理IO设备。
只有一个内核实际上是做不了什么真正有用的事情,内核是给人用的,为了与内核交互,发明了命令行以及图形界面GUI,就形成了操作系统
进程与线程的区别
进程是运行中的程序,线程是进程的内部的一个执行序列
进程是除CPU之外的系统资源的分配单元,线程是调度、执行的单元 ⟶ \longrightarrow ⟶系统资源应理解为硬件为其服务的时间,如CPU的时间片
进程间切换代价大,线程间切换代价小
进程拥有资源多,线程拥有资源少 ⟶ \longrightarrow ⟶ 进而线程切换时空开销少,解决进程切换麻烦的问题,这正是线程提出的意义
多个线程共享进程的资源
进程的互斥与同步
1 生产者与消费者
关系分析: 两者在对缓冲区的访问上互斥(一次只能有一个进程访问临界资源),在消息传递上同步(协同合作)
思路: 生产者需要空缓冲区P(empty)
、对缓冲区的访问P(mutex)
,提供满缓冲区V(full)
;消费者需要满缓冲区P(full)
、对缓冲区的访问P(mutex)
,提供空缓冲区V(empty)
信号量(记录资源情况的变量/结构):
mutex 缓冲区访问互斥锁
empty 空缓冲区资源数量
full 满缓冲区资源数量
typedef int semaphore;
semaphore mutex = 1; // 互斥信息量,初值为 1
semaphore full = 0; // 同步信号量,满缓冲区 初值为 0
semaphore empty =6; // 同步信号量,空缓冲区 初值为 n
void P(semaphore S)
{
while (S <= 0);
S--;
}
void V(semaphore S)
{
S++;
}
void Productor()
{
P(::empty);
P(mutex);
// product
V(mutex);
V(full);
}
void Consumer()
{
P(full);
P(mutex);
// consume
V(mutex);
V(::empty);
}
2.复杂的生产者与消费者(盘子里放水果,拿水果)
关系分析: Dad和Mom对盘子的访问为互斥,Dad与Daughter,Mum与Son为两对同步关系,Daughter和Son显然没有关系
思路: Dad在盘子放入苹果后,Daughter必须从盘子中拿走苹果,这两个动作必须连贯执行。Mon与Son同理
信号量:
mutex 盘子访问互斥锁
apple 苹果资源数量
orangle 橘子资源数量
typedef int semaphore;
semaphore plate = 1;// mutex lock
semaphore apple = 0;
semaphore orange = 0;
void P(semaphore& S) // 申请资源
{
while (S <= 0);
S--;
}
void V(semaphore& S) //释放资源
{
S++;
}
void Dad()
{
while (1)
{
P(plate);
// put an apple
V(apple);
}
}
void Daughter()
{
while (1)
{
P(apple);// take an apple
V(plate);
}
}
void Mum()
{
while (1)
{
P(plate);
// put an orange
V(orange);
}
}
void Son()
{
while (1)
{
P(orange); // take an orange
V(plate);
}
}
3 读者与写者
关系分析: 写者与写者,写者与读者为互斥关系,读者与读者为同步关系(非互斥关系更合理)
思路: 写着申请占有共享文件P(mutex)
,写完后释放共享文件,涉及一个互斥锁变量 mutex
。读者情况较复杂,因为要做到与写者互斥,并与读者同步,为此引入计数器counter
记录读者数量:对首个读者,初始counter ==0
,要申请占用共享文件P(mutex)
;最后一个读者退出时,counter ==0
,要释放共享文件V(mutex)
。显然,对counter
变量也是一个临界资源,因为一次只允许一个进程修改counter
值。
信号量:
mutex 共享文件互斥锁
r 计数器互斥锁
typedef int semaphore;
semaphore mutex =1 ;
semaphore r = 1 ;
int counter = 1 ;
void P(semaphore S)
{
while (S <= 0);
S--;
}
void V(semaphore S)
{
S++;
}
void Writer()
{
while (1)
{
P(mutex);
// write shared documents
V(mutex);
}
}
void Reader()
{
while (1)
{
P(r);// 访问counter
if (counter == 0)
P(mutex);
counter++;
V(r);
// read
// read over
P(r);
counter--;
if (counter == 0)
V(mutex);
V(r);
}
}