您的位置:首页 > 运维架构 > Linux

linux内核完全注释【读书笔记】

2015-03-30 14:21 141 查看
版本:Linux-0.11

Linux内核源代码目录结构:

包含14个子目录,共102个代码文件。

1.Makefile文件:

*1*Makefile,是编译辅助工具软件make的参数配置文件,make工具软件的主要用途是通过识别那些文件已被修改,从而自动的决定在一个含有多个源程序文件的程序系统中那些文件需要被重新编译。

该文件描述了整个程序包中各个程序之间的关系,并针对每个需要更新的文件给出具体的控制命令。

2.引导程序启动目录boot:

包含3个汇编语言文件,是内核源代码文件中最先被编译的程序。

*2*bootsect.s代码是磁盘引导块程序,驻留在磁盘第一个扇区中。

主要作用是:

首先将setup模块(由setup.s编译而成)从磁盘加载到内存中紧接着bootsect后面的位置(0x90200)

然后利用bios中断0x13取磁盘参数表中当前启动引导盘的参数,接着在屏幕上显示“loading system…”字符串。

再将system模块从磁盘上加载到内存0x10000开始的地方。随后确定根文件系统的设备号

最后长跳转到setup程序的开始处(0x90200)执行setup程序。

(从硬盘启动时,通常内核映像文件image存放在活动分区的根文件系统中。因此需要知道image处于文件系统中的位置以及是什么样的文件系统)

*3*setup.s程序。

主要作用:

利用bios中断读取机器系统数据,并将这些数据保存到0x90000开始的位置(覆盖掉bootsect程序所在的位置)

然后将system模块从0x10000-0x8ffff整块移动到内存绝对地址0x00000处。

接下来加载中断描述符表寄存器(idtr)和全局描述符表寄存器(gdtr),开启A20地址线(实现地址线的兼容),(为进入保护模式做准备?)重新设置两个中断控制芯片8259A,将硬件中断号重新设置为0x20-0x2f。

最后设置cpu的控制寄存器CR0,从而进入32位保护模式,并跳转到位于system模块最前面的head.s程序继续运行。

*4*,head.s

head.s在被编译后会被连接成system模块的最前面开始部分。他处于内存绝对地址0处开始的地方。

作用:

首先加载各个数据段寄存器,重新设置中断描述符表idtr(共256项),并使每个表项均指向一个只报错误的哑中断程序。

然后重新设置全局描述符表gdt。接着使用物理地址0与1MB开始处的内容相比较的方法检测A20地址线是否开启。

然后测试pc机是否含有数学协处理器芯片。并在控制寄存器CR0中设置相应的标志位。

接着设置管理内存的分页处理机制,将页目录表放在绝对物理地址0开始处(覆盖掉自己)。紧随其后放置共可寻址16MB内存的4个页表,

最后利用返回指令将预先放置在堆栈中的/init/main.c程序的入口地址弹出去执行main()。

head.s执行完后,正式完成了内存页目录和页表的设置,并重新设置了内核实际使用的中断描述符表idt和全局描述符表gdt。此时system模块在内存中的详细映像如下图。

系统启动的大致流程:

开机加电后cpu自动进入实模式并从地址0xFFFF0(偏移量寄存器?全1)开始执行指令.该地址一般指向bios中(CMOS\BIOS是一段固化的自检程序),bios开始系统检测并在物理地址0处开始初始化中断向量(?是填写中断向量?),此后将启动设备(现在的硬盘)的第一个扇区读入内存绝对地址0x7C00处,并跳转到这个地方。即执行bootsect.s程序(linux最前面部分是bootsect.s)。bootsect.s执行时将自己移动到绝对地址0x90000处,并把启动设备中后2kb代码(setup.s)读入到0x90200处,而内核其他部分(system模块)被读入从地址0x10000开始处,跳转到setup后,setup将system移动到内存起始处,这样system模块中代码的地址等于实际的物理地址,便于对内核代码和数据的操作。(为什么不一步到位?启动时内存起始处被中断向量表占用。)下图是linux系统启动时内存变化。

系统启动时程序的执行顺序:

3.内核初始化程序目录init

只包含一个main.c文件。

*5*,main.c:

系统在执行完boot/目录中的head.s程序后就将执行权交给main.c。用于执行内核所用初始化工作,然后移到用户模式创建新进程,并在控制台设备上运行shell程序。

