跳转至

toLearn

3.2 taskPriority

工作优先级四象限(优先级矩阵)

  • 基础版本(艾森豪威尔)
    • 对于紧急又重要的事情马上做。如果这类事情过多,那就想办法规划时间,减少此类事情。
    • 对于重要但不紧急的事情计划做。尽可能地把时间花在重要但不紧急的事情上,这样才能减少产生重要且紧急的工作量。
    • 对于紧急但不重要的事情授权做。处理原则是授权,让别人去做。
    • 最后对于不重要不紧急的事情减少做
  • 额外的维度
    • 依赖关系:工作中显露的潜在工作会打断工作的交付,砍半降低交付效率
      • 尽可能全面

拓展版本

  • 当前工作优先级评估由 四个连续值维度 + 三个逻辑指标 组成
  • 优先级评估的时候不止是自己的视角,还有别人的视角(别人在心里的权重 * 重要性 * 紧迫性)。其中别人在心里的权重,一般来说: 父母、爱人、子女 > 领导 > 我
四个连续值维度
  • 喜好程度
  • 估计工作量(投入收益比)。这一点其实很难量化,自己都没有做怎么知道,只能横向收集友商的数据。
  • 紧急的纬度由DDL时间确定,这点可以和工作量指标互动。
  • 重要性由以下几点确定,都能提高对工作的重要性评价:
    • 增加对工作的喜爱程度的任务: 高效插件与可视化工具的学习使用,
    • 提高工作效率的任务:学习基础知识,
    • 减少长期的工作量:学习、制造和使用轮子;自动化工作。
三个逻辑指标
  • 工作间依赖关系
  • 专注度要求(与疲劳度互补,清醒时才能做思考工作,一天工作后也能进行的简单工程工作)
  • 是否属于未知的领域。(与专注度要求不是正交的关系,是集合的包含关系。需要动脑的事情,肯定是未知的)
经常遇到的实际情况

相同的指标

  1. 紧急程度:不紧急。我一般会比较焦虑,所以工作会较早立项。
  2. 重要程度:我认为重要的才会主动去做,无论是对眼前的毕业考核,还是长远的考虑
  3. 喜好程度:我认为有趣的才会主动去做
  4. 工作间的依赖关系:我会遵守逻辑

不同的指标:

  1. 是否未知:阅读信息的需求
  2. 是否需要专注: 思考需求

两者结合:纯思考 > 阅读加稍微思考 > 初步的阅读收集信息 > 纯机械工作

任务周期内:时间分配和执行顺序

之前的任务优先级评判,都是从完成任务的角度考虑。但是实际情况是每个任务都需要很久(许多任务周期)才能完成。

按照优先级的指标,例如:

紧急性(3) 重要性(3) 喜好(1) 工作量(3) 总分 分配 要求
report 3 0 0 0 3 一天欠 2
thesis 3 3 0 3 9 两天多 3
AI 2 2 1 2 7 两天欠 1
OpenCL 2 1 1 1 5 一天多 1
web 1 0 0 1 2 一天欠 1
Summary 26
  1. 紧急性: 迫在眉睫(几天), 稍等几周,稍等几月,半年一年,可有可无
  2. 重要性: (当下)重大转折,(潜在)深远影响, 一年内小方向,与我无瓜
  3. 喜好:特别喜欢,有点意思,毫无波澜,有点厌恶
  4. 预估工作量(专心情况下):半年以上,一个季度,一个月,一周
  5. 要求(专注度):纯思考 > 阅读加稍微思考 > 初步的阅读收集信息 > 纯机械工作 (3~0)

注意

  • 工作安排 “必须做”占 40%,“愿意做”限制在 30% 左右,剩下30%处理出现的未发现的依赖任务和计划外工作。
  • 涉及到合作的工作:要与对方商量好,自己的选择(为什么把你鸽了,不是)

