单任务系统的问题
如果一个CPU只能运行一个程序,那么当程序读写磁盘时,CPU就空闲下来了。想象一下,你用鼠标打开一个文件(假如文件很大),由于磁盘读写很慢过,过了几分钟后,鼠标才可以动了,那该是多么沮丧的事情。
所以多任务操作系统就诞生了,当然这中间也是经历漫长的过程,这里就不再科普计算机操作系统的发展史了。
多任务操作系统
现在操作系统都是多任务的系统,多任务操作系统有两个很重要的概念:隔离和并发
关于隔离:所有的应用程序都以进程的方式运行在操作系统上,每个进程都有自己独立的地址空间,使得进程之间的地址空间相互隔离,操作系统的多任务功能使得CPU能够在多个进程之间很好的共享。
关于并发:而多线程技术可以使得任务并发的执行,以提高程序的执行效率。
由于操作系统管理着CPU资源,当操作系统分配给每个进程的时间都很短,即CPU在多个进程之间快速切换时造成了多个程序同时运行的假象。这就是多任务操作系统的工作方式
尽管我们知道了“进程”是和多任务有关的,但是理解起来依然很抽象,我们不妨从操作系统角度出发,看看多任务系统需要解决的问题有哪些:
-
早期的计算机程序是直接运行在物理内存上的,程序在运行时所访问的地址都是物理地址,这样计算机一次只能运行一个程序,如何让计算机同时运行多个程序来提高效率
-
同时能运行多个程序,让所有的程序都直接访问物理内存地址,这显然是不可以的。你没法保证你的程序正在访问空间内容不会被其他恶意程序修改,如何让正在运行的程序之间做到相互隔离
-
汇编中的地址一般都是固定的,不同的程序每次启动都需要装入到内存;作为码农的你无法确定你的程序被载入内存的地址就是你代码里写的地址。
解决上面的问题的思路就是在物理内存和用户程序之间增加一个中间层,这就是虚拟内存
虚拟内存:
虚拟地址空间是指虚拟的,人们想象出来的地址空间,并不真实存在。每个进程都有一段连续的虚拟地址空间,当程序启动的时候操作系统通过映射把这块虚拟空间映射到物理内存,具体怎么映射就由操作系统来完成,这里暂时不讨论
有了虚拟内存的存在,每个进程都只能访问自己的地址空间。程序1和程序2被映射到了两块不同的物理空间区域,没有重叠,从而达到隔离的目的,如果越界访问就会被系统检测到。
由于虚拟内存的地址空间是连续,程序员也就不用关心物理地址的变化
关于虚拟空间和物理空间的映射关系:图
image.png
虚拟内存也是一个复杂的技术(内存分页),虚拟地址空间上分布着:OS区,栈区,堆区,DATA区,code区等,这里暂且不讨论。
现在再去理解百科中关于进程的解释,“进程 是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位”这句话,就会容易许多。因为只有程序启动了才会有虚拟内存,讨论进程才有意义。程序没有启动,它就是保存在磁盘上的一块数据。
到底什么是进程
通过上文我们知道,进程最大的特点就是有一段连续的虚拟地址空间,因为进程之间相互隔离,所以进程也是资源独立的
总结起来就是,进程是正在运行中的程序,拥有完整的虚拟地址空间,资源上独立
关于线程
除了进程,线程也是一个很重要的概念。以下说的线程都指的是用户线程
线程 是操作系统能够进行运算调度的最小单位。大部分情况下,它被包含在进程之中,是进程中的实际运作单位。
这句话来自维基百科,乍一看也很抽象,我们还是先看看一个线程都包含哪些:
一个标准的线程由线程ID,当前指令指针,寄存器集合和堆栈组成;
看到指令、寄存器和堆栈,我们自然就能想到CPU。代码最终会被编译成一行一行的指令,即使我们只在main函数里面只写了一行打印''hello word!'',最终被编译成指令也要上万行代码(实际上是系统已经为我们实现了程序可执行的基本代码,即使我们不需要实现,程序启动的时候也会装载到内存中),这么多代码最终都是通过CPU来执行的执行的,线程的作用可以理解:把我们想让CPU执行的这部分代码运送到寄存器中让CPU来执行,这部分代码暂且就叫做任务线,一个线程对应一个任务,每个进程默认都有一个线程,通常叫做主线程。
所以线程其实可以理解为:它是CPU执行的单元,是一个进程中的实际运作单位,它不像进程那样有独立的虚拟地址空间,但是共享它所在进程的全部系统资源,如虚拟地址空间,文件描述符和信号处理等等.很“轻”,故线程的切换很快,且开销小
关于多线程:
如果一个任务可以被细分成诸多的子任务,那么就可以用更多的线程来完成,从而提高效率,怎么理解可被细分呢?比如一部手机有10个主要零件,就可以拆分成10个流水线同时生产,最后统一组装;不可分,比如生孩子10个月,就不能拆分开来由10个人花一个月完成;
进程和线程的关系:
每个进程都至少有一个线程(主线程),多个线程之间可以并发执行
线程是进程中的一部分,一个进程下的所有线程共享进程资源
网友评论