首页 > 其他分享 >[操作系统]用户态内核态

[操作系统]用户态内核态

时间:2024-09-12 20:46:54浏览次数:1  
标签:操作系统 用户 线程 内核 进程 执行

用户态内核态

用户态线程和内核态线程有什么区别?

这是一个组合型的问题,由很多小问题组装而成,比如:

  • 用户态和内核态是什么?
  • 用户级线程和内核级线程是一个怎样的对应关系?
  • 内核响应系统调用是一个怎样的过程?

什么是用户态和内核态

Kernel 运行在超级权限模式(Supervisor Mode)下,所以拥有很高的权限。按照权限管理的原则,多数应用程序应该运行在最小权限下。因此,很多操作系统,将内存分成了两个区域:

  1. 内核空间(Kernal Space),这个空间只有内核程序可以访问;
  2. 用户空间(User Space),这部分内存专门给应用程序使用。

用户态和内核态

用户空间中的代码被限制了只能使用一个局部的内存空间,我们说这些程序在用户态(User Mode) 执行。
内核空间中的代码可以访问所有内存,我们称这些程序在内核态(Kernal Mode) 执行。

系统调用过程

如果用户态程序需要执行系统调用,就需要切换到内核态执行。下面我们来讲讲这个过程的原理。

image

如上图所示:内核程序执行在内核态(Kernal Mode),用户程序执行在用户态(User Mode)。当发生系统调用时,用户态的程序发起系统调用。因为系统调用中牵扯特权指令,用户态程序权限不足,因此会中断执行,也就是 Trap(Trap 是一种中断)。

发生中断后,当前 CPU 执行的程序会中断,跳转到中断处理程序。内核程序开始执行,也就是开始处理系统调用。内核处理完成后,主动触发 Trap,这样会再次发生中断,切换回用户态工作。

线程模型

上面我们学习了用户态和内核态,接下来我们从进程和线程的角度进一步思考本课时开头抛出的问题。

进程和线程

一个应用程序启动后会在内存中创建一个执行副本,这就是进程。Linux 的内核是一个 Monolithic Kernel(宏内核),因此可以看作一个进程。也就是开机的时候,磁盘的内核镜像被导入内存作为一个执行副本,成为内核进程。

进程可以分成用户态进程和内核态进程两类。用户态进程通常是应用程序的副本,内核态进程就是内核本身的进程。如果用户态进程需要申请资源,比如内存,可以通过系统调用向内核申请。

那么用户态进程如果要执行程序,是否也要向内核申请呢?

程序在现代操作系统中并不是以进程为单位在执行,而是以一种轻量级进程(Light Weighted Process),也称作线程(Thread)的形式执行。

一个进程可以拥有多个线程。进程创建的时候,一般会有一个主线程随着进程创建而创建。

如果进程想要创造更多的线程,就需要思考一件事情,这个线程创建在用户态还是内核态。

你可能会问,难道不是用户态的进程创建用户态的线程,内核态的进程创建内核态的线程吗?

其实不是,进程可以通过 API 创建用户态的线程,也可以通过系统调用创建内核态的线程,接下来我们说说用户态的线程和内核态的线程。

用户态线程

用户态线程也称作用户级线程(User Level Thread)。操作系统内核并不知道它的存在,它完全是在用户空间中创建。

用户级线程有很多优势,比如。

  1. 管理开销小:创建、销毁不需要系统调用。
  2. 切换成本低:用户空间程序可以自己维护,不需要走操作系统调度。

但是这种线程也有很多的缺点。

  1. 与内核协作成本高:比如这种线程完全是用户空间程序在管理,当它进行 I/O 的时候,无法利用到内核的优势,需要频繁进行用户态到内核态的切换。
  2. 线程间协作成本高:设想两个线程需要通信,通信需要 I/O,I/O 需要系统调用,因此用户态线程需要支付额外的系统调用成本。
  3. 无法利用多核优势:比如操作系统调度的仍然是这个线程所属的进程,所以无论每次一个进程有多少用户态的线程,都只能并发执行一个线程,因此一个进程的多个线程无法利用多核的优势。

操作系统无法针对线程调度进行优化:当一个进程的一个用户态线程阻塞(Block)了,操作系统无法及时发现和处理阻塞问题,它不会更换执行其他线程,从而造成资源浪费。

内核态线程

内核态线程也称作内核级线程(Kernel Level Thread)。这种线程执行在内核态,可以通过系统调用创造一个内核级线程。