(1) main.c先通过setup.s程序取得的系统参数设置系统根文件设备号以及一些内存全局变量。这些内存变量指明了主内存的开始地址,系统拥有的内存容量和作为高速缓存区内存的末端地址。

内核可以自由访问高速缓存,而主内存区中的区域由内存管理模块m m通过分页机制进行管理,使用时只能通过mm。

(2) 然后内核进行所有方面的硬件初始化(调用了其他程序中的初始化部分)。包括陷阱门,块设备,字设备和,tty和人工创建的第一个任务task0.待所有初始化工作完成后就设置中断允许标志,开启中断。

(3) 内核完成初始化后,将执行权限切换到用户模式,即cpu从0特权级切换到第3特权级。然后系统第一次调用创建进程函数fork()创建出一个用于运行init()的自进程,在该进程中系统将运行控制台程序。控制台建立成功再生成一个子进程用于运行shell程序/bin/sh。

由于创建新进程的过程是通过完全复制父进程代码段和数据段的方式实现的,因此在首次使用fork()创建新进程init时,为了确保新进程用户态堆栈没有进程0的多余信息,要求进程0在创建第一个新进程之前不能使用用户态堆栈,即任务0不能调用函数。因此fork()在程序中采用gcc函数内嵌的形式实现系统调用。

init()函数分为四个部分:安装根文件系统,显示系统信息,运行系统初始资源配置文件rc中的命令,执行用户登录shell程序。

系统执行到这里时已经生成了一系列进程,内核通过执行sched.c中的调度函数schedule()和system_call.s中的定时时钟中断过程timer_interrupt进行进程的调度,

4. 内核程序主目录 kernel

包含12个代码文件,一个makefile文件和3个子目录

(1)12个代码文件从功能上可分为3类:硬件(异常)中断处理程序文件,系统调用服务处理程序文件,进程调度等通用功能文件。调用关系如下:

中断处理程序:

包含asm.s和traps.c:

*6*, asm.s(汇编文件)实现大部分硬件异常引起的中断,包括大部分cpu探测到的异常故障处理的底层代码和数学协处理器fpu的异常处理。

asm.s的主要处理方式是在中断处理程序中调用相应的c函数程序,显示出错位置和出错号。然后退出中断。

*7*, trap.c实现了asm.s中调用的c函数。用于显示出错位置和出错号等调试信息

系统调用处理相关程序:

系统调用内核通过中断调用int0x80进行,寄存器eax中放调用号。实现系统调用的相关文件包括system_call,fork.c,signal.c,sys.c和exit.c文件

*8* fork.c ,fork.c中的fork()系统调用用于创建子进程。Linux中所有进程都是进程0(任务0)的子进程。该程序是sys_fork()(在kernel/system_call.s中)系统调用的辅助处理函数集 。给出了sys_fork()系统调用中使用的两个c语言函数:find_empty_process()和copy_process()。还包括进程内存区域验证与内存分配函数verfy_area()。

*9*,system_call.s的作用类似于asm.s的作用,主要实现系统调用(system_call)中断int 0x80的入口处理过程以及信号检测处理

另外实现对时钟中断和硬盘,软盘中断进行处理。

对于软中断(system_call,coprocessor_error,device_not_available),处理过程基本上是首先为调用相应c函数处理程序做准备,将一些参数压入堆栈,然后调用c函数进行相应功能的处理,处理返回后再去检测当前任务的信号位图,对值最小的一个信号进行处理并复位信号位图中的该信号。系统调用的c语言处理函数分布在整个linux内核代码中,由include/linux/sys.h头文件中的系统函数指针数组表来匹配。

对于硬件中断请求信号IRQ发来的中断,首先向中断控制芯片8259A发送结束硬件控制字指令EOI,然后调用相应的C函数处理流程。

*10* signal.c 给出了设置和获取进程信号阻塞码系统调用函数sys_sset-mask()和sys_sgetmask(),信号处理系统调用sys_singal(),修改进程在收到特定信号时所采取的行动的系统调用sys_sigaction()以及在系统调用中断处理程序中处理信号的函数do_signal()。

signal.c 程序涉及内核中所有有关信号处理的函数。在unix系统中,信号是一种“软件中断”处理机制。许多较为复杂的程序会使用到信号。信号机制提供了一种处理异步事件的方法。

