Linux系统概要总结

原创 2011年01月21日 18:41:00

这篇文章概要地把整个LINUX系统(0.11)串起来。部分图片来自于《Linux内核完全注释》一书,版权归原作者所有。另,以下总结,纯属个人观点,并不一定是对的,欢迎指正。

 

零. 总括

   image

  LINUX 系统总的来说分为几部分管理,即内存,进程,文件系统,中断,进程通信,网络接口

 

一. 硬件

image

Linux 0.11是基于80386系统芯片的。所以寄存器信息如下

http://blog.csdn.net/yunsongice/archive/2010/10/04/5921873.aspx

 

个人觉得,对操作系统理解,首先要清楚我们有什么样的硬件,这些硬件提供什么样的功能。

CPU:取指令(CS+IP。根据设置,可能运行于实模式,即物理=CS*16+IP。也可能是保护模式,即CS里可能是段描述符,需要进行虚->线性的转换。另外,当开启了分页机制时,还需要线性->物理的转换) + 执行指令(当CS或IP值有变化时,通过上面所说的步骤,取到正确的指令,并执行)

 

二. 内存管理

    1. 三个重要概念

     虚拟地址:CS+IP中的就是虚拟地址(这样说未必很准确,不过可以让我们有个概念)

    线性地址: 开启段保护后,CS中存入的是描述符,由段描述符得到段基址,加上偏移,得到线性地址。

    物理地址: 真正的内存地址。当没有开启分页时,线性地址就是物理地址。当开启分页时,分割为4K一页,采用二级目录形式(传说中这样比较省空间,因为二级目录是可以动态分配的)。由于线性到物理的映射是由所有任务共有(采用同样的映射方法),所以段映射时得到的线性地址不可以重合(理论上,但其实有的会故意重合)。

   2. 映射

   涉及到GDT,LDT, CR3等等。

image

GDT指向全局描述符表,为所有任务共有。其中,内核数据段,代码段的描述符放在里面 + TSS + 任务的LDT表

LDT指向局部表,每个任务有自己的LDT。

个人觉得GDT和LDT映射出来的线性空间是不重叠的。

image

    上图描述了三种地址的关系

3. 线性内存的分配

image 

image

前16M用于内核,包括内核所有代码、内核段表(GDT,IDT,TSS)、页目录表和内核二级页表、内核局部数据及临时堆栈。而且其线性地址与物理地址应是一一对应的。这样GDTR指向的就是GDT的地址了。

4. 物理内存的分配

image

5. 保护机制

   CPL: 应该是CS,SS段寄存器里0,1位的东东(这也是段选择符的0,1,不过它只是CS,SS的)

   RPL: 是段选择符的0,1位

   DPL: 是段描述符里的

image

代码段的控制权转移可通过 JMP,RET,INT,IRET及异常和中断机制。即目标代码段的段选择符必需要加载至CS中(会先有一系列安全机制检查)。

 image

三. 进程管理

   1. 系统调用

      系统调用的根在于用int 80产生中断,然后由中断处理程序,对传入的系统调用号进行处理(eax用于存放调用号,ebx,ecx,edx用于传参),源码的include/unistd.h中有相关定义。

    2. 用户态堆栈和内核堆栈

     image

  用户态堆栈为线性地址,栈底在其64M空间的最高(除参数外)。

 

image

内核堆栈是当进程由用户态转向内核态时产生的。它是位于其任务数据结构所在页面的末端(task_struct),即与任务数据结构放在同一页面中。

p->tss.esp0 = PAGE_SIZE + (long)p;

p->tss.ss0 = 0x10;

image

  3. 什么是一个任务

    GDT里有它的LDT,TSS。LDT中定义了code, data段,放入task[]里。

 四. 中断

采用8259A可编程中断控制芯片。二级联,共可有15个中断

image

中断int 0- int 31,由Intel公司设定或保留,属软件中断,不过intel称为异常(又分为故障和陷阱两类)

image

int 32- int 47,对应8259的中断。而int 80则是用来系统调用中断

image

