Linux内核入门(五)——必要的硬件知识

Linux驱动开发入门(内核态用户态) 确认你的环境:确保你正在使用一台运行Linux操作系统的计算机。对于驱动程序开发,最好是选择一个具备良好的硬件支持和最新内核版本的Linux发行版。了解设备驱动程序的类型:在Linux中,驱动程序通常分为字符设备驱动和块设备驱动两种类型。字符设备驱动用于处理像终端、键盘等字符流的设备,而块设备驱动用于处理像硬盘、固态驱动器等块数据的设备。学习Linux设备模型:Linux内核采用一种称为设备模型的框架来管理和表示设备。学习如何在设备模型中注册设备、分配和释放资源以及与设备进行交互是非常重要的。 阅读详情

作原理,就必须懂点基本的硬件知识。这里我们主要介绍Intel 80x86系列CPU保护模式下最核心的部件中几个寄存器的作用,这些寄存器在Linux内核运行时起着至关重要的作用。至于其他那些各式各样的硬件设备,我们在讲解设备驱动时会针对具体的驱动程序来介绍的。首先,大家先看看CPU的主要架构:

EU(通用寄存器、运算器和控制器)执行部件:完成指令所要求的功能。
SU(段寄存器、段转换器)分段部件:完成执行单元的地址请求, 将虚地址转换为线性地址。
PU(TLB、页转换器)分页部件:将线性地址转换为物理地址。
BIU(总线接口)接口部件:完成指令预取请求和执行单元的数据存取请求,数据存取请求优先于指令预取请求。
IPU(控制逻辑和预取队列)预取部件:16字节指令预取队列, 提出预取请求。
IDU(指令译码、6字节指令队列)译码部件:完成指令译码功能。
FPU(片内集成了浮点协处理器):专用于浮点运算的处理部件。

下面,我们针对EU、SU和PU模块做做详细说明,其他模块就暂时不介绍了,相应的Linux专题会涉及到的。

1 EU模块

EU模块是CPU中最核心,最重要的部件。现在的奔腾CPU已经发展了若干年了,但其中最起作用的还是加法单元ALU,一组通用寄存器组、一个标志和控制逻辑。如图:

首先,8个32位通用寄存器按使用情况分为三种:指针寄存器、变址寄存器、数据寄存器。

[1] 指针寄存器:主要提供全部或部分偏移量
    
ESP:专门存放堆栈段中栈顶单元的偏移量。
EBP:存放堆栈段中某个单元的全部/部分偏移量,也可存放32位或16位操作数或运算结果。

[2] 变址寄存器

ESI/EDI:存放主存操作数的全部/部分偏移量,也可存放16位操作数和结果,在多数情况功能可以互换。 但在串操作指令中作用不能互换,源

操作数必须用ESI提供偏移量,目的操作数必须用EDI提供偏移量。
  
[3] 数据寄存器

◆ 数据寄存器既可以作为4个32位的寄存器,也可以作为8个16位的寄存器 ,还可以作为16个8位的寄存器。
◆ 在程序中,数据寄存器用来存放操作数、运算结果或其他信息。
◆ 数据寄存器在许多指令中要求指明使用,但也有隐含或特定使用,详细情况请查阅相关资料。

其次,4个控制寄存器CR0~CR3

[1] CR0:由80286的MSW寄存器演变而来,并增加了2位,Linux最看重他的PG位——PG=0,允许分页;PG=1,不允许分页。
[2] CR1:未使用
[3] CR2:页故障地址寄存器, 存放出现故障的页的32位线性地址
[4] CR3:页目录基地址寄存器, 存放页目录表的基地址。 

最后来看看标志寄存器FR

FR用来记录程序执行时的状态,即两个操作数通过ALU后的状态:

[1] 进位标志位CF(Carry Flag)
[2] 奇偶标志位PF(Parity Flag)
[3] 辅助进位标志位AF(Auxiliary Carry Flag)
[4] 零值标志位ZF(Zero Flag)
[5] 符号标志位SF(Sign Flag)
[6] 溢出标志位OF(Overflow Flag)
[7] 单步标志位TF(Trace Flag)
[8] 中断标志位IF(Interrupt-enable Flag)
[9] 方向标志位DF(Direction Flag)

 

2 SU模块