在内核代码中通常使用一个无符号长整数(32位)中的比特位来表示各种不同信号。因此最多可表示32个不同的信号。本版本linux内核中定义了22种不同的信号。20种是posix.1标准规定的所有信号,另外两种是linux专用信号:SIGUNUSED(未定义)和SIGSTKFLT(堆栈错)。

*11* sys.c程序主要包含很多系统调用功能的实现函数。其中若返回值为-ENOSYS ,表示本版的linux还没有实现该功能。

*12* exit.c,主要描述了进程(任务)终止和退出的处理事宜。主要包含进程释放,会话终止和程序退出处理函数以及杀死进程,终止进程,挂起进程等系统调用函数。还包括进程信号发送函数send_sig()和通知父进程子进程终止的函数tell_father().

释放进程函数release()主要根据指定的任务数据结构(任务描述符)指针,在任务数组中删除指定的进程指针,释放相关内存页并立刻让内核重新调度任务的运行。

进程组终止函数kill_session()通过向会话号与当前进程相同的进程发送挂断进程的信号。

系统调用sys_kill()用于向进程发送任何指定的信号。

程序退出处理函数do_exit()是在系统调用的中断处理程序中被调用。

系统调用waitpid用于挂起当前进程。直到pid指定的子进程退出(终止)或者受到要求终止该进程的信号,或是需要调用一个信号句柄(信号处理程序)。

通用程序:

*13* mktime.c,该程序只有一个函数mktime(),仅供内核使用。计算从1970年1月1日0时起到开机当日经过的时间(秒),作为开机时间。

*14* sched.c 是内核中关于调度函数的程序,其中包括有关调度的基本函数(sleep_on,wakeup,schedule等)以及一些简单的系统调用函数。

*15* vsprintf.c 主要包括sprintf()函数,用于对参数产生格式化输出。

*16* printk.c ,printk()是内核中使用的显示函数。功能与c标准函数库中的printf()相同。

*17* panic.c内核程序出错时调用函数painc(),显示错误信息并使系统进入死循环。

(2)块设备驱动程序子目录kernel/blk_drv:

块设备是指按照固定大小数据块为单位寻址和访问的。如硬盘。

在内核与硬盘进行io操作时,需要考虑三个对象的交互作用:系统,控制器(8259A?)和驱动器。系统可直接向控制器发送命令或等待控制器发出中断请求;控制器在接受到命令后就会控制驱动器的操作,w/r数据或进行其他操作。

kernel/blk_drv包含4个c一个头文件和一个makefile文件。。

他们的大致关系如图

*18*,blk.h是有关硬盘块设备参数的头文件,定义了3个c程序中共用的块设备结构和数据块请求结构。其中有请求等待队列中项的数据结构request,用宏语句定义了电梯搜索算法。

*19*,hd.c程序是硬盘控制器驱动程序,提供对硬盘控制块设备的读写驱动和硬盘初始化处理。主要实现对硬盘数据块进行读/写的底层驱动函数。抄不下去了直接上图:

*20*,floppy.c程序主要实现对软盘数据块的读/写驱动。

*21*,ll_rw_blk.c主要用于执行底层块设备读写操作,实现底层块设备数据读/写函数ll_rw_block.c():为块设备创建块设备读写请求项,并插入到指定块设备请求队列中。

*22* ramdisk.c 内存虚拟盘驱动程序。

(3)字符设备驱动程序子目录kernel/chr_drv:

字符设备是以字符流作为操作对象的设备,不能进行寻址,如打印机。

在linux0.11中,字符设备主要包括控制终端设备和串行终端设备。

终端驱动程序用于控制终端设备,在终端设备和进程之间传输数据,并对所传输的数据进行一定的处理。用户在键盘上键入的原始数据(raw data),在通过终端程序处理后,被传送给一个接受进程;而进程向终端发送的数据,在终端程序处理后,被显示在终端屏幕上或者通过串行线路被发送到远程控制。

在linux 0.11内核中,终端控制台驱动程序涉及keyboard.s和console.c程序。Keyboard.s用于处理用户键入的字符,把他们放入读缓冲队列read_q中,并调用copy_to_cooked()函数读取read_q中的字符,经转换后放入辅助缓冲队列secondary。console.c程序实现控制台终端的输出处理。

包含4个c程序和2个汇编程序及一个makefile文件

