自制操作系统Antz day07——实现内核 (上)

简介: 在前几天的任务中,我们已经简单实现了MBR,直接操作显示器和硬盘操作来加载其他扇区的程序,如今已经可以进入保护模式了,简单引入了C语言,接下来我们编写自己的内核。

  Antz系统更新地址: https://www.cnblogs.com/LexMoon/category/1262287.html

  Linux内核源码分析地址:https://www.cnblogs.com/LexMoon/category/1267413.html

  Github地址:https://github.com/CasterWx 

  在前几天的任务中,我们已经简单实现了MBR,直接操作显示器和硬盘操作来加载其他扇区的程序,如今已经可以进入保护模式了,简单引入了C语言,接下来我们编写自己的内核。

0. 汇编生成ELF

  完成实模式到保护模式跳转的这一任务是由loader进行的,而我们不应该用loader做太多的事,loader只需要完成跳转就好了,剩下的工作交给内核。

  为了加载内核到内存,需要使用ELF格式,如何编译这种格式呢?

  来看看下面这个例子。

[section .data]

strHello    db    "Hello, Antz !", 0Ah
STRLEN        equ    $ - strHello


[section .text]    

global _start    

_start:
    mov    edx, STRLEN
    mov    ecx, strHello
    mov    ebx, 1
    mov    eax, 4        
    int    0x80        
    mov    ebx, 0
    mov    eax, 1
    int    0x80    

  global _start定义了程序的入口地址,相当于c/c++中main。

  接下来使用NASM编译。

  

  -f elf 指定了输出文件的格式为ELF格式。

  编译完成之后要进行链接,链接指令如下:

  

    (出现警告,在linux无警告,Windows下会有,可以无视)

  -s是strip的简写,可以去掉符号表等内容,对生成的可执行代码进行减肥。

 

1. 汇编与C语言共同使用

  我们已经可以生成一个支持载入内存的内核格式文件了,现在我们要学会把汇编程序和c语言程序链接在一起。这是我们编写内核的一大步。

  先来看看c代码:

    其中定义了一个choose函数,声明了一个myprint函数。

 1 void myprint(char* msg, int len);
 2 
 3 int choose(int a, int b)
 4 {
 5     if(a >= b){
 6         myprint("the 1st one\n", 13);
 7     }
 8     else{
 9         myprint("the 2nd one\n", 13);
10     }
11 
12     return 0;
13 }

 

  再来看看汇编代码:

 1 extern choose
 2 
 3 
 4 [section .data]    ; 数据在此
 5 
 6 num1st        dd    3
 7 num2nd        dd    4
 8 
 9 
10 [section .text]    ; 代码在此
11 
12 global _start    
13 global myprint    
14 
15 _start:
16     push    num2nd        
17     push    num1st        
18     call    choose        
19     add    esp, 4        
20 
21     mov    ebx, 0
22     mov    eax, 1        
23     int    0x80    
24 
25 ; void myprint(char* msg, int len)
26 myprint:
27     mov    edx, [esp + 8]    ; len
28     mov    ecx, [esp + 4]    ; msg
29     mov    ebx, 1
30     mov    eax, 4        ; sys_write
31     int    0x80    
32     ret
33     

  如果你懂汇编,这个代码一定没有如何问题。

  第一行的extern choose就是指c代码中定义的choose函数。

  后面的global导出了函数入口,_start和在c文件中没有定义的myprint函数,myprint在汇编代码中完成了定义。

  _start中调用了choose,choose中又调用了myprint函数。

  这样这两个代码文件内容就很清晰了吧。

  在Linux终端下查看结果:

1 nasm -f elf foo.asm -o foo.o
2 gcc -c bar.c -o bar.o
3 ld -s hello.o bar.o -o foobar
4 ./foobar

2. 从Loader到内核

  加载内核到内存和引导扇区的工作很相似,只是处理内核时我们要根据ELF文件结构中的值将内核中相应段放入相应位置。

  fat12hdr.inc :

 1 BS_OEMName    DB 'Antz__Os'
 2 
 3 BPB_BytsPerSec    DW 512    
 4 BPB_SecPerClus    DB 1        
 5 BPB_RsvdSecCnt    DW 1
 6 BPB_NumFATs    DB 2        
 7 BPB_RootEntCnt    DW 224    
 8 BPB_TotSec16    DW 2880        
 9 BPB_Media    DB 0xF0        