下面着重看看SU部件。这个部件也被Linux用到了,但Linux用它的目的并不是遵循Intel手册对地址进行虚拟化,而是利用它来做用户态和内核态的切换。而对地址的虚拟化,则是通过PU单元,也就是分页机制来实现的,具体的内容将在内存管理专题中详细阐述。

首先来看看SU模块的架构图:

处理器提供了6个段寄存器,段寄存器的唯一的目的是存放选择子(16位)。这些段寄存器称为cs, ss, ds, es, fs和gs。尽管只有6个段寄存器,但程序可以把同一个段寄存器用于不同的目的,方法是先将其值保存在存储器中,用完后再恢复。

6个寄存器中3个有专门的用途:
cs——代码段寄存器,指向包含程序指令的段。
ss——栈段寄存器,指向包含当前程序栈的段。
ds——数据段寄存器,指向包含静态数据或者全局数据的段。

其它三个段寄存器作一般用途,可以指向任意的数据段。

每个段由一个8字节的描述子(Segment Descriptor)表示,它描述了段的特征。描述子放在全局描述符表(Global Descriptor Table, GDT)或局部描述符表(Local Descriptor Table, LDT)中,这些表位于内存中,如图所示。如果是多CPU,则每个CPU定义一个GDT,而每个进程除了存放在GDT中的段之外如果还需要创建附加的段,就可以有自己的LDT。GDT在主存中的基地址和大小存放在gdtr处理器寄存器中,当前正被使用的LDT地址和大小放在ldtr处理器寄存器中。

虚拟地址由16位选择子和32位偏移量组成,段寄存器仅仅存放选择子。CPU的分段单元(SU)执行以下操作:
[1] 先检查选择子的TI字段,以决定描述子对应的描述子保存在哪一个描述符表中。TI字段指明描述子是在GDT中(在这种情况下,分段单元从gdtr寄存器中得到GDT的线性基地址)还是在激活的LDT中(在这种情况下,分段单元从ldtr寄存器中得到LDT的线性基地址)。
[2] 从选择子的index字段计算描述子的地址,index字段的值乘以8(一个描述子的大小,其实就是屏蔽掉末尾那三位指示特权级的CPL和指示TI的字段),这个结果与gdtr或ldtr寄存器中的内容相加。
[3] 将对应的描述子从内存拷贝到CPU的隐Cache中,这样,只有在选择子改变的情况下才会修改Cache中的内容。
[4] 把逻辑地址的偏移量与隐Cache中描述子Base字段的值相加就得到了线性地址。
 
请注意,多亏了与段寄存器相关的不可编程的隐Cache,只有当段寄存器的内容被改变时才需要执行前三个操作。

LDT在Linux中使用得很少,我们就不细说他了,它跟我们下面讲的IDT差不多。

中断描述符表(Interrupt Descriptor Table,IDT)是一个系统表,它与每一个中断或异常向量相联系,每一个向量在表中有相应的中断或异常处理程序的入口地址。内核在允许中断发生前,必须适当地初始化IDT。

IDT的格式与这GDT和LDT的格式非常相似,表中的每一项对应一个中断或异常向量,每个向量由8个字节组成。因此,最多需要256×8=2048字节来存放IDT(Linux有256个中断向量)。

idtr寄存器使IDT可以位于内存的任何地方,它指定IDT的线性基地址及其大小(最大长度)。在允许中断之前,必须用lidt汇编指令初始化idtr。

IDT包含三种类型的描述符,下图显示了每种描述符中的64位的含义。尤其值得注意的是,在40~43位的Type字段的值表示描述符的类型。

这里还要提一个问题,就是TSS技术是个很过时的技术,Linux并没有按照Intel要求的那样把TSSD(任务门)存放到IDT中,而是存放在全局描述符GDT中。每个CPU的tr寄存器包含了对应TSS的TSSD选择符(这个选择符可以编程),还包含了两个隐藏的非编程字段:TSSD的Base字段和Limit字段作为隐Cache,这样,处理器就能直接对TSS寻址而不用从GDT中检索TSS的地址。TSS这个东西主要用来在进程切换的时候保存部分CPU寄存器的内容(其实就主要是堆栈切换的时候使用到的那些寄存器)。Linux只为每个CPU准备一个TSS数据结构——tss_struct,只是用来存放当前进程的部分寄存器内容,并没有按照Intel推荐的那样为每个进程准备一个TSS数据结构,并存放所有的内容。所以,按照我的理解,每个进程的那个thread_struct结构存放的内容就是当进程被执行的时候需要tss_struct记住的那些寄存器的内容。

