漫谈操作系统4 -- 基础知识(进程和线程/任务)

来源:互联网 发布:mac口红在澳洲是什么价 编辑:程序博客网 时间:2024/06/03 17:07

接着前一篇博文,接着讲解操作系统的基本知识,这次集中在操作系统中进程和线程的概念上,虽然已有很多书籍和文章在讲进程和线程的定义和概念,但是个人感觉这个属于操作系统中最核心的部分,还是有必要单独拎出来再讲一下,当然也希望自己能够讲出一些新意,而不是老生常谈。


为了解释进程和线程的概念首先需要解释清楚程序的不同表征状态(比较恶心表征这个词,但是没办法)

我们缩写的源代码比如C/C++的代码,经过编译器翻译成可执行文件之后,这个可执行文件我理解就是程序。可执行程序有不同的格式,比如常见的格式 是Linux的ELF格式,还有windows的PE格式,他们都是可执行文件。而可执行文件由于格式的不同所以对应的在操作系统的内核中有不同的可执行文件加载器来进行解析并加载运行。

而一般情况下认为保存在磁盘上的可执行文件是程序,而如果把程序运行起来之后,其运行的状态会是一个进程。所以进程是可执行程序的动态表征。


下面开始讲可执行程序动态表征里的两个概念:


1. 进程

在早期的操作系统的概念里进程是最小的执行单位和资源单位,也就是说进程定义了一个程序在运行时拥有的资源,其中包括内存空间, 打开文件描述符表(打开文件句柄), 各种权限, PID ...... 于此同时此进程在操作系统内核中也记录了当前代码运行的上下文状态。 

由于对称多处理器的兴起,后来出现了多线程编程的概念,此时大部分的操作系统内核都将进程抽象为只表示资源的概念,对于Linux系统第一个内核中的进程描述结构体包含了进程运行时的系统资源占用情况和进程描述,也包含了进程的主运行逻辑上下文。


Linux的进程和线程都使用task_struct结构体在内核表示,而又都需要一个thread_info表示运行的上下文,个人觉得实际上是一种不好的方法,浪费了task_struct结构体,并且会造成别人的误解,以为线程和进程是等效的概念(当然会看内核代码的人应该不至于弄不明白这个)


而对于FreeBSD系统,它会有单独的主线程描述结构和进程表述结构,而进程描述结构体只包含了资源占用和进程描述的情况,而主线程结构体包含了主程序的运行上下文。


FreeBSD的进程描述结构,其包括一个尾队列的线程描述结构体,所以对于FreeBSD来说在内核中进程就是进程,线程就是线程泾渭分明。 而当程序通过execv/fork来创建新的进程时会直接创建主线程,并运行主线程逻辑。


2. 线程

上面讲了进程是操作系统内核中的资源占用的概念,下面就可以讲实际的运行状态概念了,其实内核中对运动状态的描述有一个专用名词叫做调度实例。线程在内核中的结构体主要描述了操作系统内核对其描述的调度状态(ready, suspend, runnung),运行的上下文(硬件体系结构相关)。 操作系统内核的调度器部分主要操作的数据都集中在这个数据结构之上,内核围绕线程来进行分时复用处理器资源。


这里需要说明的一点是,此处的thread指的是内核线程,而我们在POSIX标准C接口中使用的pthread_*函数族是其用户态的实现对于Linux操作系统来说其通过clone系统调用来创建pthread_*对应的内核调度实例。 在早期的pthread_*函数族实现中有N:1, N:M的实现,其表示N个用户态的线程共享一个内核调度实例,其实现是在内核中的调度实例之上在用户态再对其进行分片,从而达到在用户态调度多个用户态线程共享一个内核态时间分片的目的。

但是当前的主流pthread_*都已经更改为1:1线程也就是一个用户态线程对应一个内核调度实例。


3. 其他

很多嵌入式操作系统都没有像FreeBSD/Linux这么详尽的实现线程和进程的概念,对于只运行在内核态并且没有MMU的内核往往都只有一个线程概念,兼顾的在其中有一些特殊的标记表明有限的资源。 对于微内核系统来说thread或者说task也是一个内核的概念,因为分时复用CPU资源是操作系统最重要的功能之一,所以微内核系统的进程空间等都在用户态进行描述,但是其调度实例一定是在内核态存在的。

所以线程或者调度实例的概念是操作系统中的一等公民,不论系统如何演变,其都会存在在内核中。




原创粉丝点击