内容会持续更新,有错误的地方欢迎指正,谢谢!
进程与线程
概念
1.从底层cpu的角度去理解进程和线程:
- 进程和线程都是CPU工作时间段的描述,不过是颗粒大小不同。
- 进程的并发: CPU在一个时间片只能执行一个进程,当多个进程要执行时只能轮流着来,当一个进程得到CPU的临幸,相关的资源必须也已就位,然后CPU开始执行,当这个进程执行完了或者分配给它的CPU执行时间用完了,那它就要被切换出去,等待下一次CPU的临幸。进程在被切换出去的最后一步工作就是保存程序上下文环境,即下次它被CPU临幸的运行环境。
- 进程和线程: 进程A得到CPU->CPU加载A的上下文->并发执行A的a、b小段->CPU保存A的上下文。 a、b的执行是共享了A的上下文,CPU在执行时没进行上下文切换。a、b就是两个线程,a、b也在并发执行。也就是说线程是共享了进程的上下文环境的更为细小的CPU时间段。
2.从实际应用的角度去理解:
一个运行着的微信,就是一个进程。在微信的这个进程里,传输文字开了一个线程、传输语音开了一个线程。所以一个进程管着多个线程。
问题
1、进程与应用程序的区别?
应用程序是一个存储在存储空间中的静态文件,而进程是处于动态条件下由OS维护的系统资源管理实体。所以,进程就是在内存中运行的应用程序,进程是暂存的,程序是长存的。本质区别是:动态和静态特征。
2、进程和线程以及它们的关系?
进程:
进程是由程序、数据、PCB组成的。是具有一定独立功能的程序关于某个数据集合上的一次运行活动,是系统资源分配和调度的基本单位,实现了操作系统的并发(有处理多个任务的能力,但不同时;并行却可以同时)。
线程:
线程是由程序、数据、TCB组成的。是进程的子任务,是CPU调度和分派的基本单位;多个线程共享CPU实现进程内部的并发。
关系:
一个程序至少有一个进程,一个进程至少有一个线程,线程依赖于进程而存在;进程在执行过程中拥有独立的内存单元,而多个线程共享进程的内存和资源。
补充内容:进程控制块PCB:作为进程实体的一部分,系统是通过PCB感知进程的存在,包含:
- 进程标识符PID:唯一标识一个进程
- 处理机状态信息:也称为处理机的上下文,进程切换时,以确保进程从断点处开始重新执行
- 进程调度信息:进程的状态、进程的优先级、引起进程阻塞的事件等信息
- 进程控制信息:程序和数据地址、进程同步和通信机制等信息
为了管理系统中众多的PCB,常见的组织方式有两种;链接方式和索引方式。
3、线程通信的方式有哪些?(了解)
线程间的通信目的主要是用于线程同步。所以线程没有像进程通信中的用于数据交换的通信机制。
- 锁机制:包括互斥锁、条件变量、读写锁等;
- 信号量机制:信号量只能置一次初值,再P操作和V操作;
- 信号:通过通知来保持多线程同步。
4、线程有几种状态?
创建(new)、就绪(runnable)、运行(running)、阻塞(blocked)、等待(waiting)、时间等待(time waiting)、死亡(dead/terminated)。在给定的时间点上,一个线程只能处于一种状态。
线程各状态之间的转换如下:
5、Linux进程间的通信的几种方式,详细解释其中最熟悉的一到两种?
管道(pipe)及有名管道(named pipe):管道可用于具有亲缘关系的进程间的通信,数据只能单向流动;有名管道允许任意进程间的通信。
消息队列:消息队列是消息的链接表,它克服了上面两种通信方式中信号量有限的缺点。
共享内存:映射一段能被其他进程所访问的内存。这段共享内存由一个进程创建,但多个进程都可以访问,不同进程可以及时看到对方进程中对共享内存中数据的更新。这种方式需要依靠某种同步操作。
套接字:网络中不同机器之间的进程间通信,应用非常广泛。
信号:通过通知来保持多进程同步。
信号量机制:信号量只能置一次初值,再P操作和V操作。实现进程之间及同一种进程的不同线程之间的同步和互斥的手段。
6、Windows进程间通信的几种方式?(了解)
管道及命名管道、共享内存、套接字、文件映射、剪切板、邮件槽、动态连接库等
7、进程有哪几种状态、状态转换图、导致转换的事件?
就绪状态:进程已具备运行条件但未占有CPU,暂时不能运行;
运行状态:已占有CPU,在CPU上运行;
阻塞状态:等待某种运行条件(例如请求I/O而等待I/O完成等),在条件满足之前不能运行。
到运行状态的只能是就绪状态!
8、线程同步的方式?(了解)
互斥量、事件(信号)、信号量机制(信号量只能置一次初值,再P操作和V操作)
9、说出你所知道的保持进程同步的方法,并详细说说其中一两种?(了解)
- 原子操作
- 信号量机制(信号量只能置一次初值,再P、V操作。其必有公共内存,不能用于分布式操作系统,这是它最大的弱点)
- 自旋锁(保护共享资源提出的一种锁机制)
- 管程(将共享变量和对它们的操作集中在一个模块中)
- 会合(进程直接进行相互作用)
- 分布式系统等。
10、什么是临界区?如何解决冲突?
每个进程中访问临界资源的那段程序(P操作和V操作的开区间那段)称为临界区,每次只准许一个进程进入临界区,进入后不允许其他进程进入。
11、P操作和V操作、进程互斥和同步、信号量的基本概念
信号量S的物理含义 S即空闲资源总数。S>0:表示有S个资源可用;S=0表示无多余的资源;S<0时表示一个进程已进去、等待队列中的进程个数为|S|。信号量的初值都应大于等于0。
P操作、V操作
//表示申请一个资源,S减1;若减1后仍S>=0,则该进程继续执行;
//若减1后 S<0,表示已无资源可用,需将自己阻塞起来。
P(S,q)
{
S=S-1;
if(S<0)//若S>=0,该进程继续进行(不是重复执行P(S,q),而是去做它该做的)
{
insert(Caller,q);//Caller为当前进程,q为等待队列
Block(Caller);//阻塞当前进程
调度函数();
}
}
//表示释放一个资源,S加1;若加1后S>0,则该进程继续执行;
//若加1后S<=0,表示等待队列q上有等待进程,需将第一个等待的进程唤醒。
V(S,q)
{
S=S+1;
if(S<=0)
{
Remove(q,pid);//pid是进程ID
Wakeup(pid);
}
}
互斥:两个进程具有临界资源。例如:打印机、交通十字路口
同步:两个进程需要协作。例如:司机与售票员、生产者与消费者、作者与读者
三种信号量:
1.互斥信号量:把信号量视为一个加锁标志位,实现对一个共享变量的互斥访问。
mutex的初始值为1
P(mutex);
访问该共享数据
V(mutex);
初值一般为 1。它根据临界资源的类型的数量来设置的,有几种类型的临界资源就设置几个互斥信号量;但不管有多少进程,一种临界资源类型只用设置一个互斥量,代表一次只允许1个进程访问这个临界资源。
2.同步信号量:把信号量作为进程间的同步工具
临界区C1;
V(S);
P(S);
临界区C2;
初值一般为 0。它是根据进程的数量设置的,有几个进程就设置几个同步信号量,表示该进程是否可执行,或表示该进程是否执行结束。
3.共享资源的剩余个数:把信号量视为是某种类型的共享资源的剩余个数,实现对一类共享资源的访问。
P(resource); // resource的初始值为该资源的个数N
使用该资源;
V(resource);
互斥和同步实现的一些规则:
- 用于实现互斥或同步的PV必须成对出现;
- 当为互斥时,P和V在同一个进程;若有两个进程,当为同步时,两对P和V交叉出现在这两个进程中;
- 若同一进程中同时存在互斥和同步,必须先执行对同步信号量的P操作,但对V操作没要求。
互斥、同步的解题方法:
1) 关系分析。分析进程之间的同步和互斥关系。
2) 整理思路:写出代码逻辑流程。
3) 设置信号量。根据上面两步,设置需要的信号量,确定初值。
12、生产者和消费者问题?
问题描述:一群生产者向一群消费者提供产品,共享一个大小为n的初始为空的缓冲区。要求:不能同时存和取;当缓冲区为空时不能取,当缓冲区为满时不能存。
1) 关系分析:由于缓冲区不能同时存取,两者对缓冲区的操作为互斥关系;由于生产者存后消费者才能取,两者还有同步关系。
2) 整理思路:生产者先同步P,再互斥P,再存,再V;消费者同理。
3) 设置信号量:mutex=1为互斥量;由于有两个进程,所以有两个同步信号量,empty=n为缓冲区中空位的个数,num=0为缓冲区中产品的个数。
Producer_i()//i=1...m
{
while(1)
{
Producing;//生产产品
P(empty);
P(mutex);
Save the produce;//存
V(mutex);
V(num);
}
}
Consumer_j()//j=1...k
{
while(1)
{
P(num);
P(mutex);
Get the produce;//取
V(mutex);
V(empty);
Consumer the produce;//消费掉
}
}
13、哲学家就餐问题?
题目描述:5个哲学家坐一桌就餐,要么思考要么就拿起筷子吃饭,但桌上只有五根筷子,大家都会先拿起其左手方的筷子,如图:
1) 关系分析:五个哲学家分别对其周围的两个人关于筷子的使用互斥。
2) 整理思路:对每个哲学家而言,先通过P控制其左手的那支筷子,然后发生死锁。。
3) 互斥量:一个含有五个元素的互斥量数组mutex[i]=1(i=1,2,3,4,5)
但是我们可以增加一个互斥量stopOther=1,stopOther的作用是:某个哲学家在取筷子前用P(stopOther)获得互斥量以阻止其他哲学家拿筷子,直到这位拿了两支筷子就V(stopOther)了。
int stopOther=1;
int mutex[5]={1,1,1,1,1};
People_i()//i为i号哲学家
{
P(stopOther);//在取筷子前获得互斥量
拿起左手方的筷子;
P(mutex[i]);
P(mutex[(i+1)%5]);
V(stopOther);
吃饭;
V(mutex[i]);
V(mutex[(i+1)%5]);
思考;
}
//如果不加stopOther这个互斥量就会发生死锁。
14、什么是死锁?死锁产生的条件?死锁处理的常用方法?
两个或多个进程无限期的阻塞、相互等待的一种系统状态。
死锁产生的四个必要条件:
- 互斥条件:至少有一个资源一次只能被一个进程使用,其他进程申请该资源,必须等到该资源被释放;
- 占有条件并保持请求:占有至少一个其他进程需要的资源,并申请得到在其他进程的资源;
- 环形条件:进程之间形成头尾相连的环形等待资源的关系;
- 非抢占条件:进程资源不能被抢占,只能被该进程资源释放。
死锁处理的常用策略:
- 预防死锁:确保死锁发生的四个必要条件中至少有一个不成立,就能预防死锁的发生;
- 避免死锁:动态地检测资源分配状态,以确保循环等待条件不成立;
- 检测和解除死锁:允许死锁发生,但可通过检测机制及时检测出与思索有关的进程,终止一些进程以回收一些资源。
- 鸵鸟策略
15、操作系统中进程调度策略有哪几种?
- 先来先服务先请求先分配得到CPU
- 最短作业优先:忽视了作业的等待时间
- 优先级:优先级(静态+动态优先级)越高越先分配得到CPU
- 高响应比优先:响应比=(等待时间+运行时间)/运行时间
- 时间片轮转: 以时间片为单位轮流使用CPU
- 多级反馈队列:集合了前几种算法的优点,若某进程使用了过多CPU时间,那它会被转移到更低的优先级队列;在较低优先级队列等待时间过长的进程会被转移到更高优先级队列。
16、介绍一下孤儿进程、僵尸进程和守护进程?
孤儿进程:一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被系统回收,实际是不占用资源的。
僵尸进程:一个进程使用fork创建子进程,如果子进程退出,该子进程都会把自己的进程信息发给父进程,父进程收到信息后都会很快地来处理掉,所以每个子进程都有成为僵尸进程的时候。若父进程没响应子进程发的信息,那么僵尸进程将占用一个进程ID号,对系统是一种危害。
守护进程:一类在后台运行的特殊进程,用于执行特定的系统任务。大多数守护进程在系统启动时启动,并且一直运行到系统关闭。
17、系统感知进程的唯一实体是
PCB(进程控制块)可看成 进程的上下文,是进程的标志。
PCB(pid+status+优先级+堆栈+进程通信机制等等)+程序(代码+数据)=进程
18、同步和异步的区别
先了解阻塞和非阻塞:进程/线程要访问的数据是否就绪,进程/线程是否需要等待;
同步:直接制约而互相发送消息而进行互相合作、互相等待,使得各进程按一定的速度执行的过程称为进程间的同步。
实例:
同步就是你叫我去吃饭,我听到了就和你去吃饭;如果没有听到,你就不停的叫,直到我告诉你听到了,才一起去吃饭。
异步就是你叫我,然后自己去吃饭,我得到消息后可能立即走,也可能等到下班才去吃饭。
同步,异步:访问数据的方式,同步需要主动读写数据,在读写数据的过程中还是会阻塞;异步只需要I/O操作完成的通知,并不主动读写数据,由操作系统内核完成数据的读写。
19、协程和多线程的区别
协程又称微线程,在Lua和C#中得到了广泛地应用。
协程的特点在于是一个线程执行,那和多线程比,协程有何优势?
- 最大的优势就是协程极高的执行效率。因为协程可以在用户空间内切换上下文,不再需要陷入内核来做线程切换,从而降低了CPU的消耗。
- 第二大优势就是不需要多线程的锁机制。因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁,只需要判断状态就好了,所以执行效率比多线程高很多。