当执行了一条指令后,CS和eip这对寄存器包含下一条将要执行的指令的逻辑地址。在处理那条指令之前,控制单元会检查在运行前一条指令时是否已经发生了一个中断或异常。如果发生了一个中断或异常,那么控制单元执行下列操作:

1. 确定与中断或异常关联的向量i (0 ≤ i ≤ 255)。
2. 读由idtr寄存器指向的 IDT表中的第i项。
3. 从gdtr寄存器获得GDT的基地址,并在GDT中查找,以读取IDT表项中的选择符所标识的段描述符。这个描述符将会是一个中断门或者一个陷阱门,其含有指定中断或异常处理程序所在段的基地址。
4. 确信中断是由授权的(中断)发生源发出的。首先将当前特权级CPL(存放在cs寄存器的低两位)与段描述符(存放在GDT中)的描述符特权级DPL比较,如果CPL小于DPL,就产生一个“General protection”异常,因为中断处理程序的特权不能低于引起中断的程序的特权。对于编程异常,则做进一步的安全检查:比较CPL与处于IDT中的门描述符的DPL,如果DPL小于CPL,就产生一个“General protection”异常。这最后一个检查可以避免用户应用程序访问特殊的陷阱门或中断门。
5. 检查是否发生了特权级的变化,也就是说,CPL是否不同于所选择的段描述符的DPL。如果是,控制单元必须开始使用与新的特权级相关的栈。通过执行以下步骤来做到这点:

i. 读tr寄存器,以访问运行进程的TSS段。

ii. 用与新特权级相关的栈段和栈指针的正确值装载ss和esp寄存器。这些值可以在TSS中找到。

iii. 在新的栈中保存ss和esp以前的值,这些值定义了与旧特权级相关的栈的逻辑地址。

6. 如果故障已发生,用引起异常的指令地址装载CS和eip寄存器,从而使得这条指令能再次被执行。
7. 在栈中保存eflags、CS及eip的内容。
8. 如果异常产生了一个硬件出错码,则将它保存在栈中。
9. 装载cs和eip寄存器,其值分别是IDT表中第i项门描述符的段选择符和偏移量字段。这些值给出了中断或者异常处理程序的第一条指令的逻辑地址。

控制单元所执行的最后一步就是跳转到中断或者异常处理程序。换句话说,处理完中断信号后,控制单元所执行的指令就是被选中处理程序的第一条指令。

中断或异常被处理完后,相应的处理程序必须产生一条iret指令,把控制权转交给被中断的进程,这将迫使控制单元:

1. 用保存在栈中的值装载CS、eip或eflags寄存器。如果一个硬件出错码曾被压入栈中,并且在eip内容的上面,那么,执行iret指令前必须先弹出这个硬件出错码。
2. 检查处理程序的CPL是否等于CS中最低两位的值(这意味着被中断的进程与处理程序运行在同一特权级)。如果是,iret终止执行;否则,转入下一步。
3. 从栈中装载ss和esp寄存器,因此,返回到与旧特权级相关的栈。
4. 检查ds、es、fs及gs段寄存器的内容,如果其中一个寄存器包含的选择符是一个段描述符,并且其DPL值小于CPL,那么,清相应的段寄存器。控制单元这么做是为了禁止用户态的程序(CPL=3)利用内核以前所用的段寄存器(DPL=0)。如果不清这些寄存器,怀有恶意的用户态程序就可能利用它们来访问内核地址空间。

 

3 PU模块
分页单元PU模块的目的是把线性地址转换成物理地址。其中一个关键任务是把所请求的访问类型与线性地址的访问权限相比较,如果这次内存访问是无效的,就产生一个缺页异常。

分页单元把所有的主存看成一块一块的,称其为页框(page frame)(有时叫做物理页)。每一个页框是固定的大小(跟分段的最大区别,一般为32位处理器为4k、64位处理器为64k)包含一个页(page)。

把线性地址映射到物理地址的数据结构称为页表(page table),其存放在主存中,并在启用分页单元之前必须由内核对页表进行适当的初始化。从80386开始,所有的80x86处理器都支持分页,它通过设置cr0寄存器的PG标志启用。当PG=0时,线性地址就被解释成物理地址。

从80386起,Intel处理器的分页单元处理4KB的页。32位的线性地址被分成3个字段:
目录(Directory)——最高10位
页表(Table)——中间10位
偏移量(Offset)——最低12位

