linux内核初探
文章平均质量分 66
nginux
阿里巴巴
展开
-
arm push/pop/b/bl汇编指令
push支持同时将多个寄存器入栈,格式{xx,xx},如push{r0,r1,r2}BL函数条跳转前执行LR=PC-4;如同push一样,pop也支持同时pop出栈多个寄存器。原创 2022-07-31 15:48:04 · 7865 阅读 · 3 评论 -
linux内存管理浅析
【虚拟内存管理】每个进程对应一个task结构,它指向一个mm结构,这就是该进程的内存管理器。mm->pdg指向容纳页表的内存,每个进程都有自己的mm,每个mm都有自己的页表。用户程序对内存的操作(分配、回收、映射等)都是对mm的操作,具体来说是对mm上的vma(虚拟内存空间)的操作。这些vma代表这进程的各个区域,比如堆、栈、代码区、数据区、各种映射区等等。用户程序对内存的操作并不会直接影响页原创 2014-06-06 21:09:47 · 962 阅读 · 0 评论 -
Linux-0.12内核打开文件过程--sys_open源码分析
上图展示了进程打开文件使用的内核数据结构,所以要打开文件,就要构造上图中的关系。int sys_open(const char *filename,int flag,int mode){ struct m_inode *inode; struct file *f; int i,fd; mode&=0777&~current->umask; //在filp数组中寻找“空闲位置”原创 2014-05-25 20:34:20 · 2610 阅读 · 0 评论 -
linux搜索文件过程
1.文件中的数据是放在磁盘的数据区中的,而一个文件名则是通过对应的i节点与这些磁盘块联系起来,这些盘块的号码就存放在i节点的逻辑块数组i_zone[]中。在文件系统的一个目录中,其中所有文件名信息对应的目录项保存在该目录名文件的数据块中,例如,root/下的所有文件名的目录项就保存在root/目录名文件的数据块中,而文件系统根目录下的所有文件名信息则保存在指定i节点(1号节点)的数据块中,文件名的原创 2014-05-25 08:36:52 · 2042 阅读 · 0 评论 -
堆栈brk指针
内存分配的原理从操作系统角度来看,进程分配内存有两种方式,分别由两个系统调用完成:brk和mmap(不考虑共享内存)。1、brk是将数据段(.data)的最高地址指针_edata往高地址推;2、mmap是在进程的虚拟地址空间中(堆和栈中间,称为文件映射区域的地方)找一块空闲的虚拟内存。 这两种方式分配的都是虚拟内存,没有分配物理内存。在第一次访问已分配的虚拟转载 2014-06-09 09:39:12 · 1907 阅读 · 0 评论 -
linux-0.12内核之内存管理(1)
1.内存分页管理机制内存分页管理是通过页目录表和内存页表所组成的二级表组成的,其中页目录表和页表的结构是一样的,表项结构也相同。页目录表中的每个表项(4B)来寻址一个页表,而每个页表项(4B)来指定一页物理内存页。因此,当指定了一个页目录项和一个页表项,我们就可以唯一地确定所对应的物理内存页。在Linux 0.12内核中,所有进程都是用一个页目录表,而每个进程都有自己的页表。内核代码和数据段长原创 2014-05-26 11:15:49 · 1421 阅读 · 0 评论 -
PAGE_MASK判定addr是否是4096倍数
将物理地址addr修整为页边界地址(页的上边界)#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)|------------|PAGE_ALGN(addr)| || || || |addr|原创 2014-06-09 11:22:08 · 4548 阅读 · 0 评论 -
brk系统调用实现分析
brk(addr)直接修改堆的大小。addr指定current->mm->brk的新值,返回值是线性区新的结束地址,这是一个系统调用。当用户态的进程调用brk()系统调用时,内核执行sys_brk(addr)函数。下面分析这个函数的执行流程:1:检测addr参数是否位于进程代码段所在的线性区,如果是直接返回,因为堆不能与进程代码段所在的线性区重合。mm=current->mm;down_原创 2014-06-10 10:02:24 · 5688 阅读 · 0 评论 -
Linux内核之内存管理(4)--缺页处理程序
缺页处理程序//下面函数将一页内存页面映射到指定线性地址处,它返回页面的物理地址//把一物理内存页面映射到线性地址空间指定处或者说把线性地址空间指定地址address处的页面映射到主内存区页面page上。主要工作是在相关也目录项和页表项中设置指定页面的信息。在处理缺页异常函数do_no_page中会调用这个函数。参数:address--线性地址;page--是分配的主内存区中某一页面指针st原创 2014-05-27 09:49:55 · 1796 阅读 · 0 评论 -
Linux0.12内核之内存管理(2)
本文主要介绍Linux0.12内核memory.c中的函数1.void free_page(unsigned long addr)//释放物理地址addr处的一页内存。用于free_page_tables()函数void free_page(unsigned long addr){//首先判定给定物理地址的合理性。如果物理地址addr小于内存低端1M,对此不///予处理。如果a原创 2014-05-26 20:43:24 · 1371 阅读 · 0 评论 -
Linux0.12内核之内存管理(3)
本系列的第三篇文章主要来介绍与共享物理页面相关的两个函数。//在发生缺页异常的时,首先看看能否与运行同一个文件的其他进程进行页面共享处理。该函数首先判断系统中是否有另外进程也在运行与当前进程一样的执行文件。若有,则在系统当前任务中找寻这样的任务。若找到了这样的任务就尝试与其共享指定地址处的页面。判断系统中是否有另一个进程也在执行同一个可执行文件的方法是利用进程任务数据结构中的executabl原创 2014-05-27 09:22:20 · 1275 阅读 · 0 评论 -
写文件的流程
许多文件系统都是通过generic_file_write()函数来实现文件对象的write方法,即write(库函数)->sys_write()->generic_file_write():ssize_t generic_file_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)原创 2014-06-15 16:37:27 · 1656 阅读 · 0 评论 -
内存映射
1.概述一个线性区可以和磁盘文件系统的普通文件的某一个部分或者块设备文件相关联。这就意味着内核把对线性区中页内某个字节的访问转换成对文件中相应字节的操作,这种技术称为内存映射。有两种类型的内存映射:共享型:在线性区页上的任何写操作都会修改磁盘上的文件;而且,如果进程对共享映射中的一个页进行写,那么这种修改对于其他映射了这同一文件的所有进程来说都是可见的。私有型:当进程创原创 2014-06-17 11:02:00 · 1357 阅读 · 0 评论 -
Linux权限引发的"血案"
前言使用Linux的时候是否有过权限不足的烦恼?rwx对于文件和目录到底有什么作用?Linux又是如何确定进程是对于文件的访问权限的?本文将解决上面的疑问,有了上述基础,再介绍Linux的重要API–exec权限对于linux的重要性解读rwx文件: r(read):可以读取文件的内容 w(write):可以编辑/修改文件内容(不包含删除) x(execute):可执行权限 目录: r原创 2015-08-22 20:00:41 · 1225 阅读 · 0 评论 -
文件读写的理论
为了提高效率,稍微复杂一些的操作系统对文件的读写都是带缓冲的,Linux当然也不例外。所谓缓冲,就是操作系统为最近刚读写的文件内容在内核保留一份副本,以便当再次需要已经缓冲存储在副本中的内容时就不必再临时从设备上读入,而需要写的时候则可以先写到副本中,待系统较为空闲的时候再从副本写入设备。在多进程的系统中,由于同一个文件可能为多个进程所共享,缓冲的作用就更为显著。然而,怎么样实现缓冲,在哪一个原创 2014-06-14 11:17:59 · 1353 阅读 · 0 评论 -
Linux内核的进程切换(上)
硬件上下文概念尽管每个进程都可以拥有属于自己的地址空间,但所有进程必须共享CPU寄存器。因此在,在恢复一个进程执行之前,内核必须确保每个寄存器装入了挂起进程时的值。而这些必须装入的寄存器中的数据就称为硬件上下文。任务状态段80X86体系结构: 包括一个特殊的段类型,叫任务状态段(TSS),作用是存放硬件上下文。段是x86的概念,在保护模式下,段选择符参与寻址,段选择符在段寄存器中,而tss段则在t原创 2015-08-19 11:30:52 · 2179 阅读 · 0 评论 -
linux0.12内核的内存组织和进程结构
进程结构Linux0.12中的每个进程都有如下的结构:在gdt中占有两项,一项是tss段描述符,一项是ldt段描述符。在task数组中占有一项,指向一页物理内存,该物理内存低端是进程控制块task_struct(里面包括tss段和ldt段),其余部分是进程的内核态堆栈。在页目录表和页表中设置有相关项。Linux0.12中,最多只有64个进原创 2014-05-24 10:26:55 · 1655 阅读 · 0 评论 -
Linux-0.12内核sleep_on函数分析
sleep_on用于进程休眠,原型如下:void sleep_on(struct task_struct **p)当进程访问某个互斥资源时,如果资源被另外进程占用,当前进程就需要休眠。假设资源的结构如下:struct res{....struct task_struct *wait;}其实我们参考下文件系统的i节点就会发现,i节点也是一种资源,它的结构体中就有一原创 2014-05-23 10:10:57 · 2191 阅读 · 3 评论 -
实现多任务的内核Linux0.00分析
最近终于把实现多任务的微内核调试了一遍,我们阐述了如何在保护模式下切换任务。同时知识包括:gdt,idt,ldt,tss,时钟中断服务,特权级切换,显存编程,boot和loader功能,bios调用等等。详细知识还要在实践中摸索学习,希望大家一起进步。这篇文章仅仅做个记录,如有亲身调试过代码,可能不大好理解。接下几天重点看看0.12启动程序,多分页需要更加深入了解。;#Mode=Dos ;放在原创 2014-05-15 10:15:01 · 1805 阅读 · 0 评论 -
AT&T汇编指令介绍
linux中使用的AT&T格式的汇编指令,所以总结一下一些比较重要的指令。1.寻址模式有多种不同的寻址模式,允许不同形式的存储器引用。我们用符号Ea表示任意寄存器,R[Ea]表示它的值。M[addr]表示addr处地址的值。题目:答案:0x100,0xAB,0x108,0xFF,0x11,0x12,0xFF,0x11。2.leal指令加载有效地址指令其实是m原创 2014-05-05 20:01:13 · 1696 阅读 · 0 评论 -
as编写hello,world
.text.global _start_start: movl $len,%edx movl $msg,%ecx movl $1,%ebx movl $4,%eax int $0x80 movl $0,%ebx movl $1,%eax int $0x80.dat原创 2014-05-05 20:56:10 · 2566 阅读 · 0 评论 -
bootloader实现
上篇文章我们完成了一个简单的bootloader,与其说是bootloader,不如说是boot,本篇我们完成loader部分功能.loader部分是在boot部分基础上,通过到约定好的启动盘位置上读数据载入内存,达到loader的目的。到启动盘读数据是bios提供的功能调用.1. 铺垫(1)我们这次的程序分两个部分,一个部分是bootloader,boot和loader功能;一个是hea原创 2014-05-09 11:04:29 · 2091 阅读 · 0 评论 -
bochs调试命令
bochs调试的有些命令根据版本好像有变化,我在ubuntu下安装了bochs-2.4.6,发现和bochs-2.3.6命令出现区别,在2.3。6版本支持dump_cpu、info r等命令,在我安装的2.4.6版本中不支持这两个命令,后面在使用bochs的过程中会陆续总结一些2.4.6支持的命令,最简单的方法是通过help来获取,下面先记录一些常用的:r 查看通用寄存器sreg 查看段寄原创 2014-05-09 09:32:12 · 1273 阅读 · 0 评论 -
实现一个最简单的boot
1.汇编语言实现,汇编和链接器分别为as86和ld86。代码如下:.globl begtext,begdata,begbss,endtext,enddata,endbss.textbegtext:.databegdata:.bssbegbss:.textBOOTSEG=0x7c0entry startstart: jmpi go,BOOTSEGgo: mov ax,原创 2014-05-08 22:54:31 · 1951 阅读 · 1 评论 -
Linux下的bochs安装
强烈建议使用ubuntu系统,apt-get指令太好用了,安装各种依赖相当简单。1.首先到bochs网站上下载一个linux版本bochs。在安装之前需要安装一些依赖:sudo apt-get install build-essentialsudo apt-get install xorg-devsudo apt-get install libgtk2.0-devsudo ap原创 2014-05-08 21:02:59 · 1206 阅读 · 0 评论 -
嵌入汇编
本文介绍内核C语言程序中接触到的嵌入式汇编(内联汇编)语句。具有输入和输出参数的嵌入式汇编语句的基本格式为:asm("汇编语句":输出寄存器:输入寄存器:会被修改的寄存器);除第一行外,后面带冒号的行若不使用就都可以省略。其实asm是内联汇编语句的关键词;"汇编语句"是你写汇编指令的地方;"输出寄存器"表示这段嵌入汇编执行完之后那些寄存器用于存放输出数据。输入寄存器表示在开始执行汇原创 2014-05-16 15:11:34 · 1440 阅读 · 0 评论 -
linux系统调用原理分析
写这篇文章是看到一个as汇编器里编写的汇编代码,有一个指令int 80h没有搞懂,然后自己查资料发现不少东西,本文旨在浅显的分析linux的系统调用,主要是linux0.12内核来说!目前操作系统内核的结构模式主要分为整体式的单内核和层次式的微内核模式。而0.12内核是单内核模式。在单内核模式的系统中,操作系统提供服务的流程:应用程序使用指定的参数值执行系统调用指令(int 80h),使CPU原创 2014-05-05 10:28:48 · 1873 阅读 · 0 评论 -
80x86保护模式下IDT和中断调用过程分析
1.中断描述符表(IDT),将每个异常或中断向量分别与它们的处理过程联系起来。与GDT和LDT类似,IDT也是由8字节长度的描述符组成。IDT空描述符的存在标志位必须是0。IDT表可以驻留在线性地址空间的任何地方,处理器使用IDTR寄存器来定位IDT表的位置。LIDT指令可以把内存中的限长值和基地址操作数加载到IDTR寄存器中,该指令仅能由当前特权级CPL是0的代码执行,通常被用于创建原创 2014-05-11 10:02:36 · 2049 阅读 · 0 评论 -
bochs+gdb联调linux-0.11内核
终于把bochs和gdb连起来了,下面描述下步骤以作记录。1.安装bochs前面有篇文章介绍了bochs源码编译安装过程,这里安装也非常相似,只是命令稍微有些不同./configure --enable-gdb-stubmakemake install2.下载调试映像http://oldlinux.org/Linux.old/bochs/linux-0.11-gdb-r原创 2014-05-19 09:03:58 · 1763 阅读 · 0 评论 -
linux0.11内核fork实现分析(不看不知道,一看很简单)
曾几何时,只是一直在调用库函数fork,只知道它创建一个子进程,并且子进程返回值是0,父进程返回值是子进程pid。但是一直没有深究内核代码,今天终于使用gdb调试了一把fork的内核代码,下面就让我们一探究竟吧。1.创建进程的本质是什么?根据目前理解,其实就是构造了PCB,这个PCB会唯一标示一个进程的存在,并且会构建子进程的页目录和页表等等。2.为什么fork()调用会有2个返回值,原创 2014-05-19 16:18:58 · 1922 阅读 · 0 评论 -
CPU特权级保护
1.特权级1.1特权级处理器段保护机制可以识别0-3共原创 2014-05-14 08:38:11 · 1641 阅读 · 0 评论 -
iret指令详解
在“实地址模式”中,IRET 指令执行到中断程序或过程的远返回。在执行此操作的过程中,处理器从堆栈将返回指令指针、返回代码段选择器以及 EFLAGS 映像分别弹入 EIP、CS 以及 EFLAGS 寄存器,然后恢复执行中断的程序或过程。在“保护模式”中,IRET 指令的操作取决于以下因素:EFLAGS 寄存器中 NT(嵌套任务)与 VM 标志的设置,以及当前堆栈中存储的 EFLAGS 映像原创 2014-05-14 09:47:37 · 15796 阅读 · 1 评论 -
Linux0.12信号
1.我们先来看下0.12版本内核是如何处理信号的。在系统调用或者时钟中断末尾,内核会检测每个进程是否收到信号,如果收到信号就会调用do_signal()函数。这个函数是内核系统调用(0x80)中断处理程序中对信号的预处理程序。do_signal会把信号处理函数插入到用户程序堆栈中。这样,在当前系统调用结束后就会立即执行信号处理程序,然后继续执行用户程序,如下图所示:在把信号处理程序的参原创 2014-06-03 16:40:31 · 1419 阅读 · 1 评论 -
宏和函数
此为C语言的基础,和Linux内核关系并不大,不过还是作为补充知识点介绍一下好了。宏非常频繁的用于执行简单的计算,比如在两个表达式中寻找其中较大的一个:#define MAX(a,b) ((a)>(b)?(a):(b))如果使用函数来实现的话就比较慢,宏的话在编译的时候就完成工作,所以使用宏远比使用函数调用效率来的可观。和使用函数相比,使用宏的不利之处就在于每次使用宏的时候,一个宏定义代码原创 2014-05-05 11:15:15 · 977 阅读 · 0 评论