进程与线程-复习笔记

进程与线程

进程

定义

是一个程序的实例化,再加上程序计数器,寄存器和变量的值。它是对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)问题

哲学家就餐问题

读者-写者问题

posted @ 2021-12-14 09:56  shared_pointer  阅读(67)  评论(0)    收藏  举报