当一个进程运行时,必须有一个分配给它的页目录,其每一个目录项指向一个页表的地址。不过,没有必要马上为进程的所有页表都分配内存。Linux是在当进程实际需要一个页表时才给该页表分配RAM以提高效率。

正在使用的页目录的物理地址存放在控制寄存器cr3中。线性地址内的最高10位(Directory字段)决定页目录中的目录项,而目录项指向适当的页表。地址的中间10位(Table字段)依次又决定页表中的表项,而表项含有页所在页框的物理地址。最低12位(Offset字段)决定页框内的相对位置(见图)。由于它是12位长,故每一页含有4096字节的数据。

页表转æ¢

 

页目录项和页表项有同样的结构,每项的内容主要包括对应页(页表也是一个页)的索引以及对应页的状态,我们将在存储管理中分段Linux分段分页机制博文中详细介绍。

下面再来谈谈分页的硬件保护方案,分页单元和分段单元的保护方案不同。尽管80x86处理器允许一个段使用四种可能的特权级别,但与页和页表相关的特权级只有两个,由页目录项和页表项有同样的结构的User/Supervisor标志所控制。若这个标志为0,只有当CPL小于3(这意味着对于Linux而言,处理器处于内核态)时才能对页寻址;若该标志为1,则总能对页寻址。

此外,与段的三种存取权限(读,写,执行)不同的是,页的存取权限只有两种(读,写)。如果页目录项或页表项的Read/Write标志等于0,说明相应的页表或页是只读的,否则是可读写的。

 

4 高速缓存
当今的微处理器时钟频率接近几个GHZ,而动态RAM(DRAM)芯片的存取时间是时钟周期的数百倍。这意味着,当从RAM中取操作数或向RAM中存放结果这样的指令执行时,CPU可能等待很长时间。

为此,80x86体系结构中引入了一个叫行(line)的新单位。行由几十个连续的字节组成,它们以脉冲突发模式(burst mode)在慢速DRAM和快速的片上静态RAM(SRAM)之间传送,用来实现高速缓存。

具体的高速缓存实现细节太复杂,我只简单地说说原理:当访问一个RAM存储单元时,CPU从物理地址中提取出子集的索引号并把子集中所有行的标签与物理地址的高几位相比较。如果发现某一个行的标签与这个物理地址的高位相同,则CPU命中一个高速缓存(cache hit);否则,高速缓存没有命中(cache miss)。

当命中一个高速缓存时,高速缓存控制器的操作不同,具体取决于存取类型。 对于读操作,控制器从高速缓存行中选择数据并送到CPU寄存器;RAM不被访问且节约了CPU时间,因此,高速缓存系统起到了其应有的作用。对于写操作,控制器可能采用以下两个基本策略之一,分别称之为通写(writethrough)和回写(writeback)。在通写中,控制器总是既写RAM 也写高速缓存行,为了提高写操作的效率关闭高速缓存。回写方式只更新高速缓存行,不改变RAM的内容,提供了更快的功效。当然,回写结束以后,RAM最终必须被更新。只有当CPU执行一条要求刷新高速缓存表项的指令时,或者当一个FLUSH硬件信号产生时(通常在高速缓存不命中发生之后), 高速缓存控制器才把高速缓存行写回到RAM中。

当高速缓存没有命中时,高速缓存行被写回到内存中,如果有必要的话,把正确的行从RAM中取出放到高速缓存的表项中。很复杂吧?我们应该大肆庆幸,因为所有这一切都在硬件级处理,内核根本不需要关心。

高速缓存技术正在快速向前发展。例如,第一代Pentium芯片包含一颗称为L1-cache的片上高速缓存。近期的芯片又包含另外的容量更大,速度较慢,称之为L2-cache,L3-cache的片上高速缓存。多级高速缓存之间的一致性是由硬件实现的。Linux忽略这些硬件细节并假定只有一个单独的高速缓存。

处理器的cr0寄存器的CD标志位用来启用或禁用高速缓存电路。这个寄存器中的NW标志指明高速缓存是使用通写还是回写策略。

除了通用硬件高速缓存之外, 80x86处理器还包含了另外一个称之为翻译后备缓冲器或TLB(Translation Lookaside Buffer,有些书上也把这组寄存器叫做“联想存储器”)的高速缓存用于加快线性地址的转换。当一个线性地址被第一次使用时,通过慢速访问RAM中的页表计算出相应的物理地址。同时,物理地址被存放在一个TLB表项(TLB entry)中,以便以后对同一个线性地址的引用就可以快速地得到转换,如图。

