电子说
No.1
执行流
这里先说一说执行流,有助于线程的理解。
程序计数器中的下一条指令地址组成的轨迹称为程序的执行流。执行流是逻辑上独立的指令区域,是人为给处理器安排的处理单元。指令指导处理器的执行方向,从处理器的角度看,执行的指令形成一条路径,称为执行流。执行流可大可小,可以是整个程序文件,也可以是一个函数。
一个代码段想要突然去执行另外一个代码段的指令,比如call指令或者因中断去执行中断处理程序,只要先将调用前或中断前的上下文环境保存好就可以在iret或中断返回后继续执行原代码段的指令。所以说当我们为任何一段指令提供它所需要的上下文环境,那么这段指令就可以在独立的上CPU运行,也就是说这段指令成为了一个单独的执行流。这里说的上下文环境指的是指令所使用的寄存器映像、栈、内存等资源。可以独立在CPU上运行的代码段,哪怕被中断也可以返回继续执行,因为它所需要的资源得到了维护。
在任务调度器的眼里,执行流是调度单元,即处理器上运行的每个任务都是调度器分配的执行流。换句话说,实现任务调度,就是换不同的执行流在CPU上运行。我们要说的线程就是一个执行流。进程和线程有很多相似的地方,当一个进程中只有一个线程时,我们称之为单线程进程,它比线程就只多了处理的资源。我们可以认为线程和进程都是由执行流实现的。
No.2
线程
回想创建线程的过程,我们先声明并定义一个函数作为线程的处理函数,该函数的返回值为void*参数也是void*,然后调用pthread_create()函数创建线程。可以理解为线程就是去执行一个函数,但线程和普通的函数的区别在于线程拥有独立的上下文环境成为了独立的执行流,也就成为了独立的调度单元,可以独立在CPU上运行。在一般的函数调用中,函数随着程序的执行流被顺便执行。给每个执行流分配的时间是有限的,一个普通函数要等到该它运行的时候才可以在CPU上运行,前面有再多的函数它都要等着,还没有到它运行的时候可能该执行流就被换下CPU了。而线程则因为成了单独的执行流,可以独自享用分配的CPU时间,这才是线程真正优势的地方。
只有理解了线程的优势,在使用线程的时候才能恰到好处,现在再回想自己写的多线程程序是否真的需要使用多线程。将要处理的单独一类事件放在一个执行流等待就好了,没有必要写成多线程,在调度器调度的时候反而会花费额外的时间。
线程是一套机制,给一段代码块构建它依赖的上下文环境,从而让代码块称为单独的执行流,也就成为了调度器的调度单元可以直接在CPU运行。
线程中调用的函数让所运行的函数以调度单元的身份独立运行在CPU上,当函数运行时,可以让程序中多个函数(执行流)以伪并行的方式运行,为程序提速。
No.3
线程与进程
进程是运行中的程序。对于处理器来说,进程是执行流的集合,至少包含一个执行流,执行流之间相互独立,但它们共享进程的所有资源。
在Linux早期版本(Linux 0.11),其中并没有操作系统书籍说到的有关线程的代码,比如thread_info结构体和创建线程的函数。那时CPU调度的单元是进程,进程就是各个执行流(调度单元),这里想说明的是进程和线程都是概念上的。在线程出现之前依然能够实现并发处理,线程在进程的基础上实现了二次并发,目的是提高效率。进程与线程的区别,一个是上面所说的进程中可以有多个线程。第二个就是线程没有自己的资源,没有自己的地址空间,必须要依附于进程的地址空间中才可以运行。
No.4
进程线程的状态
上面说了进程和线程是概念上的,真正实现时都是人为创造的代码块,因此执行流的状态也是人为划分的。比如因为有的线程在读写磁盘时需要等待,那么就需要该线程为阻塞状态,当线程可以上CPU运行时该线程就叫就绪态,在CPU运行时就称为运行态。在有其他需求的时候可能还会由别的状态出现,只要合理就可以,说明状态都是因为某种需求而出现的,然后当状态满足后就说明线程符合了某些条件,比如线程由阻塞态变为就绪态说明现在线程可能正在等待的资源已经等到了可以上CPU运行了。
No.5
程序控制块PCB
PCB(Process Control Block)是进程的身份证,记录了与进程相关的所有信息,比如进程状态、PID、优先级等。每个进程都有自己的一个PCB。所有PCB放到一张表格中维护,就是进程表,调度器根据这张表选择上处理器运行的进程。PCB的内容取决于操作系统功能的复杂程度。PCB可以确定处理器要执行的任务,记录程序运行时所需要的数据资源、给任务分配的时间大小、上下文信息的存储地址、进程状态、进程地址空间等信息。
全部0条评论
快来发表一下你的评论吧 !