内核级线程有很多优势。

  1. 可以利用多核 CPU 优势:内核拥有较高权限,因此可以在多个 CPU 核心上执行内核线程。
  2. 操作系统级优化:内核中的线程操作 I/O 不需要进行系统调用;一个内核线程阻塞了,可以立即让另一个执行。

当然内核线程也有一些缺点。

  1. 创建成本高:创建的时候需要系统调用,也就是切换到内核态。
  2. 扩展性差:由一个内核程序管理,不可能数量太多。
  3. 切换成本较高:切换的时候,也同样存在需要内核操作,需要切换内核态。

用户态线程和内核态线程之间的映射关系

线程简单理解,就是要执行一段程序。程序不会自发的执行,需要操作系统进行调度。我们思考这样一个问题,如果有一个用户态的进程,它下面有多个线程。如果这个进程想要执行下面的某一个线程,应该如何做呢?

这时,比较常见的一种方式,就是将需要执行的程序,让一个内核线程去执行。毕竟,内核线程是真正的线程。因为它会分配到 CPU 的执行资源。

如果一个进程所有的线程都要自己调度,相当于在进程的主线程中实现分时算法调度每一个线程,也就是所有线程都用操作系统分配给主线程的时间片段执行。这种做法,相当于操作系统调度进程的主线程;进程的主线程进行二级调度,调度自己内部的线程。

这样操作劣势非常明显,比如无法利用多核优势,每个线程调度分配到的时间较少,而且这种线程在阻塞场景下会直接交出整个进程的执行权限。

由此可见,用户态线程创建成本低,问题明显,不可以利用多核。内核态线程,创建成本高,可以利用多核,切换速度慢。因此通常我们会在内核中预先创建一些线程,并反复利用这些线程。这样,用户态线程和内核态线程之间就构成了下面 4 种可能的关系:

多对一(Many to One)

用户态进程中的多线程复用一个内核态线程。这样,极大地减少了创建内核态线程的成本,但是线程不可以并发。因此,这种模型现在基本上用的很少。我再多说一句,这里你可能会有疑问,比如:用户态线程怎么用内核态线程执行程序?

程序是存储在内存中的指令,用户态线程是可以准备好程序让内核态线程执行的。后面的几种方式也是利用这样的方法。

image

一对一(One to One)

该模型为每个用户态的线程分配一个单独的内核态线程,在这种情况下,每个用户态都需要通过系统调用创建一个绑定的内核线程,并附加在上面执行。 这种模型允许所有线程并发执行,能够充分利用多核优势,Windows NT 内核采取的就是这种模型。但是因为线程较多,对内核调度的压力会明显增加。

image

多对多(Many To Many)

这种模式下会为 n 个用户态线程分配 m 个内核态线程。m 通常可以小于 n。一种可行的策略是将 m 设置为核数。这种多对多的关系,减少了内核线程,同时也保证了多核心并发。Linux 目前采用的就是该模型。

image

两层设计(Two Level)

这种模型混合了多对多和一对一的特点。多数用户态线程和内核线程是 n 对 m 的关系,少量用户线程可以指定成 1 对 1 的关系。

image

上图所展现的是一个非常经典的设计。

我们这节课讲解的问题、考虑到的情况以及解决方法,将为你今后解决实际工作场景中的问题打下坚实的基础。比如处理并发问题、I/O 性能瓶颈、思考数据库连接池的配置等,要想完美地解决问题,就必须掌握这些模型,了解问题的本质上才能更好地思考问题衍生出来的问题。

总结

这节课我们学习了用户态和内核态,然后我们简单学习了进程和线程的基础知识。这部分知识会在“模块四:进程和线程”中以更细粒度进行详细讲解。等你完成模块四的学习后,可以再返回来看这一节的内容,相信会有更深入的理解。

最后,我们还讨论了用户线程和内核线程的映射关系,这是一种非常经典的设计和思考方式。关于这个场景我们讨论了 1 对 1、1 对多以及多对 1,两层模型 4 种方法。日后你在处理线程池对接;远程 RPC 调用;消息队列时,还会反复用到今天的方法。

【解析】 用户态线程工作在用户空间,内核态线程工作在内核空间。用户态线程调度完全由进程负责,通常就是由进程的主线程负责。相当于进程主线程的延展,使用的是操作系统分配给进程主线程的时间片段。内核线程由内核维护,由操作系统调度。