å表

 

例如CPU给出有效地址为(D,P,W),它把页号P送入输入寄存器,随后立即和TLB各单元的页号进行比较,如与某个单元中的页号相匹配,则把该单元中的块号B送入输出寄存器。这样,就可以用(D,B,W)访问相应的主存单元。

在多处理系统中,每个CPU都有自己的TLB,这叫做该CPU的本地TLB。与硬件高速缓存相反,TLB中的对应项不必同步,这是因为运行在现有CPU上的进程可以使同一线性地址与不同的物理地址发生联系。

当CPU的cr3控制寄存器被修改时,硬件自动使本地TLB中的所有项都无效,这是因为新的一组页表被启用而TLB指向的是旧数据。

ARM-Linux内核基础知识 文章目录系列文章一、ARM-Linux内核和普通内核的区别1.Linux内核2. ARM-Linux内核二、Linux 模块概述1. 与module相关的命令有2. 模块命令三、模块的加载四、模块的卸载五、ARM-Linux系统的启动和初始化六、移植的基本概念1. 从一个硬件平台移植到另外一个硬件平台- Linux操作系统移植。- 内核移植2. 从一个操作系统移植到另一个操作系统3. 从一种软件库环境移植到另一种软件库环境 系列文章 ARM-Linux内核知识点 Linux之交叉编译器的构建 一、ARM 阅读详情

相关推荐

Linux内核入门(一)——小白学ARM

Linux内核入门(一)——小白学ARM前言LINUX的前世今生LINUX系统整体结构LINUX内核中的各模块功能1.文件系统2.内存管理模块3.进程管理模块&进程间通信模块4.驱动管理模块 前言 小白之前一直跟着正点原子的教程学Linux嵌入式驱动开发,但总觉得少了点什么,现在回头来看,发现是对LINUX内核的一些基础知识缺乏了解。 例如说,教程里教你移植内核,教你写驱动,教你并发与竞争,但是,缺少一个整体框架,就容易学的云里雾里,所以小白觉得,学之前,还是得学一下LINUX的一些知识。 LINU

qq_38406667的博客 851

CPU为什么这么贵,微机来解答

