全局描述符表GDT(Global Descriptor Table):

(1)在整个系统中,全局描述符表(注意这里是表,表只有一张)GDT只有一张(一个处理器对应一个GDT)。

(2)GDT可以被放在内存的任何位置,但CPU必须知道GDT的入口,也就是基地址放在哪里,Intel的设计者门提供了一个寄存器GDTR用来存放GDT的入口地址,程序员将GDT设定在内存中某个位置之后,可以通过LGDT指令将GDT的入口地址装入此积存器,从此以后,CPU就根据此寄存器中的内容作为GDT的入口来访问GDT了。GDTR中存放的是GDT在内存中的基地址和其表长界限。

每一个LDT自身作为一个段存在,它们的段描述符被放在GDT(全局描述符表中)中。

每一个段描述符由一下几部分组成:
(1)32位的base域,含有段的第一个字节的线性地址

(2)粒度位G,如果被清0,段大小以字节为单位,否则以4096(4kB)字节为基本单位

(3)20位的limit域,指定了以字节为单位的段长度,如果G被置0,则是一个非空段大小在1个字节到1M之间变化的,否则将在4KB到4GB之间变化

(4)系统标志S,如果被清0.则是一个系统段,存储内核数据结构,否则他是一个普通的代码段或数据段

(5)4位TYPE域,描述了段的类型特征和他存取权限,一下类型的段描述符被广泛采用

代码段描述符:

这个段描述符代表一个代码段,可以是GDT或LDT中,S标志位1

数据段描述符:

这个段描述符代表一个数据段,可以放在GDT或LDT 中,S标志为1,栈段一般通过一般数据段实现

任务状态段描述符:

这个段描述符代表一个任务状态段(Task state segment,TSS),也就是说这个段用于保存寄存器的内容,他只呢个放在GDT中,分组相应的进程是否正在CPU 上运行,其TYPE域的值分别为11或9,S标志为0

局部描述符表描述符:

这个段描述符代表一个LDT段,他只能放在GDT中,相应的TYPE为2,S标志为0

(6)2位DPL(描述符特权级),用来限制对这个段的存取,他表示方位这个段,cpu所需要的最小特权级

(7)segment-present 标志,设置为0 ,标志这个段当前不在主存中,Linux总是把这个域设为1,因此它从来不把整个段交换到磁盘上去。

(8)一个被称为D或B的额外标志,取决于是代码段还是数据段。D或B的含义在两种情况下稍微有区别。但是,段偏移量的地址是32位,他被置为1,如果偏移量是16位,它被置为0

(9)第53位是保留位,总是设为0

(10)AVL标志,可以被操作系统使用,但是被Linux

进程:

内核必须知道进程的优先级,进程的状态,给进程分配什么样的地址空间,允许访问哪些文件,这些信息都被记录在一个叫——进程描述,的结构中。

进程描述符号都是task_struct{}类型的。

进程状态:

TASK_RUNNING(可运行状态) :

进程要么在CPU中运行,要么准备运行.

TASK_INTERRUPTBLE(可中断的等待状态):

进程被挂起(睡眠),知道一些条件为真,这些条件包括,硬件中断,释放进程等待的资源,或传递一个信号,都可以唤醒一个进程,让进程进入TASK_RUNNING状态

TASK_UNINTERRUPTBLE(不可中断的等待):

该状态和前一个状态类似,但是不能被信号唤醒,要满足特殊的状态才能被唤醒。

TASK_STOPPED(暂停状态):

所谓的暂停状态是指,进程任然在使用CPU 但是,在某个时间,停止运行,当进程接收到信号SIGSTOP,SIGSTP.........等信号时,就会进入该状态。进程用于软件的调试

TASK_ZOMBIE(僵死状态):

进程的执行被终止,但是父进程还没有发布wait()类系统调用以返回死进程的相关信息,如果没有返回相应的信息,内核系统就不能 丢弃死进程中的描述符中的数据,因为符进程可能需要他。

进程描述符的存放:

task 数组中的仅仅包含进程描述符的指针,而不是进程描述符本身。因为进程是动态实体,所以被放在动态内存中,而不是放在永久性分配的内核内存区。Linux把两个不同的数据结构紧凑的放在一个单独为进程分配的存储区域内:(1)一个是内个态的进程堆栈(2)另外一个是紧挨进程描述符的小数据结构中——thread_info(线程描述符)

进程堆栈段和线程描述符总共有8KB的空间

注意:从效率上来讲,进程堆栈段和线程描述结构紧密结合带来的好处是:内核很容易从esp寄存器的值获得当前在CPU 正在运行的thread_info 结构的地址

进程链表:

为了对给定进程类型(可运行的所有进程)进行有效的搜索。内核建立几个进程链表(每个进程链表由指向进程描述符的指针组成,PID存放在进程描述符的PID描述符中)。进程描述符的数据结构中包含了一个指向下一个进程链表指针。

注意:进程链表的链表头是init_task描述符,他是所有进程的祖先。

相关函数:

宏:

SET_LINKS/REMOVE_LINKS //用来链表中插入和删除一个进程描述符

for_each_task()//用来扫描整个进程链表

进程链表——TASK_RUNNING状态的进程链表:

当内核需要寻找一个新的进程在CPU 上运行,必须考虑可运行的进程。如果扫描整个进程链表效率太低了。因此引入可运行状态进程双向链表,也叫做运行队列(runqueue),和一般的进程链表一样,init_task作为链表头,nr_running变量存放可运行队列进程总数

相关函数:

添加和删除:

add_to_runqueue()//把一个进程描述符插入到链表的开始

del_from_runqueue()//从进程中删除一个进程描述符

队列调度:

move_first_runqueue()

move_last_runqueue()

唤醒进程:

wake_up_process()//将一个进程的状态设置为TASK_RUNNING

进程链表——pidhash表及链接表:
当一个进程需要向另外一个进程发送信号,如果采用遍历扫描他消耗时间,然后就使用pidhash 算法。不懂!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

相关函数:

hash_pid()//在pidhash 表中插入进程

unhash_pid()//在pidhash 表中删除一个进程

find_task_by_pid()//查找散列表并返回给定PID 进程的进程描述符指针(如果没有找到则返回空指针NULL)

进程链表中——task空闲表象列表

每当进程被创建或撤销时,就要更新task数组。把一个新项有效的加到数组中去方式,不是线性的寻找列表中找到一个空闲项,而是内核维持了一个独立的包含空闲项的非循环双向列表,这个数组中的每一个空闲项指向下一个空闲项。而链表中的最后一个元素包含空指针,当一个进程被撤销时,task中对应的元素加到表头。

相关函数:

get_free_taskslot()//获得空闲进程描述符表项

add_free_taskslot()//添加空闲进程描述符表项

进程之间的亲属关系:

进程之间的关系无非是父子和兄弟之间的 关系,在进程描符中引出几个域来描述这种关系

等待队列:

运行队列链表把处于TASK_RUNNING 状态的进程组织到一起,同理运行队列列表也会把处于其他状态的组织到一起。

(1)TASK_STOPPED 或TASK_ZOMBIE状态的进程不链接在专门的链表中也没有必要分组,因为父进程可以通过进程PID ,或进程之间的亲属关系检索到子进程

(2)把TASK_INTERRUPTIBLE和TASK_UNINTERRUPTIBLE分类,每一类完成特定类型的,这样进程状态满足不了快速检索进程,因此有必要引入另外的进程链表——等待队列。

进程调度:

Linux内核代码之重要函数

modify_ldt(int func, void *ptr, unsigned bytecount):

该系统调用用来改变当前进程的局部段描述表

Linux内核代码之重要数据

<wiz_tmp_tag id="wiz-table-range-border" contenteditable="false" style="display: none;">

 
 
 
 

Linux内核代码的更多相关文章

  1. [转] Linux内核代码风格 CodingStyle [CH]

    from:http://blog.csdn.net/jiang_dlut/article/details/8163731 中文版维护者: 张乐 Zhang Le <r0bertz@gentoo. ...

  2. 从linux内核代码分析操作系统启动过程

    朱宇轲 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 在本次的实验中, ...

  3. 第三次阅读赵炯博士的《linux内核代码完全注释》:序

    这是我第三次阅读linux内核代码完全注释了,当然前两次也没有读完,第一次读到第五章,第二次第七章. 所以说,赵炯博士对我最大的帮助时介绍了intel386的结构,以及内核编程的方法. 至于真正的内核 ...

  4. 使用QEMU调试Linux内核代码

    http://blog.chinaunix.net/uid-20729583-id-1884617.html http://www.linuxidc.com/Linux/2014-08/105510. ...

  5. win7 变WIFI热点 & 在线Linux 内核代码

    https://daniel.haxx.se/docs/sshproxy.html netsh wlan set hostednetwork mode=allow ssid=mywifi  key=1 ...

  6. linux内核代码的编写初步以及makefile的配置

    在linux内核代码开发中,头文件不能包含标准C头文件,只能采用GNC标准 而且内核开发中没有main函数,只有init 和 exit ,这是每个内核模块中必须要包含的函数模块. 在GNU C标准中, ...

  7. Linux学习笔记:【004】Linux内核代码风格

    Chinese translated version of Documentation/CodingStyle   If you have any comment or update to the c ...

  8. linux内核代码注释 赵炯 第三章引导启动程序

    linux内核代码注释 第三章引导启动程序 boot目录中的三个汇编代码文件   bootsect.s和setup.s采用近似intel的汇编语法,需要8086汇编器连接器as86和ld86 head ...

  9. Linux 内核代码风格

    文章目录 从编码风格错误开始 快速修改编码风格的工具 scripts/checkpatch.pl scripts/Lindent astyle Linux 内核代码风格 1) 缩进 2) 把长的行和字 ...

随机推荐

  1. window下卸载MySQL

    更多内容推荐微信公众号,欢迎关注: 网上找来的,留在这做个备份. 1.控制面板里的增加删除程序内进行删除 2.删除MySQL文件夹下的my.ini文件,如果备份好,可以直接将文件夹全部删除 3.开始- ...

  2. C# 图片和Base64之间的转换

    public static Bitmap GetImageFromBase64String(string strBase) { try { MemoryStream stream = new Memo ...

  3. Python——杂记

    python 最近出错总结: 1.而for..in ..中不要用else if  x in y:     print  else:     print2.def fibs(num): ...     ...

  4. [MySQL FAQ]系列 — EXPLAIN结果中哪些信息要引起关注

    我们使用EXPLAIN解析SQL执行计划时,如果有下面几种情况,就需要特别关注下了: 首先看下 type 这列的结果,如果有类型是 ALL 时,表示预计会进行全表扫描(full table scan) ...

  5. GDB调试基础

    GDB调试基础 https://lesca.me/archives/gdb-basic-knowledge.html GDB笔记(二):条件断点.命令列表.监视点 https://lesca.me/a ...

  6. ClientDataset 三层 var and out arguments must match parameter

    ​​​将Delphi升级到10.1.2后,从客户端传ClientDataset的Delta数据到服务端程序时,出现var and out arguments must match parameter错 ...

  7. Mysql 监控性能状态 QPS/TPS【转】

    QPS(Query per second) 每秒查询量 TPS(Transaction per second)每秒事务量 这是Mysql的两个重要性能指标,需要经常查看,和Mysql基准测试的结果对比 ...

  8. C# 托管资源 与 非托管资源

    C# 托管资源 与 非托管资源 托管资源一般是指被CLR控制的内存资源,这些资源的管理可以由CLR来控制,.NET可以自动进行回收,主要是指托管堆上分配的内存资源.例如程序中分配的对象,作用域内的变量 ...

  9. python网络编程-动态导入和断言

    一:动态导入importlib 在程序运行的过程中,根据变量或者配置动态的决定导入哪个模块,可以使用模块importlib importlib使用示例 二:断言assert 如果接下来的程序依赖于前面 ...

  10. java基础22 日期类、日历类、日期格式类

    package com.dhb.code; import java.text.ParseException; import java.text.SimpleDateFormat; import jav ...