对应代码:

image

IDT中可以包含中断门,陷阱门和任务门。

要区分两种中断,一种是过程调用,另一个是任务切换,个人觉得前者是用栈,后者则通过TSS保存必要信息。

image

 

五. 文件系统

Linux 0.11中用的是MINIX文件系统。文件系统提供了文件的管理方式,应该有以下几种

image

文件系统可以放在多种类型的存储介质上,比如软盘,硬盘等。所以不同的介质需要相应的驱动(块,字符)。

以下按照MINIX介绍

image

有8个超级块,因此最多支持8个文件系统。每个超级块纪录了根目录的I节点(每个文件或目录都有一个I节点)。

image

如,要查找/usr/bin/vi的i节点号,首先从根节点i节点号(固定1)开始,即从i节点号1的数据块中查找到名称为usr的目录项,从而得到文件/usr的i节点号,再得到bin的目录项,依次得到vi的i节点号

看文件系统与具体设备的交互可以选择一个系统调用函数,一层层剖析,比如sys_read,可以一路跟踪到最终是通过什么基操作实现的。

image

----------------------------------------------------------源代码----------------------------------

一. 系统启动,引导 (boot, linux/boot/目录下)

image

其中,bootsect.s及setup.s是16位代码程序,使用intel 的as86和ld86编译。而head.s则是AT&T语法,GNU 的AS编译。

image

开机—>bios(自检,跳转至引导)—>boot(拷贝必要文件,初始化GDT,IDT,LDT,处理器和协处理器,分页工作等)注意,head.s是编入了system中的--->进入实模式,执行setup.s(它位于地址0处),调用init/main.c中main函数

step 1. 当开机时,是实模式,CS置F000,IP置FFF0H,所以CS*16+IP=FFFF0。

step 2. 这里是BIOS的跳转指令。

step 3. 跳到BIOS开始执行,进行自检,初始化中断向量等。并且,将引导设备的第一扇区(bootsect.s)读入0X7C00处。

step 4.跳转至7C00.

image

image

image

image

索引有 2^13 = 8k,即8192个。段选择符用于段寄存器,CS,DS,ES… 它可指向GDT或LDT中其中一项。

image

描述符格式如下

image

描述符由TYPE和S指定不同的类型。其中S用于标志是数据代码描述符(S=1)或者是系统描述符(LDT,TSS,调用门,中断门,陷阱门,任务门)

GDT中能存储的最大段描述符为256个(2K),其中2项空闲,2项系统使用,其余进程使用,理论上可有126个进程,不过0.1版本规定了最大64个。

image

 

当head.s执行完成后,内存中分布如下:

image 

 

二. 内核初始化

 

image

image

三. kernel

1. sched.c

   用于进程调度。 全部的进程放在task中

struct task_struct * task[NR_TASKS] = {&(init_task.task), };

image

 

调度的核心

while (1)
{
    c = -1;
    next = 0;
    i = NR_TASKS;
    p = &task[NR_TASKS];
    while (—i) //这里不会执行到0的情况
    {
        if (!*—p)  
            continue;
        if ((*p)->state == TASK_RUNNING && (*p)->counter > c)
            c = (*p)->counter, next = i;
    }
    if (c) break;
    for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)
        if (*p)
            (*p)->counter = ((*p)->counter >> 1) +
                    (*p)->priority;
}

和pause的关系,什么时候会调用schedule,和main函数关系

2. 系统调用

以fork为例

1. main.c中的调用

static inline _syscall0(int,fork);

---->int 80, __NR_fork(发生中断时,会查询IDT表,根据描述符找到中断处理。在sched.c中,set_system_gate(0x80,&system_call);将80中断与system_call联系起来)

---->system_call(system_call.s中,具体将按照下图所示进行,但简略来说是下面两步)

--->sys_call_table[__NR_fork](sys.h)

---->sys_fork(sys.h, system_call.s)

image

其中,