10 BPB_FATSz16    DW 9        
11 BPB_SecPerTrk    DW 18        
12 BPB_NumHeads    DW 2        
13 BPB_HiddSec    DD 0    
14 BPB_TotSec32    DD 0    
15 
16 
17 BS_DrvNum    DB 0        
18 BS_Reserved1    DB 0         
19 BS_BootSig    DB 29h    
20 BS_VolID    DD 0         
21 BS_VolLab    DB 'Tinix0.01  '
22 BS_FileSysType    DB 'FAT12   '    
23 
24 FATSz            equ    9     
25 RootDirSectors        equ    14    
26 
27 SectorNoOfRootDirectory    equ    19     
28 SectorNoOfFAT1        equ    1     
29 DeltaSectorNo        equ    17     
30                      

  boot.asm :

  1 org  07c00h        
  2 
  3 BaseOfStack        equ    07c00h 
  4 BaseOfLoader        equ    09000h
  5 OffsetOfLoader        equ    0100h
  6 
  7     jmp short LABEL_START 
  8     nop        
  9     
 10 
 11 %include    "fat12hdr.inc"
 12 
 13 LABEL_START:    
 14     mov    ax, cs
 15     mov    ds, ax
 16     mov    es, ax
 17     mov    ss, ax
 18     mov    sp, BaseOfStack
 19 
 20     
 21     mov    ax, 0600h        
 22     mov    bx, 0700h     
 23     mov    cx, 0         
 24     mov    dx, 0184fh     
 25     int    10h         
 26 
 27     mov    dh, 0         
 28     call    DispStr         
 29     
 30     xor    ah, ah     
 31     xor    dl, dl 
 32     int    13h    
 33 
 34     mov    word [wSectorNo], SectorNoOfRootDirectory
 35 LABEL_SEARCH_IN_ROOT_DIR_BEGIN:
 36     cmp    word [wRootDirSizeForLoop], 0    
 37     jz    LABEL_NO_LOADERBIN        
 38     dec    word [wRootDirSizeForLoop]    
 39     mov    ax, BaseOfLoader
 40     mov    es, ax         
 41     mov    bx, OffsetOfLoader     
 42     mov    ax, [wSectorNo]    
 43     mov    cl, 1
 44     call    ReadSector
 45 
 46     mov    si, LoaderFileName     
 47     mov    di, OffsetOfLoader     
 48     cld
 49     mov    dx, 10h
 50 LABEL_SEARCH_FOR_LOADERBIN:
 51     cmp    dx, 0                                     
 52     jz    LABEL_GOTO_NEXT_SECTOR_IN_ROOT_DIR     
 53     dec    dx                                         
 54     mov    cx, 11
 55 LABEL_CMP_FILENAME:
 56     cmp    cx, 0
 57     jz    LABEL_FILENAME_FOUND 
 58 dec    cx
 59     lodsb             
 60     cmp    al, byte [es:di]
 61     jz    LABEL_GO_ON
 62     jmp    LABEL_DIFFERENT         
 63     
 64 LABEL_GO_ON:
 65     inc    di
 66     jmp    LABEL_CMP_FILENAME     
 67 
 68 LABEL_DIFFERENT:
 69     and    di, 0FFE0h                     
 70     add    di, 20h                         
 71     mov    si, LoaderFileName                     
 72     jmp    LABEL_SEARCH_FOR_LOADERBIN
 73 
 74 LABEL_GOTO_NEXT_SECTOR_IN_ROOT_DIR:
 75     add    word [wSectorNo], 1
 76     jmp    LABEL_SEARCH_IN_ROOT_DIR_BEGIN
 77 
 78 LABEL_NO_LOADERBIN:
 79     mov    dh, 2             
 80     call    DispStr             
 81 %ifdef    _BOOT_DEBUG_
 82     mov    ax, 4c00h      
 83     int    21h         
 84 %else
 85     jmp    $         
 86 %endif
 87 
 88 LABEL_FILENAME_FOUND:         
 89     mov    ax, RootDirSectors
 90     and    di, 0FFE0h     
 91     add    di, 01Ah     
 92     mov    cx, word [es:di]
 93     push    cx             
 94     add    cx, ax
 95     add    cx, DeltaSectorNo     
 96     mov    ax, BaseOfLoader
 97     mov    es, ax             
 98     mov    bx, OffsetOfLoader     
 99     mov    ax, cx