理想中的二维可视化细节

  • 科研工作与生活各自独立一张图。处理的时间段不同。
  • 横坐标是时间DDL表示紧急程度Urgency,纵坐标是重要性Impact(代表能增强自身和造轮子,还是繁琐小事)
    • 横坐标会随时间自动移动,
    • 标记出四块或者9块颜色
  • 节点可以可视化的部分
    • 颜色深浅表示喜好程度、投入收益比
    • 大小表示工作量绝对值(难易程度)
    • 会根据每日的任务自动调整
    • 甘特图 Gantt:的长条状,中间塞进度条的百分比实现。
    • 和连线表示工作依赖关系
    • 特殊颜色/形状 表示设置里程碑(北极星)任务,完成后自己会收获什么(能力属性标签)
  • 节点额外的属性值(不可视化)
    • 任务的风险
    • 需要的合作者,资源
    • DoD (完成标准,验收标准)
  • 根据公式和数据, 计算工作的优先级并给出推荐。
    • 考虑WIP(Work in Progress)
  • 实现日历功能
  • 为了能激励自身,引入信息增长统计
    • 过去一周/月/季度/年,完成的各类型的Task
    • 引入勤劳值(工作量统计),和收获值(能力增长统计)
    • 能力属性标签, 数值是否随时间衰减

已有的优先级矩阵产品

  • ducalis
  • 另一种维度,将紧急程度与工作量交换:pic

团队合作的优先级

团队合作中,解决问题的策略与优先级

对象:领导、部门的同事团队( 其余部门的同事团队),个人主体。

思考的基础与前提(多沟通,深分析,找关键):

  1. 找到问题的关键,并提出实用有效的方法
  2. 问题考虑全面,目光长远,设计方法可持续

情形:

  1. 别人遇到问题求助
    1. 授人以鱼不如授人以渔
    2. 如果有其余需求,归纳到最后一点统计决策
  2. 自己遇到问题
    1. 研究瓶颈
      1. 在充分的调研与汇总整理后,向同事或者上级咨询与求助
    2. 两难抉择: 返工的bug修复,新功能,新业务,新研究方向与现有的工作的时间冲突
      1. 工作优先级四象限:根据重要性、紧急程度、喜好程度、工作量(投入收益比)与依赖关系分类
      2. 要与提出需求的对方商量好,解释自己的选择和困难

参考文献

上面回答部分来自ChatGPT-3.5,没有进行正确性的交叉校验。

3 EfficientJumpingRunning

jumping the branch task

五大阻碍工作完成时间的罪魁祸首

  1. 过多的Work in Progress
  2. 太多WIP会导致很多问题:交付延误、品质下降和员工情绪恶化
  3. 利特尔定律 \(\(平均周期时间 =\frac{平均WIP量 }{平均产出量 }\)\)
  4. 未知的依赖工作
  5. 常见依赖关系有3种: > 架构(软件和硬件):一个组件的变更可能破坏另一个组件导致它停止运行 专业知识:从专家那里获得建议或帮助(需要怎样做某事) 活动:直到活动完成才能取得进展
  6. 计划外工作(妨碍你完成某事或导致你无法实现里程碑的干扰事项)
  7. 优先级冲突(相互竞争的项目和任务。当你不确定做什么事情是最重要的时候,就会加剧这种冲突)
  8. 被忽视的工作(技术债)

如何相互影响

  1. 信念/意志确实很重要
  2. 强烈的信念能让你的工作迈出坚实的第一步,而且每一步都走得是否有力
  3. 但是前提是你要十分明确努力的方向,对工作的不自信会减半工作热情。
    1. 工作的优先级冲突,这将导致过多的WIP,从而导致更长的周期时间。
  4. 明确任务的优先级,并分阶段、逐步击破是最好的选择。

需要进一步的研究学习

暂无

遇到的问题

暂无

开题缘由、总结、反思、吐槽~~

参考文献

上面回答部分来自ChatGPT-3.5,没有进行正确性的交叉校验。

DeviceExpansion

拯救者 R7000 2020(1650ti)

内存条

内存为两根8GB DDR4-3200内存组成双通道。 如果要拓展,需要全部升级为 16GB * 2。 拓展视频图文教程

