大壮嘎嘎壮

  • 2025-02-15
  • 发表了主题帖: 《Linux内核深度解析》- 第六章 文件系统

        在Linux系统中,一切皆文件,目录、设备、套接字和管道等都是文件。     文件系统充当着类似数据管家的作用:管理磁盘上的数据。主要承担着管理数据放在磁盘的位置,提供快速找到某个文件方法,对文件操作的权限控制、日志记录、防止崩溃丢数据等。     应用程序可以直接使用内核提供的系统调用访问文件,系统调用mount用来把文件系统挂载到某个目录下。常用操作接口:         1.open:打开文件         2.close:关闭文件         3.read:读文件         4.write:写文件         5.lseek:设置文件偏移     文件系统通过“三层目录结构”管理文件:         1.超级块(Superblock)             记录整个文件系统的信息:磁盘总大小、空闲空间、文件系统类型、日志信息。         2.Inode(索引节点)             每个文件/目录对应一个唯一的 inode,相当于书的“身份证”,记录着文件权限,文件大小、创建时间及数据块地址。         3.目录项(Dentry)             目录的本质是一个“映射表”,例如:                 文件名 cat.jpg → 对应的 inode 编号。                 通过目录层级(如 /home/user/photos)组织文件路径。     文件系统工作流程大体有以下步骤,如果应用程序要读取 /user/data/log.txt 为例:         解析路径:从根目录 / 开始,逐级查找 user→data→log.txt 的 inode。         权限检查:内核检查当前用户是否有权访问 log.txt 的 inode。         读取数据:根据 inode 中的“数据块地址”,从磁盘读取文件内容到内存。         返回结果:将文件内容传给应用程序。     常见的文件系统类型有:fat、ext4、ubi、ntfs等。nandflash适用于fat、ubi文件系统,emmc适用于ext4文件系统。U盘根据大小及使用场景可格式化成ntfs、fat16、fat32、exfat等文件系统。由于linux对ntfs的支持不是特别友好,常用ntfs-3g来对ntfs格式的块设备进行操作。

  • 发表了主题帖: 《Linux内核深度解析》- 第四章 中断、异常和系统调用

    本帖最后由 大壮嘎嘎壮 于 2025-2-15 12:36 编辑 ·    在arm64和MIPS等体系结构中,中断、系统调用和其他打断程序正常执行的事件被统称为异常。 一、异常     1.级别     以arm64处理器共有四个异常级别:0~3 数字越大,级别越高,权限越高。     异常级别0:用户模式。     异常级别1:内核模式。     异常级别2:基于内核的虚拟机KVM是内核的一个模块,直接在处理器上执行客户操作系统。在宿主操作系统的异常级别1和客户操作系统的异常级别1之间切换时,需要KVM陷入异常级别2。     异常级别3:arm64架构的安全扩展定义了两种安全状态:正常世界和安全世界。两个世界只能通过异常级别3的安全监控器切换。     2.分类     同步异常:系统调用、数据终止、指令终止、栈指针或指令地址未对齐、未定义指令、调试异常。     异步异常:中断、快速中断、系统错误。     3.处理     异常处理程序是内核中用于处理特定类型异常的函数。每个异常都有一个与之对应的处理程序。这些程序通常执行以下步骤:         (1)保存现场:             异常处理程序首先会保存被中断程序的执行环境,包括各种寄存器的值、堆栈指针等。这是为了确保在异常处理完成后能够恢复被中断程序的执行。         (2)确定异常类型:             根据异常向量表中的信息或异常处理程序的参数,确定异常的类型和原因。         (3)执行异常处理逻辑:             根据异常类型,执行相应的处理逻辑。这可能包括修复错误、记录日志、发送信号给进程等。         (4)恢复现场:             在异常处理完成后,恢复被中断程序的执行环境,包括恢复寄存器的值和堆栈指针。         (5)返回被中断的程序:             最后,异常处理程序会返回到被中断的程序继续执行。如果异常无法处理或导致内核崩溃,则系统可能会进入panic状态并重启。       还有一些对于特定类型的异常处理,内核可能有不同的处理策略。例如:         (1)页错误异常:             当进程访问未映射到物理地址的虚拟地址时,会触发页错误异常。内核会尝试分配新的页帧给进程,并更新页表以映射虚拟地址到物理地址。         (2)除法错误异常:             当进程执行除法运算且除数为零时,会触发除法错误异常。内核会向进程发送SIGFPE信号,通知其发生了浮点异常。         (3)系统调用异常:             当进程执行系统调用时,会触发系统调用异常。内核会根据系统调用号执行相应的系统调用服务函数。 二、中断     中断是外围设备通知处理器的一种机制。·     中断处理分为上半部和下半部,这应该是为了快速响应并减少中断屏蔽的时间。上半部处理紧急任务,然后下半部处理不那么紧急的部分。上半部是在中断上下文中执行,需要快速完成,而下半部可能用tasklet、软中断或者工作队列之类的机制延迟处理。当硬件触发中断,CPU保存现场,跳转到中断处理程序。上半部执行必要的操作,比如读取数据,然后登记下半部处理。下半部可能在稍后的时间执行,比如软中断在中断返回前处理,或者tasklet调度到软中断上下文中。工作队列则可能在内核线程中运行,可以睡眠。 三、系统调用     系统调用是内核给用户程序提供的变成接口,主要有以下特点:         权限隔离:用户程序无权直接操作硬件或内核资源,必须通过系统调用“敲门”,由内核代劳。         高效切换:通过软中断或专用指令,快速完成用户态和内核态的上下文切换。         统一接口:所有硬件操作(如读写文件、网络通信)都被抽象为系统调用,对用户程序透明。     大体流程如下:         1.用户程序发起请求             调用库函数(如 write()),库函数将参数和系统调用号(如 __NR_write)放入寄存器。         2.触发内核模式切换             通过软中断(如 int 0x80)或专用指令(如 syscall),CPU 从用户态切换到内核态。         3.内核处理请求             根据系统调用号,从内核的“系统调用表”中找到对应的处理函数(如 sys_write)。             验证参数合法性(如检查内存权限),执行实际操作(如写文件到磁盘)。         4.返回用户态             内核将结果(如成功写入的字节数或错误码)返回给用户程序,CPU 切换回用户态。  

  • 2025-01-20
  • 加入了学习《自己动手写嵌入式操作系统》,观看 自己动手写操作系统

  • 2025-01-19
  • 发表了主题帖: 《Linux内核深度解析》初见 - 第一章 内核引导和初始化

    本帖最后由 大壮嘎嘎壮 于 2025-1-19 17:26 编辑 .globl   _start _start:     岁聿云暮,一元复始,最近终于得空抽出时间来阅读这本《Linux内核深度解析》。     一、Boot阶段     在嵌入式系统中,BOOT(引导加载程序)扮演着至关重要的角色,它负责初始化硬件、加载操作系统内核或其他应用程序,并为系统的正常运行做好准备。     本文介绍的是嵌入式设备常用的U-Boot引导程序,U-Boot分为SPL和正常的U-Boot程序两部分。SPL(Secondary Program Loader)意为第二段程序加载器,明明作为引导程序首先出场的角色为什么要叫第二段呢,这个第二段是相对于固化在芯片内部的bootrom来说的。处理器启动时首先执行的是芯片内部固化的程序,固化程序加载SPL,SPL加载正常的U-Boot程序。由于芯片内部寸土寸金,片上内存比较小,所以才采用这种方式进行初始化内存和储存设备及一些外设,为内核的加载或者固件的更新下载做准备。Uboot最后调用boot_Jump_linux函数,跳转到linux内核。至此,uboot使命结束,CPU控制权交给内核。                                                                                                                                        二、Kernel阶段     1.初始化     内核初始化分为汇编语言和C语言部分。     汇编语言中主要执行了以下几个函数进行了一些基本的初始化流程:         (1)el2-setup:配置执行内核的异常级别。         (2)__create_page_tables:页表映射         (3)__primary_switch:开MMU         (4)__primary_switched:栈、异常向量表。数据段等初始化,调用start_kernel函数     内核初始化的C语言的入口函数是start_kernel函数,start_kernel函数的主要职责如下:         (1)设置页表和内存管理:             初始化页表,确保内核能够正确地管理内存。设置内存管理单元(MMU)的配置。         (2)初始化硬件:             初始化处理器和硬件架构相关的设置。设置中断和异常处理。         (3)内核数据结构初始化:             初始化各种内核数据结构,如调度器、进程控制块(task_struct)、内存管理等。         (4)设备驱动初始化:             初始化设备驱动框架,为内核支持的设备做好准备。         (5)文件系统初始化:             初始化虚拟文件系统(VFS)和根文件系统。         (6)启动内核线程:             启动内核守护进程和必要的内核线程,如 kswapd(内存回收守护进程)、kworker(工作线程)等。         (7)用户空间启动:             挂载根文件系统。启动第一个用户空间进程(通常是 init 进程)。     2.init进程     init进程是用户空间的第一个进程,主要有以下作用:     (1)启动系统服务:         init进程负责启动各种系统服务,如网络服务、打印服务等。这些服务通常通过运行级别(run levels)来管理,不同的运行级别对应不同的系统状态和服务组合。     (2)管理用户登录:         init进程还负责启动getty进程,用于用户登录。在系统完全启动后,init会为每个用户已退出的终端重启getty,以便下一个用户可以登录。     (3)处理孤儿进程:         当一个进程启动了一个子进程并且在子进程之前终止时,这个子进程会成为孤儿进程。init进程会接管这些孤儿进程,确保它们不会成为僵尸进程(zombie process)。     (4)系统初始化:         init进程还承担挂载文件系统、初始化属性系统和Klog、selinux的初始化等重要任务。它通过解析init.rc脚本来初始化系统daemon服务进程。

  • 2024-12-11
  • 回复了主题帖: 读书入围名单: 《Linux内核深度解析》

    确认,可以完成阅读分享计划

  • 2024-11-28
  • 加入了学习《基于Arduino玩转pico RP2040》,观看 基于Arduino玩转pico RP2040

最近访客

< 1/1 >

统计信息

已有6人来访过

  • 芯积分:24
  • 好友:--
  • 主题:3
  • 回复:1

留言

你需要登录后才可以留言 登录 | 注册


现在还没有留言