fn_ptr sys_call_table[] = { sys_setup, sys_exit, sys_fork, sys_read,
sys_write, sys_open, sys_close, sys_waitpid, sys_creat, sys_link,
sys_unlink, sys_execve, sys_chdir, sys_time, sys_mknod, sys_chmod,
sys_chown, sys_break, sys_stat, sys_lseek, sys_getpid, sys_mount,
sys_umount, sys_setuid, sys_getuid, sys_stime, sys_ptrace, sys_alarm,
sys_fstat, sys_pause, sys_utime, sys_stty, sys_gtty, sys_access,
sys_nice, sys_ftime, sys_sync, sys_kill, sys_rename, sys_mkdir,
sys_rmdir, sys_dup, sys_pipe, sys_times, sys_prof, sys_brk, sys_setgid,
sys_getgid, sys_signal, sys_geteuid, sys_getegid, sys_acct, sys_phys,
sys_lock, sys_ioctl, sys_fcntl, sys_mpx, sys_setpgid, sys_ulimit,
sys_uname, sys_umask, sys_chroot, sys_ustat, sys_dup2, sys_getppid,
sys_getpgrp, sys_setsid, sys_sigaction, sys_sgetmask, sys_ssetmask,
sys_setreuid,sys_setregid };

以上的实现,只有sys_frok和sys_execve用了汇编(system_call.s),其它的则是C实现的

对于main.c中最重要的部分,如下所示

    move_to_user_mode(); //这里将以下代码移到任务0中去执行。其实就是新建一个任务(之前没有任务,这个是任务0),通过指定不同的段,但最终物理地址指向同一位置实现
    if (!fork()) {        /* we count on this going ok */
        init();
    }
    for(;;) pause();

fork新建一个任务,并完全复制父进程的CS,IP,SS,SP等等(但内核栈不一样)。对于子进程来说,fork会返回0(实际上子进程没有执行fork,但因为eax置0,在if判断时相当于返回值是0,看下篇转载的文章),所以会执行init。而对于父进程,fork不会返回0,所以跳过执行for语句。

注:汇编调用C函数的传参

image

image

相关文章推荐

LINUX系统学习——安装与概要

VMware虚拟机安装与使用CPU:主频1GHz以上 内存:1GB以上 硬盘:分区空闲空间8GB以上 个人使用WMware建议版本8.0以下 系统分区磁盘分区 是使用分区编辑器(partiti...

linux系统安装总结

  • 2011年11月14日 15:31
  • 636KB
  • 下载

linux系统权限总结

  • 2013年07月18日 13:59
  • 393B
  • 下载

Linux系统下搭建DNS服务器——DNS原理总结

2017-01-07 整理 DNS原理域名到IP地址的解析过程IP地址到域名的反向域名解析过程抓包分析DNS报文和具体解析过程DNS服务器搭建和配置 这个东东也是今年博主参见校招的时候被很...

linux系统编程总结

  • 2014年07月06日 21:27
  • 33KB
  • 下载

使用U盘安装Linux系统经验总结

Linux机器硬件及软件说明: Inter i386CPU,1.5GHz,512M内存   IDE硬盘(非常重要,如果是SATA硬盘,硬盘名称会有区别) 使用的U盘容量大于3.7GB   一、...

定制U盘Linux系统总结报告

  • 2016年01月11日 14:32
  • 165KB
  • 下载

转载_利用虚拟机VMWARE安装并配置Debian Linux系统的总结

由于Windows XP最近故障频频,近乎崩溃,被我在上周日一怒之下重装了。重装XP已经轻车熟路了,使用系统之家的硬盘安装工具,不到半个小时就搞定了,很是方便。 :)     但是重装带来的一个严重...

Linux系统中 任务、进程和线程总结

任务、进程和线程基本概念 多任务处理是指用户可以在同一时间内运行多个应用程序,每个正在执行的应用程序被称为一个任务。Linux 就是一个支持多任务的操作系统(Windows也是多任务操作系统),比起...
  • zolalad
  • zolalad
  • 2014年05月09日 16:03
  • 1547
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Linux系统概要总结
举报原因:
原因补充:

(最多只允许输入30个字)