制作工艺: 我们知道第一款计算机的体积十分庞大,运算速度也很慢,不能进行存储。后来的冯氏结构才解决这一问题。体积大就是因为集成度不高,ALU是由晶体管组成,我们知道,电路分小规模集成电路,大规模集成电路,超大规模集成电路。我们要在一个指甲大的地方集成几亿晶体管,可见要求的技术之高。 CPU的功能: 微型计算机系统由三大部分组成:微型计算机系统——微型计算机——微处理器(详解可以参考我的一二章总结http://t.csdn.cn/2hrbAhttp://t.csdn.cn/2hrbA)。微处理器即CP

weixin_51250562的博客 1371

GNSS接收机性能测试指标详解:TTFF、位置精度、灵敏度等关键参数如何评估

本文详细解析了GNSS接收机性能测试的关键指标,包括首次定位时间(TTFF)、位置精度、灵敏度等,帮助工程师系统评估接收机性能。通过多频段协同定位和载波相位测试等技术,提升定位精度至亚米级。同时,介绍了灵敏度测试的极限挑战和授时精度的专业测试方案,为GNSS接收机的性能优化提供实用指导。

cuda7parallel的博客 960

Intel 8086/8088 CPU 寄存器结构

<br />1. 段寄存器<br /> <br />需执行程序的各部分(指令代码、数据、堆栈)分别放在主存的指定段中。<br /> <br />段寄存器:用来存放每个段的段基值,即段基址的高16位,每个段寄存器有特定功能,不能互换。<br /> <br />当前段:由CS、DS、SS、ES指向的段,如图:<br /> <br /><br /> <br />CS ----- 代码段用来存放程序的指令代码序列,CS用来存放当前代码段首址的高16位,即段基值。<br /> <br />DS ----- 数据段用来

林学森的技术专栏 3171

centos7部署mysql8.0.35,主从复制,主主集群

centos7 linux部署mysql,主从复制,主主模式

zaixiaqin的博客 1989

保姆级教程:用YOLOv5s搞定钢材表面缺陷检测,从数据集NEU-DET到模型部署全流程

本文提供了一份详细的YOLOv5s钢材表面缺陷检测教程,涵盖从NEU-DET数据集处理到模型部署的全流程。针对工业环境中的实际限制,如计算资源有限和标注样本少等问题,提供了优化方案和实用技巧,帮助开发者快速实现高效的钢材缺陷检测系统。

weixin_30568591的博客 463

Linux内核入门(七)—— 必要的编译知识

所有的内核代码,基本都包含了include/linux/compile.h这个文件,所以它是基础,涵盖了分析内核所需要的一些列编译知识,本博就分析分析这个文件里的代码:#ifndef __LINUX_COMPILER_H#define __LINUX_COMPILER_H#ifndef __ASSEMBLY__首先印入眼帘的是对__ASSEMBLY__这个宏的判断,这个

云(存储),松(耦合) 6641

腾讯滑块验证码collect参数逆向与JSVMP对抗实战

本文深入解析腾讯滑块验证码collect参数的逆向过程与JSVMP虚拟机对抗技术。通过详细的环境搭建、抓包分析和JSVMP逆向技巧,揭示collect参数的生成逻辑与加密流程,并提供完整的模拟实现方案和常见问题排查方法,助力开发者突破腾讯天御验证码的防护机制。

weixin_29009501的博客 1573

Linux内核学习路线 有入门到深入

学习linux内核,这个可不像学一门语言,c或者java一个月或者3月你就能精通掌握。学习linux内核是需要一步一步循序渐进,掌握正确的linux内核学习路线对学习至关重要,本篇文章就来分享学习linux内核的一些建议吧。 1. 了解操作系统基本概念。如果不会,可以学习《操作系统:设计与实现》Andrew S.Tanenbaum 写的那本。以MINIX为例子讲解操作系统的概念。非常推荐。 2. 有了操作系统的基本概念以后,可以了解Linux的机制了。推荐《Linux内核设计与实现》Robert L.

终码一生 6247

半导体设备上位机开发:我的经验与新人指导

半导体设备上位机开发是一项复杂而富有挑战性的工作,需要扎实的技术基础和丰富的经验。如果你对半导体设备上位机开发感兴趣,欢迎随时与我交流,我会尽力帮助你!

qq_43518667的博客 2726

生信人的一天~HIFI数据+HIC数据组装基因组

HIFI+HIC数据组装基因组!

qq_43337286的博客 9527

【Linux内核设计思想】一、Linux内核介绍

Linux内核设计思想与源码分析一:Linux内核相关知识介绍。

仅以此博客记录日常学习工作中所思所得,水平有限,难登大雅,万望海涵。 2850

基于Simulink的电机功率因数校正仿真

PF=SP​=视在功率有功功率​=cosϕ⋅Irms​I1​​(非正弦时)位移因数(cosϕ):基波电压电流相位差畸变因数(I1​/Irms​):谐波导致电流有效值增大本文带你完成了电机系统功率因数校正的Simulink仿真,实现了:✅ 理解了低功率因数的成因与危害✅ 搭建了无PFC、无源PFC、有源PFC三种对比模型✅ 掌握了Vienna整流器建模与dq解耦控制方法✅ 实现了PF与THD的自动计算与评估✅ 验证了有源PFC在PF、THD、稳定性上的全面优势。

amy_mhd的博客 154

linux内核编译入门,Linux内核入门(七)—— 必要的编译知识

Linux内核入门(七)—— 必要的编译知识所有的内核代码,基本都包含了include/linux/compile.h这个文件,所以它是基础,涵盖了分析内核所需要的一些列编译知识,本博就分析分析这个文件里的代码:#ifndef __LINUX_COMPILER_H#define __LINUX_COMPILER_H#ifndef __ASSEMBLY__首先印入眼帘的是对__ASSEMBLY__这...

weixin_39704246的博客 243

Qt实现窗口自适应分辨率大小

如果希望窗口大小始终保持与屏幕分辨率一致,可以将上述代码放在窗口的resizeEvent()函数中。这样,每当窗口大小发生变化时,都会自动调用resizeEvent()函数,从而实现窗口大小的自适应调整。在Qt中,可以通过一些简单的方法实现窗口大小随分辨率变化而自适应调整。获取到当前屏幕的分辨率后,可以根据需要调整窗口的大小。无论在何种分辨率下运行应用程序,窗口都能够正确地自动调整大小,提供更好的用户体验。除了调整窗口大小,还可以考虑将窗口设置为最大化,以充分利用屏幕空间。步骤2:调整窗口大小。

FuJavascript的博客 3654

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

开发Linux内核驱动需要知道哪些知识

成为一名合格的 Linux 驱动开发工程师需要掌握广泛的知识和技能,并具备持续学习和解决问题的能力。建议您从基础知识入手,逐步深入学习 Linux 内核和驱动开发技术,并通过实践不断提升自己的能力。书籍《Linux 设备驱动程序》(Linux Device Drivers, 3rd Edition)《深入理解 Linux 内核》(Understanding the Linux Kernel, 3rd Edition)

远方雪的专栏 1564

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Linux内核学习的非必要性,是不是每个开发者都需要学习Linux内核?

这本《深入Linux内核》相信很多程序员的书柜上都有这本书,但是真正能够啃完理解其中技术的在我看来可能少之又少,不知道有没有它书籍销量的百分之一。 这里我不禁就产生了一个疑问:Linux内核是不是需要大多数程序员都去了解学习? 对于本身正在从事或就要从事内核开发的人来说,这个当然不是一个问题。但是对于那些用户态写server的人,学内核的目的是什么,学到的知识能不能/要不要/如何用到日常开发中,这是值得思考的。 所以你是为什么要去学习Linux内核的? 我学习Linux内核一个原因是目前在工作上需要掌握内.

技术Q君样:202432010的博客 920

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

linux内核教程

微信可以设置雪花昵称了,真漂亮!!! 如何入门 Linux 内核 首先,让我们看看如何获取、构建并运行 Linux 内核。你可以通过两种方式来运行你自己定制的内核: 在虚拟机里运行 Linux 内核; 在真实的硬件上运行 Linux 内核。 1 2 我会对这两种方式都展开描述。在我们开始对 Linux 内核做些什么之前,我们首先需要先获取它。根据你目的的不同,有两种方式可以做到这一点。如果你只是想更新一下你电脑上的 Linux 内核版本,那么你可以使用特定于你 Linux 发行版的命令。 快捷键 加粗 Ct

manongxianfeng的博客 6259

shell linux内核 硬件,linux系统组成——硬件、内核、shell

linux系统由硬件、内核、shell三部分组成 硬件由CPU、内存、硬盘、磁盘阵列卡、输入/输出设备等物理设备共同组成 linux内核主要负责驱动硬件(加载驱动)、管理活动(进程管理)和分配/管理硬件资源(内存管理)系统的内核参数使用sysctl命令可以进行查看[root@localhost ~]# sysctl -a|grep shmmaxkernel.shmmax = 18446744073...

weixin_29798625的博客 1199

【Linux】Linux内核编译与入门

linux内核编译与入门

DevFrank的博客 3749

Linux内核学习路线 ,应从入门到深入,学内核就来零声教育

学习linux内核,这个可不像学一门语言,c或者java一个月或者3月你就能精通掌握。学习linux内核是需要一步一步循序渐进,掌握正确的linux内核学习路线对学习至关重要,本篇文章就来分享学习linux内核的一些建议吧。 1. 了解操作系统基本概念。如果不会,可以学习《操作系统:设计与实现》Andrew S.Tanenbaum 写的那本。以MINIX为例子讲解操作系统的概念。非常推荐。 2. 有了操作系统的基本概念以后,可以了解Linux的机制了。推荐《Linux内核设计与实现》Robert Lov

csbmww的博客 5739

Ubuntu Linux HWE 内核科普 – Linux 小知识_hwe内核

这就是 HWE 内核产生的目的,从上游社区及时引入 Ubuntu LTS 版本并测试调整,形成适应新硬件的、功能更强的新内核,即“硬件启用(HWE,HardWare Enablement)内核”。Ubuntu 20.04 LTS 系列,在安装系统时,如果是在现在普通的 UEFI 硬件系统上,桌面版 ISO(如:ubuntu-20.04.5-desktop-amd64.iso)安装,默认是安装 HWE 内核,有些版本安装菜单会有 OEM 可选项;这样,这些内核都经过了较长时间的使用与测试了。

2401_85147537的博客 1766
上一篇: Linux内核入门(一)——体系架构
下一篇: 架构决定可扩展性--聊聊用户态协议栈的意义
废言Pro
博客等级 码龄16年 1092粉丝 142原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值