*23*, tty_io.c包含tty字符设备读函数tty_read()和写函数tty_write(),为文件系统提供上层访问接口。

*24*,console.c主要包含控制台初始化程序和控制台写函数con_write()(没有控制台读?读是读缓存吧)。用于被tty设备调用,还包含对显示器和键盘中断的初始化设置函数con_init()。

*25*,rs_io.s 汇编程序用于实现两个串行接口的中断处理程序。该中断处理程序会根据从中断标识寄存器(端口0x3fa或0x2a)中取得的4种中断类型分别进行处理,并在处理中断类型为读字符的代码中调用do_tty_interrupt().

*26*,serial.s用于对异步串行通信芯片UART进行初始化操作,并设置两个通信端口的中断向量。另外还包括tty用于往串口输出的rs_write()函数。

*27*,keyboard.s主要实现了键盘中断处理过程keyboard_interrupt.

*28*tty_ioctl.c主要实现tty的io控制接口函数tty_ioctl()以及对termio[s]终端io结构的读写函数,并会在实现系统调用sys_ioctl()的fs/ioctl.c程序中被调用

(4)协处理器仿真和操作程序子目录kernel/math

仅含有一个c程序math_emulate.c.其中的math_emulate函数是中断int7的中断处理程序调用的c函数。当机器中没有数学协处理器而cpu执行了协处理器的指令时会引发该中断。该中断软件仿真协处理器的功能。该版本没有实现仿真代码。

*29*, math_emulate

5.文件系统目录fs:

Linux 0.11使用的是MINIX文件系统1.0版本,由6部分组成,一个3690kb的软盘,其各部分的分布如下图:

其中,引导块是计算机加电启动时可由ROM BIOS自动读入的执行代码和数据。对于不应作引导的磁盘,这一盘块可以不含代码。但任何盘片必须含有引导块,以保证MINIX格式的统一。超级块用于存放盘设备上文件系统结构的信息,并说明各部分的大小。

还是直接粘图吧:

对于pc机一般以一个扇区的长度(512B)作为块设备的数据块长度。而MINIX文件系统则将连续的两个扇区数据(1024B)作为一个数据块来处理,称之为一个磁盘块或盘块。

fs共包含17个c语言文件

分为4个部分:

(1) 高速缓冲区管理,

主要实现对硬盘等块设备进行数据高速存取的函数

高速缓冲区是文件系统访问块设备中数据的必经要道。为了访问文件系统等块设备上的数据,内核可以每次都访问块设备,进行读或写操作。但为了提升读写性能,内核在内存中开辟了一个高速数据缓存区(buffer cache)并将其划分为一个个与磁盘数据块大小相等的缓冲块来使用和管理,以期减少访问块设备的次数。

*30* buffer.c 用于对高速缓存区进行操作和管理,整个缓冲区被划分为1024B大小的缓冲块,正好与块设备上的磁盘逻辑块大小一样。高速缓冲采用hash表和空闲缓冲队列进行操作管理。在缓冲区初始化过程中,从缓冲区两端开始,同时分别设置缓冲块头结构和划分出对应的缓冲块。

缓冲块数据存取和管理函数的关系如下图:

(2) 底层文件操作,

说明了文件索引节点的管理,磁盘数据块的分配和释放以及文件名与i节点的转换算法

*31* bitmap.c程序:只要用于对i节点位图和逻辑块位图进行释放和占用处理。操作i节点位图的函数是free_inode()和new_inode(),操作逻辑块位图的函数是free_block()和new_block()。

*32* inode.c程序:主要包括处理i节点的函数iget(),iput()和块映射函数bmap(),以及其他一些辅助函数。

*33* super.c程序。该程序描述了文件系统超级块操作函数,这些函数属于文件系统底层,供上层的文件名和目录操作函数使用。主要有get_super(),put_super(),和read_super()。另外还有有关文件系统加载/卸载的系统调用函数sys_umount()和sys_mount(),以及根文件系统加载函数mount_root()。其他一些辅助函数与buffer.c中的辅助函数的作用类似。

*34* namei.c 程序是linux 0.11内核中最长的函数,主要实现了根据目录名或文件名寻找到对应i节点的函数,以及一些关于目录建立和删除,目录项的建立和删除等操作函数和系统调用。