M2固态

可以加装一条2280的固态, 但是无法加机械了。

B450M (主机主板)

内存条

  1. 芯片组最高支持DDR4 2933的内存频率,
  2. 单条内存最大32GB,总容量最大128GB,
  3. 向下可以兼容DDR4 2133、DDR4 2200、DDR4 2400、DDR4 2666。

M2

PCIe 3.0的数据传输速度每通道1GB/s,PCIe 2.0是其一半

B450迫击炮有两个M2插槽,一个是满速pcie3.0×4(4GB/s) 一个是半速的pcie2.0×4(2GB/s)。价格差不多的话还是用M2 nvme协议 的SSD

一点没人提过的,b450m迫击炮装上第二个m2以后,第二个pcie2.0*16的扩展(pcie_4)是没法用的。

需要进一步的研究学习

暂无

遇到的问题

暂无

开题缘由、总结、反思、吐槽~~

参考文献

上面回答部分来自ChatGPT-3.5,没有进行正确性的交叉校验。

Weekly

Content

  1. Background, history
  2. Doing, Situation, Problem, Achievement
  3. Next Plan

year 2023

Weekly 230925-231001

  1. Wednesday 0927
  2. Afternoon: compile and test MultiPIM on icarus0, suffered from python2.7 and lose package dependency. But still encounter pin failed problem

需要进一步的研究学习

暂无

遇到的问题

暂无

开题缘由、总结、反思、吐槽~~

周报是一周的总结和思考,

参考文献

上面回答部分来自ChatGPT-3.5,没有进行正确性的交叉校验。

Wake Up Process

Linux 多进程的竞争休眠机制

基本是基于Linux的时间片轮转机制。A process/thread is woken up by inserting it in the queue of processes/threads to be scheduled.

内核调度算法

CFS(Completely Fair Scheduler)是一种用于 Linux 操作系统的调度算法,它旨在实现对 CPU 时间的公平分配。CFS 是 Linux 内核中默认的调度器,自 Linux 2.6.23 版本以来就成为了标准调度器。

CFS 调度算法的主要目标是确保各个任务在相同的时间片内能够获得公平的CPU时间,不会因为优先级等因素而造成资源争夺不均。以下是 CFS 调度算法的一些关键特点和原则:

  1. 虚拟化时钟: CFS 使用了一种称为虚拟化时钟(virtual runtime)的概念,而不是传统的时间片。每个任务都有一个虚拟运行时间,调度器根据虚拟运行时间来决定哪个任务应该被调度。

  2. 权重: CFS 引入了权重的概念,用于调整不同任务的相对优先级。较高权重的任务会在相同时间间隔内获得更多的虚拟运行时间,从而实现按比例分配CPU资源。

  3. 累积虚拟运行时间: 调度器会根据每个任务的权重和已累积的虚拟运行时间,计算出每个任务的应有的虚拟运行时间片。任务在使用完它的时间片后,会根据虚拟运行时间进行重新排队。

  4. 红黑树结构: CFS 使用红黑树来管理任务队列,这种数据结构使得在插入、删除和搜索任务时的时间复杂度保持在对数级别。

除了 CFS,Linux 内核还有其他调度算法,如:

  • 实时调度器(Real-Time Scheduler): 用于实时任务,提供硬实时和软实时的调度策略,确保实时任务在指定的时间内执行完成。

  • O(1) 调度器(O(1) Scheduler): 是 Linux 2.4 内核中使用的调度器,它的时间复杂度为常数级别。然而,随着多核系统的出现,O(1) 调度器在多核环境下的性能表现受到限制,因此被 CFS 替代。

这些调度算法在不同的场景和需求下,对于多任务操作系统的调度提供了不同的方法和策略。选择适合的调度算法可以根据系统的应用和性能要求来进行。

问题

在高强度竞争之后,有些进程陷入长期sleep,并且在核空闲的时候,也不再重新运行?为什么?

原因可能是程序逻辑阻塞了,或者在等待IO

查看进程Sleep的原因

