1. 进程的有哪几种状态,状态转换图,及导致转换的事件。
状态:
1)就绪状态 进程已获得除处理机外的所需资源,等待分配处理机资源,只要分配到CPU就可执行。在某一时刻,可能有若干个进程处于该状态。
2)运行状态 占用处理机资源运行,处于此状态的进程的数目小于等于CPU的数目。
3)阻塞状态 由于进程等待某种条件(如I/O操作或进程同步),在条件满足之前无法继续执行。该事件发生前即使把处理机分配给该进程,也无法运行。
转换解释:从状态转换图中,存在四种状态转换。
当进程调度程序从就绪队列中选取一个进程投入运行时引起转换1;
正在执行的进程如因时间片用完而被暂停执行就会引起转换2;
正在执行的进程因等待的事件尚未发生而无法执行(如进程请求完成I/O)会引去转换3;
当进程等待的事件发生时(如I/O完成)则会引起转换4。
事件:就绪队列非空,则一个进程的转换3会立即引去另一个进程的转换1。这是因为一个进程发生转换3意味着正在执行的进程由执行状态变为阻塞状态,这时处理机空闲,进程调度程序必然会从就绪队列中选取一个进程并将它投入运行,因此只要就绪队列非空,一个进程的转换3能立即引起一个进程的转换1。
2. 进程与线程的区别。dll是否有独立的堆栈?
进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位.
线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.
一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行
进程是死的,只是一些资源的集合,真正的程序执行都是线程来完成的,程序启动的时候操作系统就帮你创建了一个主线程。每个线程有自己的堆栈。 DLL(动态连接库)中有没有独立的堆栈,这个问题不好回答,或者说这个问题本身是否有问题。因为DLL中的代码是被某些线程所执行,只有线程拥有堆栈,如果DLL中的代码是EXE中的线程所调用,那么这个时候是不是说这个DLL没有自己独立的堆栈?如果DLL中的代码是由DLL自己创建的线程所执行,那么是不是说DLL有独立的堆栈?以上讲的是堆栈,如果对于堆来说,每个DLL有自己的堆,所以如果是从DLL中动态分配的内存,最好是从DLL中删除,如果你从DLL中分配内存,然后在EXE中,或者另外一个DLL中删除,很有可能导致程序崩溃。
另进程和程序的区别:进程即运行中的程序,从中即可知,进程是在运行的,程序是非运行的,当然本质区别就是动态和静态的区别。程序可以存在外存中,也可以存在内存中
3. 进程通信的几种方式。
管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。
有名管道 (named pipe) : 有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。
信号量( semophore ) : 信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。
消息队列( message queue ) : 消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
信号 ( signal ) : 信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。
共享内存( shared memory ) :共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号量,配合使用,来实现进程间的同步和通信。
套接字( socket ) : 套解字也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同及其间的进程通信。
4. 线程同步几种方式。(一定要会写生产者、消费者问题,完全消化理解)
临界区(CCriticalSection):通过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问。
事件(CEvent):为协调共同对一个共享资源的单独访问而设计的。
互斥量(CMutex):为控制一个具有有限数量用户资源而设计。
信号量(CSemaphore):用来通知线程有一些事件已发生,从而启动后继任务的开始。
生产者、消费者问题
Var mutex,empty,full:semaphore:=1,n,0; // 定义三个信号量
buffer:array[0,...,n-1]of item; // 定义缓冲池,容量为n
in,out:integer:=0,0;
begin
parbegin
proceducer:begin // 生产者
repeat
producer an item nextp; // 生产一个产品 .
wait(empty); // 申请一个空缓冲区
wait(mutex); // 申请缓冲池的使用权
buffer(in):=nextp; // 将产品放入缓冲池中
in:=(in+1)mod n; // 下一个空缓冲区地址
signal(mutex); //释放缓冲池使用权
signal(full); // 释放一个满缓冲区
until false;
end
consumer:begin
repeat
wait(full);
wait(mutex);
nextc:=buffer(out);
out:=(out+1)mod n;
signal(mutex);
signal(empty);
consumer the item in nextc;
until false;
end
parend
end
nextp 应该是next proceducer的意思吧
nextc 应该是next consumer
貌似也不是什么变量,属于语言描述而已
下面的消费者也是差不多的。
至于生产者进程如何被阻塞和唤醒,因为程序中有一个 repeat语句,所以进程不断测试缓冲池是否有空缓冲区,以及缓冲池是否有其他进程使用。若两个条件不满足,则进入阻塞队列等待。若某一时刻两个条件都能满足,则能唤醒该进程。
信号量:
只支持两种操作,wait()和signal(),也叫做P、V操作,