*35* truncate.c程序 用于释放指定i节点在设备上占用的所有逻辑块,包括直接块,一次间接块和二次间接块。从而将文件的节点对应的文件长度截为0,并释放占用的设备空间。

(3) 文件数据访问,

有关对文件中数据进行读写操作,包括对字符设备,管道,块读写文件中数据的访问

*36* block_dev.c 程序属于块设备文件数据访问操作类程序。文件包括block_read() 和block_write()两个块设备读写函数。

*37* file_dev.c 包括file_read()和file_write()两个函数,仅供系统调用函数read()和write()调用。与36不同的是,本程序中的函数通过指定文件路径名方式进行操作。

*38* pipe.c 包括管道文件读写操作函数read_pipe()和write_pipe(),同时实现了管道系统调用sys_pipe()。这两个函数也是系统调用read()和write()的底层实现函数。也仅在read_write.c中使用。

*39* char_dev.c程序包括字符设备文件访问函数。主要有rw_ttyx(),rw_tty(),rw_memory()和rw_char()另外还有一个设备读写函数指针表。该表的项号代表主设备号。

*40* read_write.c() 该程序实现了文件操作系统调用read(),write()和lseek()。

(4) 文件高层函数

与文件的系统调用接口的实现有关,主要涉及文件打开,关闭,创建,以及有关文件目录操作的系统调用。

*41* open.c 实现了许多与文件操作相关的系统调用。主要有文件创建,打开,和关闭,文件宿主和属性的修改,文件访问权限的修改,文件操作时间的修改和系统文件系统root的变动等。

*42* exec.c程序实现对二进制可执行文件和shell脚本文件的加载与执行,其中主要的函数是函数do_execve(),他是系统中断调用(int 0x80)功能号_NR_execve()调用的c处理函数,是exec()函数簇的主要实现函数。

*43* stat.c程序实现取文件状态信息系统调用stat()和fstat(),并将信息存放在用户的文件状态结构缓冲区中。stat()是利用文件名取信息,fatat()是使用文件句柄(描述符)来取信息。

*44* fsntl.c程序实现了文件控制系统调用fcntl()和两个文件句柄(描述符)复制系统调用dup()和dup2()。dup2()指定了新句柄的数值,而dup()则返回当前值最小的为用句柄。句柄复制操作主要用在文件的标准输入/输出重定向和管道操作方面。

*45* ioctl.c 实现了输入输出控制系统调用ioctl()。他主要调用tty_ioctl()函数对终端的I/O进行控制。

*46* file_table.c程序目前为空仅定义了一个文件表数组。

6. 内存管理程序目录mm

主要用于管理程序对内存区的使用,实现了逻辑地址到线性地址和线性地址到物理地址的转换。

内存管理的两大主要功能就是地址转换和寻址保护。

共包含2个代码文件和一个makefile。

*47* page.s文件包括内存页面异常中断(int 14)处理程序,主要用于处理程序由于却页引发的页异常中断(发生在指令周期内)和访问非法地址引起的页保护。

*48* memory.c程序包括对内存进行初始化的函数mem_init(),由page.s的内存处理中断过程调用的do_no_page()和do_wp_page()函数。在创建新进程而执行复制进程操作时,使用该文件中的内存处理函数来分配管理内存空间。

7. 头文件主目录include:

总共32个.h文件,其中

主目录下13个头文件,主要供内核和用户程序使用。

*49* a.out.h 主要定义了二进制执行文件a.out的格式。其中包括三个数据结构和一些宏函数

*50* const.h 含有一些i节点标志的常数定义。

*51* ctype.h 定义了一些有关字符类型判断和转换的宏,使用数组(表)进行操作。

*52* errno.h 定义了linux系统中的一些出错码的常量符号。

*53* fcntl.h 文件控制选项头文件,主要定义了函数fcntl()和open()中用到的一些选项和符号。

*54* signal.h 定义了信号符号常量和数据结构sigaction.

*55* stdarg.h 是标准参数头文件,它以宏的形式定义变量参数列表。主要说明了一个类型和三个宏

*56* stddef.h 由c标准化组织创建的,其名称含义是标准(std)定义(def)主要用于存放一些“标准定义”

*57*string.h 该头文件以内嵌函数形式定义了所有字符串操作函数,为了提高执行速度使用了内嵌汇编程序。

*58* termios.h 该文件含有终端I/O接口定义,包括termios数据结构和一些对通用终端接口设置的函数原型。