100 
101 LABEL_GOON_LOADING_FILE:
102     push    ax        
103     push    bx             
104     mov    ah, 0Eh         
105     mov    al, '.'            
106     mov    bl, 0Fh            
107     int    10h         
108     pop    bx        
109     pop    ax             
110 
111     mov    cl, 1
112     call    ReadSector
113     pop    ax         
114     call    GetFATEntry
115     cmp    ax, 0FFFh
116     jz    LABEL_FILE_LOADED
117     push    ax         
118     mov    dx, RootDirSectors
119     add    ax, dx
120     add    ax, DeltaSectorNo
121     add    bx, [BPB_BytsPerSec]
122     jmp    LABEL_GOON_LOADING_FILE
123 LABEL_FILE_LOADED:
124 
125     mov    dh, 1            
126     call    DispStr            
127     
128     
129     jmp    BaseOfLoader:OffsetOfLoader    
130     
131     
132 wRootDirSizeForLoop    dw    RootDirSectors     
133 wSectorNo        dw    0        
134 bOdd            db    0        
135 
136 
137 LoaderFileName        db    "LOADER  BIN", 0 
138 
139 MessageLength        equ    9
140 BootMessage:        db    "Booting  ";  
141 Message1        db    "Ready.   "; 
142 Message2        db    "No LOADER";  
143 
144 
145 DispStr:
146     mov    ax, MessageLength
147     mul    dh
148     add    ax, BootMessage
149     mov    bp, ax            
150     mov    ax, ds            
151     mov    es, ax            
152     mov    cx, MessageLength     
153     mov    ax, 01301h         
154     mov    bx, 0007h         
155     mov    dl, 0
156     int    10h             
157     ret
158 
159  
160 ReadSector:
161     push    bp
162     mov    bp, sp
163     sub    esp, 2             
164 
165     mov    byte [bp-2], cl
166     push    bx         
167     mov    bl, [BPB_SecPerTrk]    
168     div    bl             
169     inc    ah             
170     mov    cl, ah     
171     mov    dh, al             
172     shr    al, 1             
173     mov    ch, al         
174     and    dh, 1         
175     pop    bx         
176     
177     mov    dl, [BS_DrvNum]         
178 .GoOnReading:
179     mov    ah, 2            
180     mov    al, byte [bp-2]        
181     int    13h
182     jc    .GoOnReading        
183     
184     add    esp, 2
185     pop    bp
186 
187     ret
188 
189 GetFATEntry:
190     push    es
191     push    bx
192     push    ax
193     mov    ax, BaseOfLoader     
194     sub    ax, 0100h         
195     mov    es, ax             
196     pop    ax
197     mov    byte [bOdd], 0
198     mov    bx, 3
199     mul    bx         
200     mov    bx, 2
201     div    bx             
202     cmp    dx, 0
203     jz    LABEL_EVEN
204     mov    byte [bOdd], 1
205 LABEL_EVEN:
206     xor    dx, dx         
207     mov    bx, [BPB_BytsPerSec]
208     div    bx            
209     
210     push    dx
211     mov    bx, 0             
212     add    ax, SectorNoOfFAT1     
213     mov    cl, 2
214     call    ReadSector         
215     pop    dx
216     add    bx, dx
217     mov    ax, [es:bx]
218     cmp    byte [bOdd], 1
219     jnz    LABEL_EVEN_2
220     shr    ax, 4
221 LABEL_EVEN_2:
222     and    ax, 0FFFh
223 
224 LABEL_GET_FAT_ENRY_OK:
225 
226     pop    bx
227     pop    es
228     ret
229     
230 times     510-($-$$)    db    0    
231 dw     0xaa55                

  loader.asm:

  1 org  0100h
  2  
  3 BaseOfStack        equ    0100h
  4 
  5 BaseOfKernelFile    equ     08000h     
  6 OffsetOfKernelFile    equ         0h    
  7 
  8     jmp    LABEL_START        
  9 
 10 
 11 %include    "fat12hdr.inc"
 12 
 13 
 14 LABEL_START:             
 15     mov    ax, cs
 16     mov    ds, ax
 17     mov    es, ax
 18     mov    ss, ax
 19     mov    sp, BaseOfStack
 20 
 21     mov    dh, 0         
 22     call    DispStr             
 23 
 24     
 25     mov    word [wSectorNo], SectorNoOfRootDirectory    
 26     xor    ah, ah 
 27     xor    dl, dl 
 28     int    13h    
 29 LABEL_SEARCH_IN_ROOT_DIR_BEGIN:
 30     cmp    word [wRootDirSizeForLoop], 0     
 31     jz    LABEL_NO_KERNELBIN         
 32     dec    word [wRootDirSizeForLoop]    
 33     mov    ax, BaseOfKernelFile
 34     mov    es, ax             
 35     mov    bx, OffsetOfKernelFile    
 36     
 37     mov    ax, [wSectorNo]         
 38     mov    cl, 1
 39     call    ReadSector
 40 
 41     mov    si, KernelFileName     
 42     mov    di, OffsetOfKernelFile     
 43     cld
 44     mov    dx, 10h
 45 LABEL_SEARCH_FOR_KERNELBIN:
 46     cmp    dx, 0                     
 47     jz    LABEL_GOTO_NEXT_SECTOR_IN_ROOT_DIR     
 48     dec    dx                     
 49     mov    cx, 11
 50 LABEL_CMP_FILENAME:
 51     cmp    cx, 0             
 52     jz    LABEL_FILENAME_FOUND     
 53     dec    cx             
 54     lodsb 
 55     cmp    al, byte [es:di]     
 56     jz    LABEL_GO_ON
 57     jmp    LABEL_DIFFERENT
 58 LABEL_GO_ON:
 59     inc    di
 60     jmp    LABEL_CMP_FILENAME
 61     
 62 LABEL_DIFFERENT:
 63     and    di, 0FFE0h         
 64     add    di, 20h            
 65     mov    si, KernelFileName
 66     jmp    LABEL_SEARCH_FOR_KERNELBIN
 67     
 68 LABEL_GOTO_NEXT_SECTOR_IN_ROOT_DIR:
 69     add    word [wSectorNo], 1
 70     jmp    LABEL_SEARCH_IN_ROOT_DIR_BEGIN
 71 
 72 LABEL_NO_KERNELBIN:
 73     mov    dh, 2             
 74     call    DispStr         
 75 %ifdef    _LOADER_DEBUG_
 76     mov    ax, 4c00h    
 77     int    21h            
 78 %else
 79     jmp    $         
 80 %endif
 81 
 82 LABEL_FILENAME_FOUND:             
 83     mov    ax, RootDirSectors
 84     and    di, 0FFF0h     
 85 
 86     push    eax
 87     mov    eax, [es : di + 01Ch]         
 88     mov    dword [dwKernelSize], eax 
 89     pop    eax
 90 
 91     add    di, 01Ah     
 92     mov    cx, word [es:di]
 93     push    cx         
 94     add    cx, ax
 95     add    cx, DeltaSectorNo
 96     mov    ax, BaseOfKernelFile
 97     mov    es, ax        
 98     mov    bx, OffsetOfKernelFile    
 99     mov    ax, cx         
