.htaccess wordpress,北京云无限优化,a做片手机免费网站,一款蛋糕食品类企业手机网站源码第十一章
任意进程的页目录表第0~767个页目录项属于用户空间#xff0c;指向用户页表。第768~1023个页目录项指向内核页表。每创建一个新的用户进程,就将内核页目录项复制到用户进程的页目录表#xff0c;其次需要把用户页目录表中最后一个页目录项更新为用户进程自己的页目…第十一章
任意进程的页目录表第0~767个页目录项属于用户空间指向用户页表。第768~1023个页目录项指向内核页表。每创建一个新的用户进程,就将内核页目录项复制到用户进程的页目录表其次需要把用户页目录表中最后一个页目录项更新为用户进程自己的页目录表的物理地址。 每个进程有自己单独的位图,存储在进程pcb中的userprog_vaddr中。LDT 当前运行的任务其LDT位于LDTR指向的地址选择子。每切换一个任务时需要lldt指令重新加载新任务的LDT到LDTRTSS CPU自动用此结构体变量保存任务的状态任务的上下文环境寄存器的值和自动从此结构体变量中载入任务的状态。TR寄存器始终指向当前任务的TSS这样每个任务必须有单独的TSS但Linux并未这么做。Linux所有任务共享一个TSS。 除了中断和调用门返回外CPU不允许从高特权级到低特权级。CPU在不同的特权级下使用不同的栈。 TSS和LDT一样必须要在GDT中注册。现代操作系统采用的任务切换方式 我们使用TSS的唯一理由是为0特权级的任务提供栈。 Linux中为每个CPU创建一个TSS在各个CPU上的所有任务共享同一个TSS各CPU的TR寄存器保存各自的TSS在用ltr指令加载TSS后TR寄存器永远指向同一个TSS进程切换时只把这个TSS中的SS0和esp0更新为新任务的内核栈的段地址和栈指针。 第十二章
系统调用 Linux只占用一个中断向量号0X80在寄存器eax中写入子功能号。所有系统调用都可以通过syscall函数不是由系统提供的是glibc提供的库函数直接系统调用为_syscall完成。总之对用户进程而言,在 Linux 上执行系统调用,只需要提供子功能号和参数就行了。堆内存管理arena 将一大块内存划分为无数小内存块的内存仓库。 arena 是个提供内在分配的数据结构,它分为两部分,一部分是元信息,用来描述自己内存池中空闲内存块数量,这其中包括内存块描述符指针(后面介绍),通过它可以间接获知本 arena 所包含内存块的规格大小,此部分占用的空间是固定的,约为 12 字节。另一部分就是内存地区域,这里面有无数的内存块,此部分占用 arena 大量的空间。 本书中针对小内存块的arena占用1页框内存。 每个内存块命名为mem_block分别为每一种规格的内存块建立一个内存块描述符即mem_bloc_desc。
struct mem_block_desc ( uint32 t block size //内存块大小 uint32_t blocks_per_arena; //本arena中可容纳此 mem_block 的数量 struct list free list //目前可用同类的mem_block链表
实现sys_malloc 传入参数size代表申请多少字节内存 1.首先判断用哪个内存池内核还是用户 2.若申请的内存不在内存池容量范围内直接返回NULL 3.超过1024就直接分配页框 4.若小于等于1024循环各种规格找到最合适的规格 5.判断该规格free_list是否为空若mem_block_desc的free_list中已经没有可用的mem_block就创建新的arena提供mem_block 6.从free_list中弹出一个内存块通过elem2entry宏转换成mem_block的地址返回内存块地址内存释放(页框级别) 分配内存的步骤 1.虚拟地址池中分配虚拟地址操作位图 2.物理内存池中分配物理地址操作位图 3.完成虚拟地址和物理地址的映射 释放内存的步骤 1.释放物理页地址操作位图 2.在页表中去掉虚拟地址的映射将虚拟地址对应pte的P位置0 3.在虚拟地址中释放虚拟地址操作位图 当物理内存不多时就将其数据移到硬盘中然后对应页表项pte的P位置0当CPU访问时会引发pagefault中断中断处理程序将数据物理页更新到pte中再将P位置1CPU会再次访问引起pagefault的虚拟地址。实现sys_free 对于大内存就是把页框在虚拟内存池和物理内存池的位图中相应位置0。 对于小内存是将arena中的内存块重新放回到内存块描述符的空闲块链表free_list。
第十三章
编写硬盘驱动略
第十四章
硬盘的读写单位是扇区数据一般积攒到足够大小才一次性访问硬盘足够大小的数据就是块一个块由多个扇区构成。FAT32 用链表的方式来连接每个数据块查询某个数据块很耗时inode 控制管理文件相关信息的数据结构是FCBinode就是其中一种。 用索引来查找数据块在UNIX系统中一个文件必须对应一个inode(索引表)磁盘中有多少文件就有多少个inode。inode的结构如下如图前12个索引为直接指针后面的3个为间接索引的地址。每个间接索引表都可存256个块。 在Linux中每分区inode数量是固定的分区中所有文件的inode通过一个大表格来维护此表格称为inode_table。目录项 通过文件名找文件实体数据的流程是 1.在目录中找到文件名所在的目录项 2.从目录项中获取inode编号 3.用inode编号作为inode数组的索引下标找到inode 4.从该inode中获取数据块的地址读取数据块 目录项仅存在于inode指向的数据块中有目录项的数据块就是目录目录项所属的inode指向的所有数据块便是目录。 每个分区都有自己的根目录根目录/的位置是固定不变的查找任意文件时都直接到根目录的数据块中找相关的目录项然后递归查找最终可以找到任意子目录中的文件。超级块 超级块是保存文件系统元信息的元信息。它被固定在各分区的第2个扇区。 文件系统布局 Linux早期文件系统布局如下图
第十五章
fork fork()会产生一个和父进程完全相同的子进程但子进程在此后多会exec系统调用出于效率考虑Linux中引入了“写时复制“技术也就是只有进程空间的各段的内容要发生变化时才会将父进程的内容复制一份给子进程。在fork之后exec之前两个进程用的是相同的物理空间内存区子进程的代码段、数据段、堆栈都是指向父进程的物理空间也就是说两者的虚拟空间不同但其对应的物理空间是同一个。当父子进程中有更改相应段的行为发生时再为子进程相应的段分配物理空间如果不是因为exec内核会给子进程的数据段、堆栈段分配相应的物理空间至此两者有各自的进程空间互不影响而代码段继续共享父进程的物理空间两者的代码完全相同。而如果是因为exec由于两者执行的代码不同子进程的代码段也会分配单独的物理空间。为什么fork后父子进程同一个变量地址打印出来相同 假定父进程malloc的指针指向0x12345678, fork 后子进程中的指针也是指向0x12345678但是这两个地址都是虚拟内存地址 virtual memory)经过内存地址转换后所对应的 物理地址是不一样的。所以两个进城中的这两个地址相互之间没有任何关系。 fork时子进程获得父进程数据空间、堆和栈的复制所以变量的地址当然是虚拟地址也是一样的。 每个进程都有自己的虚拟地址空间不同进程的相同的虚拟地址显然可以对应不同的物理地址。因此地址相同虚拟地址而值不同没什么奇怪。 具体过程是这样的 fork子进程完全复制父进程的栈空间也复制了页表但没有复制物理页面所以这时虚拟地址相同物理地址也相同但是会把父子共享的页面标记为“只读”类似mmap的private的方式如果父子进程一直对这个页面是同一个页面知道其中任何一个进程要对共享的页面“写操作”这时内核会复制一个物理页面给这个进程使用同时修改页表。而把原来的只读页面标记为“可写”留给另外一个进程使用。 这就是所谓的“写时复制”。正因为fork采用了这种写时复制的机制所以fork出来子进程之后父子进程哪个先调度呢内核一般会先调度子进程因为很多情况下子进程是要马上执行exec会清空栈、堆。。这些和父进程共享的空间加载新的代码段。。。这就避免了“写时复制”拷贝共享页面的机会。如果父进程先调度很可能写共享页面会产生“写时复制”的无用功。所以一般是子进程先调度滴。 注1在理解时你可以认为fork后这两个相同的虚拟地址指向的是不同的物理地址这样方便理解父子进程之间的独立性 注2但实际上Linux为了提高 fork 的效率采用了 copy-on-write 技术fork后这两个虚拟地址实际上指向相同的物理地址内存页只有任何一个进程试图修改这个虚拟地址里的内容前两个虚拟地址才会指向不同的物理地址新的物理地址的内容从原物理地址中复制得到wait和exit 进程间通信必须要借助内核无论管道、消息队列、还是共享内存等进程间通信形式子进程的返回值肯定是先交给内核然后父进程向内核要子进程的返回值。父进程调用pid_t wait(int *status)后内核就把子进程的返回值存储到status指向的内存空间。子进程的返回值存放在它的PCB中调用exit后内核会把进程占用的大部分资源回收比如内存、页表等但不能回收PCB需要将其中的返回值交给父进程后才能回收。 exit调用表面上是结束子进程运行并传递返回值给内核本质上是内核在幕后将进程除了PCB以外的所有资源回收。孤儿进程 父进程提前退出父进程的子进程会称为孤儿进程被init进程收养僵尸进程 僵尸进程就是没有父进程来给某进程收尸也就是调用wait收取返回值因此其PCB一直不能被回收。管道 Linux中管道实现如下图 其实就是对一页框大小的内存区域做读写操作 匿名管道在内核中父子进程因为有相同的管道描述符所以都可以访问这个管道。 有名管道在文件系统中创建一个管道文件FIFO是一种特殊的文件类型使得该管道对任何进程都可见因此没有父子关系也能通信。当一个进程以读(r)的方式打开该文件而另一个进程以写(w)的方式打开该文件那么内核就会在这两个进程之间建立管道所以FIFO实际上也由内核管理不与硬盘打交道。 Linux共享内存信号 http://blog.csdn.net/lqygame/article/details/71424917 http://blog.csdn.net/lqygame/article/details/73555430
写在最后 每天晚上看一点历时接近1个月终于把这本书读完感谢钢哥这本书刷新了我对操作系统的认知总算对操作系统有了个很全面的了解。这些笔记是针对我自己的一些感觉需要记录下来的东西OS还需要学习的东西还有很多啊。 --------------------- 作者月黑风高云游诗人 来源CSDN 原文https://blog.csdn.net/lqygame/article/details/73850249 版权声明本文为博主原创文章转载请附上博文链接