如何理解内核线程、内核进程?

很多人对进程,线程没有什么概念,或者面试的时候说不出里面的核心内涵,今天我打算花一点篇 幅把进程和线程讲清楚。

这里有个游戏开发学习交流小组点击可以直接加入,一起学习交流吧

1: CPU与内存

CPU 大家都知道是计算机的中央运算单元,用来计算的。CPU从内存里面读取一条一条的代码指令,然后根据指令来执行运算(加,减,乘,除,复制数据等)。 CPU在运算的过程中一些数据存放在CPU的寄存器和内存里面, CPU里面有各种寄存器,各司其职。指令指针寄存器存放的是当前执行到那条代码指令了。代码指令是写完程序后被编译器编译成二进制指令代码

2: 内核与虚拟内存。

电脑或手机开机以后,上电跑启动代码,运行OS内核,内核里也有线程,这个我们把它叫做内核态。内核启动以后, 内核将物理内存管理起来。内核提供虚拟内存管理机制给每个进程(应用程序App)内存服务。它的思路是什么呢?每个进程(应用App) 都有自己的虚拟内存空间,注意这里的空间只是一个数字空间,没有划分实际的物理内存。这样做的好处是多个进程(应用App)内存都是独立的相互不影响,物理内存只有一个,多个进程(应用App)不会因为直接使用物理内存而冲突。那么OS是如何管理物理内存的呢?进程(应用App)需要内存的时候,OS分配一块虚拟内存(起点---终点),然后OS在从自己管理的物理内存里面分配出来物理内存页,然后通过一个MMU的单元,将分配的虚拟内存与物理内存页映射起来,这样,读写虚拟内存地址最终通过映射来使用物理内存地址,这样每个进程之间的内存是独立的,安全的。每个进程会把虚拟内存空间分成4个段(代码段, 数据端,堆,栈)

每个进程(应用App)相当于一个容器,所有应用App里面需要的资源和机制都在进程里面。线程是OS独立调度执行的单元,OS调度执行的单位就是线程,线程需要以进程作为容器和使用进程相关的环境。

应用态没有进程就不会有线程。

3: 进程与线程

上面说过进程是容器,应用态的线程必须要基于进程来创建出来。那么进程与线程他们之间到底是一个什么样的关系,接下来我们来分析一下。例如"在桌面上双击打开一个App", 桌面App程序会调用OS的系统调用接口fork,让OS 创建一个进程出来, OS为你准备好进程的结构体对象,将这个App的文件(xxx.exe, 存放编译好的代码指令)加载到进程的代码段,同时OS会为你创建一个线程(main thread), 在代码里面,你还可以调用OS的接口,来创建多个线程。这样OS就可以调度这些线程执行了。 虚拟内存空间是进程的概念,那么线程如何使用的呢?各线程使用共享进程的代码段,数据段,堆,每个线程在进程的栈空间创建一个属于自己的栈空间。所以这样就得到一些结论如下:

每个线程都有自己的栈的空间,所以可以独立调用执行函数(参数,局部变量,函数跳转)相互之间不受影响。

4: OS如何调度线程的。

CPU一般会有多个核心,每个核心都调度一个线程执行。CPU有几个核心,最多同时可调度几个线程(多核能让电脑更快就是这个原理)。OS的功能就是要在合适的时候分配CPU核心来调度合适的线程。为了能实现多任务并发,OS不允许一个OS核心长期固定调度一个线程。

每个线程“随时随地”都可能被OS 中断执行,并调度到其它的线程执行。OS是如何保证一个线程在调度出去后,再重新调度回来能继续之前的数据状态来执行呢?OS是这么做到的。每个线程都会有一个运行时的环境(运行时CPU的每个寄存器的值, 栈独立, 栈的内存数据不会变。数据段,堆共用,可能调度回来会变)。当OS要把某个CPU核心调度出去给其它线程的时候,首先会把当前线程的运行环境(寄存器的值等)保存到内存,然后调度到其它线程,等再次调度回来的时候,再把原来保存到内存的寄存器的值,再设置会CPU核心的寄存器里面,这样就回到了调度出去之前的进度。

线程调度的开销就是:保存上下文执行环境,内核态运行算法决定接下来调度那个线程,切换这个线程的上下文环境。

5: 线程锁的核心原理是什么?

多线程切换的时候,栈,代码段的数据不会变,数据段与堆的数据切换前后可能会发生改变,这个就造成了"竞争", 如果某些关键数据,在执行代码的时候,不允许这种竞争性的改变,怎么办呢?这个时候多线程就给了一个机制,这个机制就是锁,那么锁的原理是什么?接下来我来和你详细的讲解。

例如: 我编写一个函数,

当线程A调用FuncA(),线程B也调用FUNCA(),OS如何设计锁能保证他们竞争的唯一性的呢?我们把具体过程来分析一下。

进程与线程各位老铁一定要掌握好,这样你写程序才能做到心中用代码, 今天的分享就到这里了,谢谢再见。 

猜你喜欢

转载自blog.csdn.net/qq_41973169/article/details/127634268
今日推荐