100 
101 LABEL_GOON_LOADING_FILE:
102     push    ax         
103     push    bx             
104     mov    ah, 0Eh             
105     mov    al, '.'            
106     mov    bl, 0Fh             
107     int    10h         
108     pop    bx        
109     pop    ax         
110 
111     mov    cl, 1
112     call    ReadSector
113     pop    ax         
114     call    GetFATEntry
115     cmp    ax, 0FFFh
116     jz    LABEL_FILE_LOADED
117     push    ax             
118     mov    dx, RootDirSectors
119     add    ax, dx
120     add    ax, DeltaSectorNo
121     add    bx, [BPB_BytsPerSec]
122     jmp    LABEL_GOON_LOADING_FILE
123 LABEL_FILE_LOADED:
124 
125     call    KillMotor         
126 
127     mov    dh, 1             
128     call    DispStr         
129 
130     jmp    $
131 
132 
133     
134 wRootDirSizeForLoop    dw    RootDirSectors
135 wSectorNo        dw    0         
136 bOdd            db    0     
137 dwKernelSize        dd    0     
138 
139 
140 KernelFileName        db    "KERNEL  BIN", 0      
141 MessageLength        equ    9
142 LoadMessage:        db    "Loading  "
143 Message1        db    "Ready.   "
144 Message2        db    "No KERNEL"
145 
146 DispStr:
147     mov    ax, MessageLength
148     mul    dh
149     add    ax, LoadMessage
150     mov    bp, ax         
151     mov    ax, ds             
152     mov    es, ax         
153     mov    cx, MessageLength     
154     mov    ax, 01301h         
155     mov    bx, 0007h     
156     mov    dl, 0
157     add    dh, 3         
158     int    10h         
159     ret
160     
161 ReadSector:
162  
163     push    bp
164     mov    bp, sp
165     sub    esp, 2         
166 
167     mov    byte [bp-2], cl
168     push    bx             
169     mov    bl, [BPB_SecPerTrk]     
170     div    bl             
171     inc    ah        
172     mov    cl, ah            
173     mov    dh, al            
174     shr    al, 1             
175     mov    ch, al             
176     and    dh, 1             
177     pop    bx
178     
179     mov    dl, [BS_DrvNum]         
180 .GoOnReading:
181     mov    ah, 2            
182     mov    al, byte [bp-2]         
183     int    13h
184     jc    .GoOnReading        
185     
186     add    esp, 2
187     pop    bp
188 
189     ret 
190     
191 GetFATEntry:
192     push    es
193     push    bx
194     push    ax
195     mov    ax, BaseOfKernelFile 
196     sub    ax, 0100h         
197     mov    es, ax            
198     pop    ax
199     mov    byte [bOdd], 0
200     mov    bx, 3
201     mul    bx         
202     mov    bx, 2
203     div    bx         
204     cmp    dx, 0
205     jz    LABEL_EVEN
206     mov    byte [bOdd], 1
207 LABEL_EVEN:
208     xor    dx, dx             
209     mov    bx, [BPB_BytsPerSec]
210     div    bx            
211     
212     push    dx
213     mov    bx, 0         
214     add    ax, SectorNoOfFAT1     
215     mov    cl, 2
216     call    ReadSector         
217     pop    dx
218     add    bx, dx
219     mov    ax, [es:bx]
220     cmp    byte [bOdd], 1
221     jnz    LABEL_EVEN_2
222     shr    ax, 4
223 LABEL_EVEN_2:
224     and    ax, 0FFFh
225 
226 LABEL_GET_FAT_ENRY_OK:
227 
228     pop    bx
229     pop    es
230     ret
231     
232 KillMotor:
233     push    dx
234     mov    dx, 03F2h
235     mov    al, 0
236     out    dx, al
237     pop    dx
238     ret 

 

  加载功能已经有了,但是还没有内核给以上程序拿来加载。

  我们来实现一个最简单的内核,以后会基于此扩展。

  kernel.asm :

    此处的K不会打印,因为这里只是假设gs指向了显存。