用户态线程无法跨核心,一个进程的多个用户态线程不能并发,阻塞一个用户态线程会导致进程的主线程阻塞,直接交出执行权限。这些都是用户态线程的劣势。内核线程可以独立执行,操作系统会分配时间片段。因此内核态线程更完整,也称作轻量级进程。内核态线程创建成本高,切换成本高,创建太多还会给调度算法增加压力,因此不会太多。

实际操作中,往往结合两者优势,将用户态线程附着在内核态线程中执行。

标签:操作系统,用户,线程,内核,进程,执行
From: https://www.cnblogs.com/DCFV/p/18410938

相关文章

  • 基于python+flask框架的基于用户行为分析的商品推荐系统APP(开题+程序+论文) 计算机毕设
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容研究背景在数字化时代,随着电子商务的蓬勃发展和移动互联网的普及,商品信息爆炸式增长,用户面临着前所未有的选择困难。传统的搜索和浏览方式已难以满......
  • 宝藏级Docker应用推荐(建议NAS/AllinOne用户收藏)
    梳理收集了个人比较常用的Docker应用,这些应用大多免费开源,能极大提高的提高日常工作效率,也能充分榨干家里闲置设备资源,比如NAS、个人PC、主机服务器等。一、家庭娱乐中心类家庭影音、漫画、小说等1、影视类Jellyfin、Emby(个人可以不开通专业版,免费版够用)推荐原因:看电影......
  • MySQL——数据库的高级操作(二)用户管理(2)创建普通用户
            在创建新用户之前,可以通过SELECT语句查看mysql.user表中有哪些用户,查询结果如下:mysql>USEmysql;Databasechangedmysql>SELECTHost,User,authentication_stringFROMmysql.user;+-----------+------------------+-----------------------------......
  • MySQL——数据库的高级操作(二)用户管理(1)uer表
            每个软件都会对用户信息进行管理,MySQL也不例外,MySQL中的用户分为root用户和普通用户,root用户为超级管理员,具有所有权限,如创建用户、删除用户、管理用户等,而普通用户只拥有被赋予的某些权限。        在安装MySQL时,会自动安装一个名为mysql的数据库......
  • ORA-01940 无法删除当前连接的用户
    ----bayaim,个人原创----2024年9月12日17:36:50 ORA-01940无法删除当前连接的用户----------------------------------------------------1、现象:删除用户dropuserECOLOGYcascade;报错:ora01940无法删除当前连接的用户2、解决办法:--查看用户的sid......
  • ThreadLocal 存储用户信息
    1Cookie+Session由于HTTP协议是无状态的,完成操作关闭浏览器后,客户端和服务端的连接就断开了,所以我们必须要有一种机制来保证客户端和服务端之间会话的连续性,常见的,就是使用Cookie+Session(会话)的方式。具体来说,当客户端请求服务端的时候,服务端会为此次请求开辟一块内存空间......
  • 【读书笔记-《30天自制操作系统》-18】Day19
    本篇内容涉及到文件与文件系统,以及应用程序的运行。首先实现type命令,读取文件并显示;接下来导入对FAT文件系统的支持,实现读取大小512字节以上,存放在不连续扇区中的文件。在此基础上,最终实现读取并运行应用程序。1.type命令实现type命令是Windows命令行中用于读取并显示文......
  • 2024年市场营销人员需要了解的16个Snapchat用户数据
    Snapchat年龄分布Snapchat性别分布Snapchat收入分布Snapchat地理位置分布我们都知道每个Snapchat用户都是独特且珍贵的,但让一个普通的社交媒体经理了解应用程序的8亿月度活跃用户的全部情况实在是太难了。这时,Snapchat的人口统计数据就派上用场了。这些方便的数据让我......
  • 不使用Redis分布式锁,如何避免用户重复点击提交?
    前端,在用户点击后,对按钮做置灰操作。但有些情况,用户会绕过置灰,实现重复点击。后端,对客户端携带的token,验证是否使用过;验证逻辑,存储在数据库中,验证逻辑使用悲观锁或者乐观锁实现。前端按钮置灰前端按钮置灰:在用户点击按钮后,将按钮禁用一段时间或直到请求响应。优点:简......
  • linux操作系统日志小知识
    Linux系统中的日志文件是系统、应用程序和各种服务运行状态的重要记录。它们对于系统管理员来说至关重要,因为它们可以帮助诊断问题、监控系统性能和安全问题。以下是Linux日志文件的一些基本概念和介绍:1.**日志文件的位置**:  -`/var/log`:这是大多数Linux发行版存储......