1. 进程:
(1)进程模型:一个进程就是一个程序的执行实例,程序是静态的,进程是动态的。一个进程有一个地址空间和一个控制线程,其中地址空间包含有:程序计数器、寄存器、变量的当前值。当一个进程被挂起时,进程的物理程序计数器值被保存在该进程的程序计数器中。下次进程运行时,再从程序计数器中取出计数值装入内存的程序计数器中。
(2)进程的创建:在unix系统中,创建新进程的方式只有一个:fork()函数,即创建一个子进程。子进程是父进程的一个副本,和父进程拥有相同的存储映像、相同的环境字符串和相同的打开文件。但是,子进程和父进程有各自不同的地址空间,不同的PID。通过系统调用execve()函数,可以替换地址空间中的程序段。(ps:子进程和父进程拥有不同的地址空间,但地址空间中的内容相同)
(3)进程的三种状态:运行态、就绪态、阻塞态。(ps:系统调用pause()可以使进程进入阻塞态)
(4)多进程的实现:操作系统维护着一张进程表,每个进程占用一个表项。该表项包含着进程状态的重要信息,包括:寄存器、程序计数器、堆栈指针、内存分配状况、打开文件的状态、调度信息、从运行态转为就绪态或阻塞态时所保存的信息(程序计数器值和寄存器中的相关信息)。当内核切换进程时,会将旧进程的信息装入进程表,保证下次该进程能正确启动,然后载入新进程的程序计数器和寄存器等相应信息到内存中,从而切换到新进程。
(5)多进程的设计模型:当一个进程从运行态转为就绪态或阻塞态时,会发生中断,中断硬件将程序计数器、程序状态字、一个或多个寄存器放入进程表中,然后跳转到中断向量所指示的地址,载入程序计数器和寄存器相关值,从而开始执行另一个进程。
2. 线程:
(1)线程模型:一个线程就像一个分离的进程,它运行在进程的上下文中,多个线程共享该进程的虚拟地址空间和其中所有可用的数据,但是每个线程都有自己独立的寄存器,堆栈空间,程序计数器,状态。多个线程各自独立地进行在同一个进程中。
(2)线程的优势: ①便于设计 ②轻量级,容易创建和撤销 ③用户态的多线程切换速度快,性能高
(3)进程和线程的联系:进程用于把资源都集中一起,而多个线程则运行在进程的上下文中,共享进程的资源,是被CPU调度执行的实体。(ps:线程是不安全的,一个线程可以修改其他线程的堆栈空间,其他线程也可以访问某个线程打开的文件)
(4)POSIX线程:一个线程包,其中主要的函数调用有:
Pthread_create 创建一个新线程
Pthread_exit 结束调用的线程
Pthread_join 等待一个特定的线程退出
Pthread_yield 释放CPU来运行另外一个线程
Pthread_attr_init 创建并初始化一个线程属性结构
(5)多线程实现方式:多线程的实现方式一般有两种,用户态实现和内核态实现。
- 用户态线程:整个线程包放入用户空间,内核对此一概不知。 当内核分一个时间片给某一进程时,进程根据进程中的线程表和自己定制的调度算法对多个线程进行调度运算,直到时间片结束为止。
(ps①:线程表和进程表类似,包含重启该线程的信息,即:每个线程的程序计数器、堆栈指针、寄存器和状态等)
(ps②:通过pthread_yield对线程调度时,先把线程信息存入线程表,进而调用调度程序选择另一个线程)
用户态线程的优缺点:
优点: 1. 保存线程状态和调度程序都是本地过程,允许每个进程有自己定制的调度算法。
2. 用户级线程没有系统调用和上下文切换,不需要对内存的高速缓存进行刷新,所以用户线程调度效率比内核线程高出一个数量级。
缺点: 1. 当进程中某个线程发生阻塞时,进程中的其他线程都会一起阻塞(ps:select调用可以预检测阻塞)
2. 当进程中的一个线程运行时,其他线程无法运行,除非该线程运行结束或强制终止。由于进程内部没有时钟中断,无法切分时间片,所以不能用轮转调度的方式调度线程。
-
内核态线程:整个线程包放入内核中,这样内核维护两张表:进程表和线程表。当内核分好时间片后,由内核根据线程表和调度算法自动地进行线程的调度。
(ps:内核视所有的线程为平等的,统一对不同进程的所有线程进行调度。当一个线程阻塞时,内核可能运行同一进程中的线程,也可能运行不同进程中的线程)
内核态线程的优缺点:
优点:1. 内核可以时钟中断,防止某一线程运行时间过长(时间片切换:定时到了之后线程自动切换)
2. 所有阻塞线程的调用都以系统调用的形式实现,防止某一线程阻塞造成该进程所有线程阻塞。
缺点: 需要完整的上下文切换,修改内存映像,清除内存中高速缓存的内容。这些导致了若干数量级的延迟,降低了性能。