1 [section .text]
2 
3 global _start     
4 
5 _start: 
6     mov    ah, 0Fh                ; 0000: 黑底    1111: 白字
7     mov    al, 'K'
8     mov    [gs:((80 * 1 + 39) * 2)], ax    ; 屏幕第 1 行, 第 39 列。
9     jmp    $

  

  出现了Ready,说明我们的kernel内核已经加载成功了。

 

目录
相关文章
|
2月前
|
存储 调度
探索操作系统的心脏:内核与用户空间的交互
在数字世界的每一次呼吸中,操作系统扮演着至关重要的角色。本文将深入探讨操作系统的核心组件——内核与用户空间之间的神秘舞蹈。通过直观的比喻和生动的代码片段,我们将一窥这场幕后的交响曲,了解它们是如何协同工作以支持我们的计算需求的。从简单的文件读写到复杂的网络通信,每一个操作背后都隐藏着内核与用户空间之间精妙的互动。准备好跟随我们的脚步,一起揭开操作系统的神秘面纱。
33 3
|
1月前
|
安全 Linux 开发者
探索操作系统的心脏:内核与用户空间的交互
在数字世界的每一次点击和命令背后,隐藏着一个复杂而精妙的操作系统世界。本文将带你走进这个世界的核心,揭示内核与用户空间的神秘交互。通过深入浅出的解释和直观的代码示例,我们将一起理解操作系统如何协调硬件资源,管理进程和内存,以及提供文件系统服务。无论你是编程新手还是资深开发者,这篇文章都将为你打开一扇通往操作系统深层原理的大门。让我们一起开始这段旅程,探索那些支撑我们日常数字生活的技术基石吧!
43 6
|
30天前
|
存储 缓存 网络协议
Linux操作系统的内核优化与性能调优####
本文深入探讨了Linux操作系统内核的优化策略与性能调优方法,旨在为系统管理员和高级用户提供一套实用的指南。通过分析内核参数调整、文件系统选择、内存管理及网络配置等关键方面,本文揭示了如何有效提升Linux系统的稳定性和运行效率。不同于常规摘要仅概述内容的做法,本摘要直接指出文章的核心价值——提供具体可行的优化措施,助力读者实现系统性能的飞跃。 ####
|
1月前
|
缓存 监控 网络协议
Linux操作系统的内核优化与实践####
本文旨在探讨Linux操作系统内核的优化策略与实际应用案例,深入分析内核参数调优、编译选项配置及实时性能监控的方法。通过具体实例讲解如何根据不同应用场景调整内核设置,以提升系统性能和稳定性,为系统管理员和技术爱好者提供实用的优化指南。 ####
|
2月前
|
存储 Linux 开发者
探索操作系统的内核——从理论到实践
操作系统是计算机科学的核心,它像一位默默无闻的指挥官,协调着硬件和软件之间的复杂关系。本文将深入操作系统的心脏——内核,通过直观的解释和丰富的代码示例,揭示其神秘面纱。我们将一起学习进程管理、内存分配、文件系统等关键概念,并通过实际代码,体验内核编程的魅力。无论你是初学者还是有经验的开发者,这篇文章都将带给你新的视角和知识。
|
1月前
|
机器学习/深度学习 人工智能 物联网
操作系统的心脏——深入理解内核机制
在本文中,我们揭开操作系统内核的神秘面纱,探索其作为计算机系统核心的重要性。通过详细分析内核的基本功能、类型以及它如何管理硬件资源和软件进程,我们将了解内核是如何成为现代计算不可或缺的基础。此外,我们还会探讨内核设计的挑战和未来趋势,为读者提供一个全面的内核知识框架。
|
1月前
|
消息中间件 安全 Linux
深入探索Linux操作系统的内核机制
本文旨在为读者提供一个关于Linux操作系统内核机制的全面解析。通过探讨Linux内核的设计哲学、核心组件、以及其如何高效地管理硬件资源和系统操作,本文揭示了Linux之所以成为众多开发者和组织首选操作系统的原因。不同于常规摘要,此处我们不涉及具体代码或技术细节,而是从宏观的角度审视Linux内核的架构和功能,为对Linux感兴趣的读者提供一个高层次的理解框架。
|
2月前
|
存储 调度 开发者
探索操作系统的心脏:内核与用户空间的交互之旅
在数字世界的无限广阔中,操作系统扮演着枢纽的角色,连接硬件与软件,支撑起整个计算生态。本篇文章将带领读者深入操作系统的核心——内核,揭示其与用户空间的神秘交互。我们将透过生动的例子和易于理解的比喻,深入浅出地探讨这一复杂主题,旨在为非专业读者揭开操作系统的神秘面纱,同时为有一定基础的读者提供更深层次的认识。从进程管理到内存分配,从文件系统到设备驱动,每一个环节都是精确而优雅的舞蹈,它们共同编织出稳定而高效的计算体验。让我们开始这场奇妙之旅,一探操作系统背后的科学与艺术。
32 5
|
2月前
|
缓存 并行计算 Linux
深入解析Linux操作系统的内核优化策略
本文旨在探讨Linux操作系统内核的优化策略,包括内核参数调整、内存管理、CPU调度以及文件系统性能提升等方面。通过对这些关键领域的分析,我们可以理解如何有效地提高Linux系统的性能和稳定性,从而为用户提供更加流畅和高效的计算体验。
36 2
|
2月前
|
缓存 网络协议 Linux
深入探索Linux操作系统的内核优化策略####
本文旨在探讨Linux操作系统内核的优化方法,通过分析当前主流的几种内核优化技术,结合具体案例,阐述如何有效提升系统性能与稳定性。文章首先概述了Linux内核的基本结构,随后详细解析了内核优化的必要性及常用手段,包括编译优化、内核参数调整、内存管理优化等,最后通过实例展示了这些优化技巧在实际场景中的应用效果,为读者提供了一套实用的Linux内核优化指南。 ####
51 1