*59* time.h 用于涉及处理时间的函数。

*60* unistd.h 定义了各种符号函数和类型,并申明了各种函数。

*61* utime.h 定义了文件访问和修改时间结构utimbuf{}以及utime()函数原型。时间一秒计。

三个子目录

asm/子目录下 4个,与计算机硬件体系结构密切相关,说明了与具体机器密切相关的一些数据结构和参数。

*62*io.h定义了对硬件IO端口访问的嵌入式汇编宏函数:outb(),inb(),outb(),inb_p()。

*63* memory.h 含有一个内存复制嵌入式汇编宏memcpy()

*64* segment.h 定义了一些访问Intel CPU中断寄存器或与断寄存器有关的内存操作函数。

*65* system.h定义了设置或修改描述符/中断门等嵌入式汇编。

linux/子目录下10个,linux内核专用文件

*66* config.h内核配置头文件的代码文件。

*67* fdreg.h 用以说明软盘系统常用到一些参数以及所用到I/O端口。

*68* fs.h:文件系统头文件,主要描述了文件操作的一些常量,高速缓冲块结构以及MINIX文件系统1.0版的结构。

*69* hdreg.h 定义了对硬盘控制器进行编程的命令常量符号。

*70* head.h 定义了CPU描述符的简单结构和指定描述符的项号。

*71* kernel.h 定义了一些内核常用的函数原型。

*72* mm.h 是内存管理文件,其中定义了内存页面的大小和几个页面释放函数原型。

*73* sched.h 调度程序头文件。定义了任务结构task_struct,初始任务0的数据

*74* sys.h 本文件列出了所有系统调用函数的原型以及系统调用函数指针表。

*75* tty.h

sys/子目录下 5个,与文件状态,进程,系统数据类型有关,包含一些系统时间信息和有关系统状态的结构。

*76* stat.h 说明了函数stat()返回的数据及其结构类型,以及一些属性操作测试宏,函数原型。

*77* times.h 主要定义了文件访问与修改时间结构tms。它将由times()函数返回。

*78* types.h 定义了基本的数据类型。所有类型均定义为适当的数字类型长度。

*79* utsname.h 是系统名称结构头文件。其中定义了结构utsname以及函数原型uname()

*80* wait.h 该文件描述了进程等待信息的一些宏。

8. 内核库函数目录lib

内核库函数用于为初始化程序init/main.c执行在用户态的进程提供支持。

在编译内核阶段,makefile中的相关指令会把以上程序编译成.o

模块,然后组建成lib.a库文件形式并链接到内核模块中。

共包含12个c语言文件,

*81* _exit.c 定义了内核使用的程序(退出)终止函数_exit()

*82* close.c 定义了文件关闭函数close()

*83* ctype.c定义了字符类型,用于判断字符的所属类型,包括控制字符(_C) 大写字符(_U)小写字符(_L)等,

*84* dup.c 该程序包括一个创建文件描述符拷贝的函数dup().

*85* errno.c仅定义了一个出错号变量errno。用于在函数调用失败前存放出错号。

*86* execve.c 定义加载并执行子进程函数execve()

*87* malloc.c包括内存分配函数malloc(),为了不与用户程序使用的malloc函数混淆,从内核0.98版后就改名为kmalloc(),而free_s()函数改名为kfree_s()。

*88* open.c open()系统调用用于将一个文件名转化为一个文件描述符。

*89* setsid.c 该程序包括一个setsid()系统调用函数,

*90* string.c 所有字符串操作函数已经在string.h中实现,因此string.c程序仅包括string.h头文件。

*91* wait.c 包括函数waitpid()和wait()。这两个函数允许进程获取与其子进程之一的状态信息。

*92* write.c程序。该程序中包括一个向文件描述符写操作函数write().该函数向文件描述符指定的文件写入count字节的数据到缓冲区buf中

9.编译内核工具程序目录tools

*93*build.c 该目录下的build.c程序用于将linux各个目录中被分别编译生成的目标代码链接合并成一个可运行的内核映像文件image。

具体的方法是对boot/中的bootsect.s,setup.s使用8086汇编器进行编译,分别生成各自的执行模块。再对源代码中的其他程序使用GNU的编译器gcc/gas进行编译,并连接成模块system。然后使用build工具将这三块组合成一个内核映像文件image。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: