Chinaunix首页 | 论坛 | 博客
  • 博客访问: 104641
  • 博文数量: 76
  • 博客积分: 50
  • 博客等级: 民兵
  • 技术积分: 400
  • 用 户 组: 普通用户
  • 注册时间: 2007-07-18 21:41
文章分类

全部博文(76)

文章存档

2011年(76)

我的朋友

分类:

2011-09-06 14:00:00

最近一直在转载文章,光有input没有output。感觉良心上过不去,实在对不起Internet。刚吃完午饭,随手翻翻ULK3,关于Linux进程,线程和内核线程有几点理解,有些比较简单,有些比较深入,也都写下来和大家一起分享。另外想起公司部门最近搞了一个Linux COP(全称是什么,我也不大清楚),大家都很积极踊跃,据说公司还打算在今年11月份搞一个Linux技术比赛,瑞典总部General Manager还要来上海分公司观摩,(当然是有别的公务,然后来顺便观摩)真是一片欣欣向荣啊。

扯远了,闲话少说,还是聊技术吧。

Linux Kernel会为每个进程process分配一个task_struct,并把其放在内核的动态内存里。
对于每个process,内核把thread_info和内核态的进程stack放在一个8KB的page frame中。(昏倒,ChinaUnix居然不能直接贴图。。。)这样做的好处是通过屏蔽esp(栈顶单元寄存器,向内存开始的方向增长)的低13位就可以得到thread_info的基地址。具体如下(head.S):
movl $0xffffe000,%ecx /* or 0xfffff000 for 4KB stacks */
andl %esp,%ecx
movl %ecx,p
这样p就是当前运行在CPU上的进程的thread_info的指针了。另外我有一个问题:
movl (%ecx) p 
为什么这样写p就成了CPU上运行进程的PCB了呢,因为task字段在thread_info中的offset为0?等价于current_thread_info()->task?但是我觉得不用parentheses,在得到p以后(struct task *)p也可以表达拿到一个task指针啊,为什么一定要加这层括号呢。(清楚这一点的朋友请在博客中留言答复)

kernel thread,我们称它为内核线程。其实在Linux看来它只不过是没有用户空间的一个进程。也就是task_struct中的mm_struct指向NULL。比较常见的KT有kswapd,太powerful了,以后写一篇专门来介绍它。至于其他的还有ksoftirqd也是如雷贯耳,你ps -ef一下,看看排列靠前面的,后面最后一个字母带d的,(daemon的意思)基本上都是内核线程。另外,KT只运行在内核态。所以他们只使用大于PAGE_OFFSET的线性地址空间。

kernel_thread()函数创建一个新的kernel thread。所有进程的祖先叫process 0,或者历史上叫做swapper进程。顺便说一下,每一个CPU都有自己的一个swapper进程,其PID=0。主内核页全局目录放在swapper_pg_dir中。start_kernel()函数初始化内核需要的数据结构,激活中断,然后创建一个init进程:kernel_thread(init, NULL, CLONE_FS|CLONE_SIGHAND),是的,就是那个回收所有孤儿进程的init process。

顺便说到CPU register,以前学习微机原理时候觉得汇编寄存器这类东西很酷,呵呵,其实也是比较酷。据说WPS就是求伯君先生用汇编在DOS下写出来的。膜拜!Orz!这里说说我知道的Intel x86 CPU中几个常用的寄存器在Linux中的作用, cr0, cr3, eax, ebx, ecx, edx, eip:

cr0,最主要的其中的PG flag,如果PG=0,线性地址就被解释称物理地址,支持分页;另外:The CD flag of the cr0 processor register is used to enable or disable the cache circuitry. The NW flag, in the same register, specifies whether the write-through or the write-back strategy is used for the caches。(这个不是很常用,先记到这里以免忘记,摘自ULK3 Section 2.4.7.)
多补充几点:
cr0 是 x86 处理器 4个控制寄存器(CR0,CR1,CR2,CR3)中的一个。
PE (cr0 中的第 0 位) 位是启用保护(Protection Enable)标志位。该位设置时开启保护莫属,复位时则立即进入实地址模式。这个位仅开启段级保护,而没有开启分页机制。
PG (cr0 中的第 31 位) 位分页(Paging)标志位。该位置位时开启分页机制,复位时则禁止分页机制。在禁止分页机制时,所有的线性地址等同于物理地址。在开启这个标志位之前,必须已经或同时启动 PE 标志。也就是说,要启用分页机制,则 PE 和 PG 两个标志位都要置位。
下面是 PE 和 PG 的几种组合:
PEPG说明
00处理器工作在实地址模式
10处理器工作在没有开启分页机制的保护模式下
01由于不在保护模式下,故不能开启分页机制,此种组合无效
1
1
处理器工作在开启了分页机制的保护模式下

cr3,我的理解最重要的一点就是:The physical address of the Page Directory in use is stored in a control register named cr3. 也就是一个进程的页目录基地址。当然cr3还有PAE功能开启时候的一些其他功能,当时我觉得都没有上面这个功能主要。

eax,也是一个非常强大的寄存器,它主要用在进程调度时context switch或者在调用system call的时候作用。具体来说,比如在system call时,eax用来传递system call的id,另外ebx, ecx, edx,等等六个寄存器用来传递这个system call的参数。
说说进程切换的时候eax的作用,简单提一下prev, next, last,(ULK3 Section 3.3.3.1.) eax和edx中会分别保存prev, next的值。
当然eax也在其他的一些地方作为临时变量,你比如说在startup_32()中enable paging unit,就是通过loading swapper_pg_dir地址到cr3,然后设置cr0:
    movl $swapper_pg_dir-0xc0000000,%eax
    movl %eax,%cr3        /* set the page table pointer.. */
    movl %cr0,%eax
    orl $0x80000000,%eax
    movl %eax,%cr0        /* ..and set paging (PG) bit */

写了两个小时。先写到这里吧,有点累啊。
2011.8.13. 

下面是转载的:2011.08.15.
========================================================
控制寄存器
(控制寄存器(CR0,CR1,CR2,CR3)用于控制和确定处理器的操作模式以及当前执行任务的特性。)
    从上表可见,80386有四个32位的控制寄存器,分别命名位CR0、CR1、CR2和CR3。但CR1被保留,供今后开发的处理器使用,在 80386中不能使用CR1,否则会引起无效指令操作异常。CR0包括指示处理器工作方式的控制位,包含启用和禁止分页管理机制的控制位,包含控制浮点协处理器操作的控制位。CR2及CR3由分页管理机制使用。CR0中的位5—位30及CR3中的位0至位11是保留位,这些位不能是随意值,必须为0。  
控制寄存器CR0的低16位等同于80286的机器状态字MSW。  
    1.CR0中的保护控制位 
    控制寄存器CR0中的位0用PE标记,位31用PG标记,这两个位控制分段和分页管理机制的操作,所以把它们称为保护控制位。PE控制分段管理机制。 PE=0,处理器运行于实模式;PE=1,处理器运行于保护方式。PG控制分页管理机制。PG=0,禁用分页管理机制,此时分段管理机制产生的线性地址直接作为物理地址使    用;PG=1,启用分页管理机制,此时线性地址经分页管理机制转换位物理地址。由此可知,如果要启用分页机制,那么PE和PG标志都要置位。
    下表列出了通过使用PE和PG位选择的处理器工作方式。由于只有在保护方式下才可启用分页机制,所以尽管两个位分别为0和1共可以有四种组合,但只有三种组合方式有效。PE=0且PG=1是无效组合,因此,用PG为1且PE为0的值装入CR0寄存器将引起通用保护异常。需要注意的是,PG位的改变将使系统启用或禁用分页机制,因而只有当所执行的程序的代码和至少有一部分数据在线性地址空间和物理地址空间具有相同的地址的情况下,才能改变PG位。   
    2.协处理器控制位 
    控制寄存器CR0中的位1—位4分别标记为MP(算术存在位)、EM(模拟位,用于选择与协处理器进行通信所使用的协议,即指明系统中是用的是80386还是80286协处理器)、TS(任务切换位) 和ET(扩展类型位),它们控制浮点协处理器的操作。  
    当处理器复位时,ET位被初始化,以指示系统中数字协处理器的类型。如果系统中存在 80387协处理器,那么ET位置1;如果系统中存在80287协处理器或者不存在协处理器,那么ET位清0。EM位控制浮点指令的执行是用软件模拟,还是由硬件执行。EM=0时,硬件控制浮点指令传送到协处理器;EM=1时,浮点指令由软件模拟。TS 位用于加快任务的切换,通过在必要时才进行协处理器切换的方法实现这一目的。每当进行任务切换时,处理器把TS置1。TS=1时,浮点指令将产生设备不可用(DNA)异常。 MP位控制WAIT指令在TS=1时,是否产生DNA异常。MP=1和TS=1时,WAIT产生异常;MP=0时,WAIT指令忽略 TS条件,不产生异常。  
    在系统刚上电时,处理器被复位成pe=0,pg=0(即实模式状态),以允许引导代码在启用分段和分页机制之前能够初始化这些寄存器和数据结构。对于这类寄存器的使用是在实模式下方可使用。
    3.CR2和CR3 
    控制寄存器CR2和CR3由分页管理机制使用。  
    CR2用于发生页异常时报告出错信息。当发生页异常时,处理器把引起页异常的线性地址保存在CR2中。操作系统中的页异常处理程序可以检查CR2的内容,从而查出线性地址空间中的哪一页引起本次异常。  
    CR3 用于保存页目录表页面的物理地址,因此被称为PDBR。由于目录是页对齐的,所以仅高20位有效,低12 位保留供更加高级的处理器使用。向CR3中装入一个新值时,低12位必须为0;但从 CR3中取值时,低12位被忽略。每当用MOV指令重置CR3的值时,会导致分页机制高速缓冲区的内容无效,用此方法,可以在启用分页机制之前,即把PG 位置1之前,预先刷新分页机制的高速缓存。CR3寄存器即使在CR0寄存器的PG位或PE位为0时也可装入,如在实模式下也可设置CR3,以便进行分页机制的初始化。在任务切换时,CR3要被改变,但是如果新任务中CR3的值与原任务中CR3的值相同,那么处理器不刷新分页高速缓存,以便当任务共享页表时有较快的执行速度。 

阅读(920) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~