首先 计算机对一个进程是如何判断sleep的,是某时间内的计算占比低于某个阈值吗?

htop s 可以查看kernel 是不是阻塞, l 可以查看是不是读写同一个文件导致阻塞了。

Sleep的瓶颈在哪里

sleep for what, waiting for what?

实践1 strace

strace -p PID 可以显示一些信息

$ strace -p 4005042
  wait4(-1, # 等待任意子进程结束

# check subprocess
$ pstree -p 4005042
pinbin(4005042)---BC_Compute(4005082)-+-{BC_Compute}(4005187)
                                      |-{BC_Compute}(4005188)
                                      |-{BC_Compute}(4005252)
                                      |-{BC_Compute}(4005296)
                                      |-{BC_Compute}(4005299)
                                      `-{BC_Compute}(4005302)

$ strace -p 4005082
strace: Process 4005082 attached
futex(0x7fffe52de1b8, FUTEX_WAIT, 2, NULL
# futex - fast user-space locking(seems to be used in OpenMP)
# It is typically used as a blocking construct in the context of shared-memory synchronization. 


$ strace -p 4005188
nanosleep({tv_sec=0, tv_nsec=2000000}, 0x7fffe5368bc0) = 0 # repeat
nanosleep({tv_sec=0, tv_nsec=2000000}, 0x7fffe536dbc0) = 0

It seems this is a subprocess repeating sleep leading to all other process to wait in the synchronization.

Use gdb -p PID to attach the process to locate the infinite loop (need Debug Symbols).

futex解释

futex 是 Linux 下的一个系统调用,用于实现用户空间线程间的同步和通信。让我们逐个解释这个系统调用中的每个参数的含义:

  1. 0x7fffe52de1b8: 这是一个指向内存地址的指针(或称为地址),通常是用于表示需要同步的资源或变量的地址。在这里,它表示需要等待的共享资源或变量的地址。
  2. FUTEX_WAIT: 这是一个指定 futex 要执行的操作的标志。FUTEX_WAIT 表示线程正在等待 futex 的值发生变化,即等待条件满足。当某个线程执行 FUTEX_WAIT 操作时,如果 futex 的值与预期不符,则该线程将被置于休眠状态,直到 futex 的值发生变化或超时。
  3. 2: 这是一个表示期望的 futex 值的参数。当调用 FUTEX_WAIT 时,线程将检查 futex 的当前值是否等于此参数指定的值。如果不等于,则线程将休眠等待。
  4. NULL: 这是一个指向 timespec 结构的指针,用于设置超时。这里为 NULL 表示调用没有设置超时,即线程将一直等待,直到 futex 的值发生变化。

总的来说,futex(0x7fffe52de1b8, FUTEX_WAIT, 2, NULL) 表示线程正在等待位于内存地址 0x7fffe52de1b8 的 futex 变量的值等于 2。如果 futex 的值不是 2,则线程将一直等待直到 futex 的值变为 2 或者超时。这样的同步机制在多线程编程中用于等待条件满足后再执行某些操作,从而避免资源竞争和提高程序的并发性能。

nanosleep解释

这是一个系统调用 nanosleep 的输出,通常用于让线程休眠一段时间。让我们逐个解释这个系统调用的含义:

nanosleep({tv_sec=0, tv_nsec=2000000}, 0x7fffe5368bc0) = 0
  1. nanosleep: 这是 Linux 下的一个系统调用,用于使线程休眠一段指定的时间。

  2. {tv_sec=0, tv_nsec=2000000}: 这是传递给 nanosleep 的第一个参数,是一个指向 timespec 结构的指针。timespec 结构用于表示时间间隔,包括秒(tv_sec)和纳秒(tv_nsec)。

在这里,tv_sec=0 表示秒数为 0,tv_nsec=2000000 表示纳秒数为 2000000。因此,这个 nanosleep 调用将会使线程休眠 2 毫秒(1 秒 = 1000000000 纳秒,所以 2000000 纳秒就是 2 毫秒)。

  1. 0x7fffe5368bc0: 这是传递给 nanosleep 的第二个参数,表示一个 timespec 结构的指针。这个参数用于存放未休眠完成的剩余时间,如果 nanosleep 被中断(例如收到信号),它将在这个指针中返回剩余的时间。在这个输出中,剩余时间被存储在内存地址 0x7fffe5368bc0 处。

  2. = 0: 这是 nanosleep 的返回值,表示成功完成。返回值为 0 表示 nanosleep 成功休眠了指定的时间。

综上所述,这个输出表示线程成功休眠了 2 毫秒。

实践2: zsim模拟程序

程序直接执行正常,zsim模拟直接sleep?

$ strace -p 303359
read(10,

$ pstree -p 303359                                                                                 gups_vanilla(303359)-+-gups_vanilla(303449)-+-orted+                                                                    |                      `-{gups+                                                                    |-{gups_vanilla}(303360)                                                                           |-{gups_vanilla}(303361)

$ pstree -p 303449                                                                                 gups_vanilla(303449)-+-orted(303451)-+-{orted}(303452)                                                                  |               |-{orted}(303642)                                                                  |               |-{orted}(303643)                                                                  |               `-{orted}(303644)                                                                  `-{gups_vanilla}(303450)

这是一个 Open MPI(Message Passing Interface)的启动命令,用于启动一个 MPI 程序,并配置一些运行时参数。让我们逐个解释这个命令中的每个选项和参数的含义:

orted --hnp --set-sid --report-uri 11 --singleton-died-pipe 12 -mca state_novm_select 1 -mca ess hnp -mca pmix ^s1,s2,cray,isolated

部分参数含义如下:

  • orted: 这是 Open MPI 的一个工具,用于启动和管理 MPI 进程。
  • -mca state_novm_select 1: 这是一个 MCA(Modular Component Architecture)选项,用于指定某个模块或组件的参数设置。在这里,state_novm_select 设置为 1,可能是指定某个组件或模块在运行时的选项。
  • -mca pmix ^s1,s2,cray,isolated: 这是另一个 MCA 选项,用于配置 PMIx(Process Management Interface for Exascale)的相关设置。^s1,s2,cray,isolated 表示排除 s1、s2、cray 和 isolated 这些模块,可能是禁用某些特定的组件或功能。
pid strace output explanation
303451 restart_syscall(<... resuming interrupted read ...>
303452 futex(0xabba001ec8, FUTEX_WAIT, 2, NULL
303642 epoll_wait(18, ... epoll_wait 系统调用,用于等待文件描述符18上的事件
303643 select(50, [48 49], NULL, NULL, 如下
303644 select(53, [51 52], NULL, NULL,
  • restart_syscall表示系统调用被中断后重新启动的过程。它通常出现在系统调用的执行过程中,当某个信号(例如 SIGSTOP 或 SIGCONT)中断了系统调用的执行,然后系统调用在信号处理完成后被重新启动。
  • select 是一个用于在多个文件描述符上进行 I/O 多路复用(I/O multiplexing)的系统调用,它可以监视多个文件描述符,并在其中任何一个文件描述符准备好进行 I/O 操作时返回。
  • select 调用的输出,它将监视文件描述符 48 和 49,并在其中任何一个文件描述符准备好读取数据或超时(2 秒后)时返回。
  • 完全无法理解呢! 可能需要深入了解MPI的实现栈细节才能明白。

命令行唤醒Sleep进程

The only way to “wake it up” is to arrange for the condition to be met. 用户是无法更改的状态的。

传统kill进程

# find pid , state S+ meaning sleep
ps aux | grep name
# gracefully kill process
kill -15 pid

需要进一步的研究学习

暂无

遇到的问题

暂无

开题缘由、总结、反思、吐槽~~

参考文献

上面回答部分来自ChatGPT-3.5,没有进行正确性的交叉校验。

Benchmark

导言

以现实中实际使用的应用为基础,根据其领域和应用计算特点来分类。

Jupyter AI

Jupyter 简介

Jupyter是一个开源的、交互式的计算环境,可以让用户创建和共享包含实时代码、可视化和文本的文档。

  • 它的名字来源于三个主要的编程语言:Julia、Python和R,这三种语言的开头字母构成了“Jupyter”。
  • Jupyter最初是IPython项目的一部分,旨在提供Python的交互式计算环境。随着时间的推移,它不仅支持Python,还扩展到其他编程语言,包括R、Julia、Scala等。Jupyter的灵感来自于IPython的交互式shell,但在其基础上增加了更多功能和可扩展性。

Jupyter最显著的特点:用户可以通过Web浏览器打开Jupyter笔记本,然后在其中编写代码、运行代码并直接查看代码的输出结果。笔记本中的代码和文本可以交叉编排,使得写作、数据分析和可视化变得非常直观和便捷。

主要的Jupyter组件包括:

  1. Jupyter Notebook:这是最常见的Jupyter界面,以.ipynb后缀的文件保存。它支持多种编程语言的代码运行,交互式地执行和编辑代码块,并支持在代码块中插入Markdown格式的文本以及图像、链接等内容。
  2. Jupyter Lab:这是Jupyter Notebook的下一代界面,提供了更加现代化和灵活的界面。Jupyter Lab将各种组件整合到一个集成的界面中,使得多个笔记本、终端和文件浏览器可以在一个窗口中同时运行。
  3. Jupyter Kernel:Jupyter支持多种编程语言的内核,通过内核,Jupyter可以与特定编程语言进行交互。例如,使用Python内核可以在笔记本中运行和编写Python代码,同样,使用R内核可以运行和编写R代码。

Jupyter在教育、数据科学、机器学习、数据分析等领域得到广泛应用。它提供了一个方便、实用的平台,帮助用户探索数据、实验算法、展示结果,并通过共享笔记本方便地与其他人交流和合作。

Jupyter vs python

Jupyter 的核心在于 数据分析的 计算-分析-可视化 的快速迭代。

如果不是数据科学,就不太需要Jupyter

Installation in Linux

安装Jupyter Lab

web-forward to local machine

远程访问服务器

Jupyter-AI

  1. Installation
  2. test

需要进一步的研究学习

暂无

遇到的问题

暂无

开题缘由、总结、反思、吐槽~~

  1. python 一大特点就是容易可视化,既然这样,我为什么不用jupyter呢?
  2. chatgpt 类的工具都是基于付费API,有两大问题
  3. 国内难以付费
  4. 国内ip一旦访问是很容易封号的。
  5. 一种解决办法是使用有免费API的工具,并且在全流量走cloudflare的wg的服务器上配置服务。

参考文献

上面回答部分来自ChatGPT-3.5,没有进行正确性的交叉校验。

https://jupyter-ai.readthedocs.io/en/latest/users/index.html#installation

Parallel_sort

并行排序算法

to learn

PSRS算法

并行正则采样排序算法

PSRS

复杂度分析

简单地讨论一下 PSRS 算法的复杂度。

  • 在第一部分的快速排序中,时间复杂度为O(klogk),k=n/p
  • 然后,各处理器选择 p-1 个代表元素,代价为O(p)
  • 再由 Proc#0 对所有送来的代表元素进行排序,然后选出主元,这里若使用快速排序,代价为O(p^2 logp^2)
  • 而若使用归并排序,则所需代价为O(p^2)
  • 每个处理器接收到主元后,再对有序数组进行划分,代价为O(k+p)
  • 最后,各个处理器全局交换,并行归并排序,
  • 每个处理器是串行的多路归并问题,时间复杂度为O(k*logp)

考虑到实际应用中,需要排序的数据长度 n 一定远远多于现有的处理器 p,此时可以视 p 为一个小常数,那么 PSRS 排序算法的时间复杂度,就可以简化为 O(klogk+k*logp)~O(klogk)

从消息复杂度的角度看,

  • 播送主元的复杂度为 O(p^2+p)
  • 分区合并(全局交换)部分的消息复杂度与具体算法实现相关,但其最大值不会超过 O(n)

需要进一步的研究学习

暂无

遇到的问题

暂无

开题缘由、总结、反思、吐槽~~

参考文献

上面回答部分来自ChatGPT-3.5,没有进行正确性的交叉校验。

https://dingfen.github.io/mpi&openmp/2021/01/23/psrs_sort.html

User Kernel Mode

内核态

内核态是计算机系统中的一种特权模式,用于执行操作系统内核的代码和功能。与用户态相比,内核态具有更高的权限和更广泛的访问能力,可以执行一些用户态无法执行的关键任务和操作。下面是从用户态的角度上介绍内核态的功能:

  1. 系统调用(System Calls):内核态允许用户程序通过系统调用接口请求操作系统提供的服务和功能。用户程序可以通过系统调用请求文件操作、网络通信、内存管理等操作。当用户程序执行系统调用时,会触发从用户态切换到内核态的转换,以便内核在高权限下执行相应的操作。
  2. 资源管理:内核态负责管理计算机系统的各种资源,包括处理器、内存、磁盘、网络等。在内核态下,操作系统可以对这些资源进行分配、调度和释放,确保资源的有效利用和合理分配。
  3. 中断处理:当发生硬件中断或异常时,内核态负责处理中断并提供相应的服务。例如,当用户程序需要与设备进行交互时,内核可以响应设备的中断信号,进行数据传输、状态检查等操作。
  4. 进程管理:内核态负责创建、销毁和管理进程。它可以调度进程,分配和回收进程所需的资源,并在必要时进行进程间的通信和同步。
  5. 内存管理:内核态控制着计算机系统的内存分配和管理。它负责将物理内存分配给进程,并维护虚拟内存和物理内存之间的映射关系。内核还处理内存保护、页面置换、内存回收等任务。
  6. 设备驱动程序:内核态包含设备驱动程序,用于与硬件设备进行交互。它允许操作系统通过设备驱动程序来控制和管理硬件设备,如磁盘驱动程序、网络驱动程序等。
  7. 安全和权限管理:内核态能够执行与系统安全和权限相关的任务。它可以控制对系统资源的访问权限,并确保用户程序不能越权访问或修改关键数据和系统配置。

总的来说,内核态提供了操作系统核心功能的执行环境,拥有更高的权限和更广泛的访问能力,使得操作系统能够管理和控制计算机系统的各个方面,同时为用户程序提供必要的服务和保护。

代码位置

在Linux系统中,每个进程的虚拟地址空间中的高位部分通常被映射为内核空间,其中包含了内核态的代码和数据。这个区域通常被称为内核空间或内核页表。内核空间中的内容包括以下两类:

  1. 内核代码:内核代码是操作系统内核的实现,包括各种系统调用、设备驱动程序和核心功能的代码。这些代码用于提供操作系统的各种服务和功能,如文件系统操作、进程管理、内存管理、网络通信等。内核代码是所有进程共享的,因为它们代表了操作系统的核心部分,为所有进程提供服务。
  2. 共享内核数据结构:内核空间中还包含一些共享的内核数据结构,用于维护系统状态和资源管理。例如,进程调度器、内存管理数据结构、文件描述符表等。这些数据结构被多个进程共享,以便内核能够管理和控制系统资源的分配和使用。

除了以上共享的内容,内核空间还包含一些每个进程独有的部分,例如:

  1. 进程描述符(Process Descriptor):每个进程都有一个唯一的进程描述符,其中包含了进程的状态信息、上下文和其他与进程相关的数据。进程描述符存储在内核空间,每个进程都有自己独立的进程描述符。
  2. 用户栈和内核栈:每个进程都有自己的用户栈和内核栈。用户栈用于保存进程在用户态执行时的局部变量和函数调用信息,而内核栈用于保存进程在内核态执行时的上下文信息和函数调用。(内核函数也要嵌套调用)

总结起来,Linux进程的高位部分映射了内核空间,其中包含了内核代码、共享的内核数据结构以及每个进程独有的部分,如进程描述符和栈空间。这种映射允许进程与内核进行交互和访问操作系统的功能和服务。

如何共享

在内核中,代码共享并不是通过动态链接库(.so)的模式来实现的。内核态的代码通常被编译成内核模块或者直接编译进内核映像中,而不是作为独立的可加载库。因此,内核中的代码共享机制与用户空间中的动态链接库不同。

在内核中,代码共享是通过代码复用和内核模块的概念来实现的。内核模块是一种可以动态加载和卸载的代码和数据集合,它可以扩展内核的功能。内核模块可以包含新的设备驱动程序、文件系统、网络协议等,以便在需要时被加载到内核中运行。

内核模块的加载过程可以在运行时根据需要进行,而不需要重新编译整个内核。这样,多个进程可以共享同一个内核模块,从而实现内核代码的共享。当多个进程需要使用某个内核模块时,模块只需要加载一次,然后被多个进程共享调用。

值得注意的是,内核中的代码共享是在内核空间内部进行的,与用户空间的动态链接库不同,它不涉及用户进程的地址空间和加载机制。内核模块的共享是在内核内部完成的,不同进程间可以通过系统调用接口访问共享的内核模块提供的功能和服务。

总结起来,内核中的代码共享是通过内核模块的加载和运行机制来实现的,而不是像用户空间中的动态链接库那样。内核模块可以被多个进程共享调用,从而提供共享的内核功能和服务。

内核态与用户态切换

切换时机

内核态与用户态的切换通常由以下几种情况触发:

  • 系统调用(System Call):当用户程序通过系统调用请求操作系统提供的服务时,会触发从用户态到内核态的切换。这是最常见的切换方式。
  • 异常(Exception)和中断(Interrupt):当发生硬件中断、软件中断(如除零错误)、内存访问错误等异常情况时,CPU会切换到内核态来处理异常。这些异常可以是由程序错误、设备请求或其他条件引起的。
  • 外部事件:例如时钟中断、I/O 完成中断等,这些事件可能需要内核处理,因此会导致从用户态切换到内核态。

切换的细节

当进程从用户态切换到内核态,或者从内核态切换回用户态时,涉及到特权级的切换和上下文的保存与恢复。下面是内核态与用户态切换的一般细节:

  1. 特权级切换:内核态拥有更高的特权级别,因此从用户态切换到内核态时,CPU会从当前运行的用户模式切换到内核模式。这种切换会改变CPU的状态,包括特权级、堆栈和指令指针。

  2. 上下文保存与恢复:在切换到内核态之前,CPU会保存当前用户态下的进程上下文信息,包括程序计数器(PC)、寄存器的值、堆栈指针等。这些上下文信息保存在进程的内核栈中。

  3. 内核态执行:当切换到内核态后,CPU开始执行相应的内核代码,处理请求或异常。在内核态下,操作系统可以访问和操作系统的所有资源和功能,执行必要的操作。

  4. 上下文恢复与切换回用户态:当内核态的任务完成后,CPU会从内核栈中恢复之前保存的进程上下文信息。然后,CPU会将特权级切换回用户态,并从保存的程序计数器继续执行用户程序。

需要注意的是,内核态与用户态的切换涉及到CPU和操作系统的底层机制,具体细节可能会因操作系统的设计和架构而有所不同。上述描述是一般情况下的概述,不同的操作系统和处理器架构可能会有特定的实现细节。

开销来源

  1. 特权级切换
  2. 上下文保存与恢复
  3. 由于PTI的存在,内核维护了两套页表。切换到内核态时,可能需要切换内存地址空间的映射关系,例如将用户态的虚拟地址空间映射为内核态的地址空间。这可能涉及页表的切换和TLB(Translation Lookaside Buffer)的刷新,会带来一定的延迟和开销。

量化

内核态与用户态的切换时间在数百到数千个CPU周期之间

需要进一步的研究学习

暂无

遇到的问题

暂无

开题缘由、总结、反思、吐槽~~

参考文献

上面回答部分来自ChatGPT-3.5,没有进行正确性的交叉校验。