这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » MCU » Linux中的分段

共1条 1/1 1 跳转至

Linux中的分段

助工
2014-12-05 17:38:54     打赏
  Linux并不使用太多的分段,原因是某些RISC机器对分段的支持不好。为此Linux的分段都存在“全局描述表(GDT)”中,GDT是一个全局desc_struct数组(位于linux-2.6.32.59archx86includeasm),其结构如下:
  #define GDT_ENTRIES 16
  struct desc_struct gdt[GDT_ENTRIES];
  struct desc_struct {
  union {
  struct {
  unsigned int a;
  unsigned int b;
  };
  struct {
  u16 limit0; // 段大小
  u16 base0; // 段起始位置
  unsigned base1: 8, type: 4, s: 1, dpl: 2, p: 1; // type表示段类型,占4位;dpl指的段运行权限,占2位
  unsigned limit: 4, avl: 1, l: 1, d: 1, g: 1, base2: 8; //d 表示内存地址位宽,占1位
  };
  };
  } __attribute__((packed));
  所以我们可以看出,段描述结构体占8个字节,至于里面的a,b,那是老的方式,后来使用C++ Struts的Bit Fields后更方便了。type类型由以下几种:
  enum {
  DESC_TSS = 0×9,
  DESC_LDT = 0×2,
  DESCTYPE_S = 0×10, /* !system */
  };
  Linux主要使用以下几种段:
  内核代码段(Kernel Code Segment):type=10,dpl=0
  内核数据段(Kernel Data Segment):type=2,dpl=0
  用户代码段(User Code Segment):type=10,dpl=3
  用户数据段(User Data Segment):type=2,dpl=3
  任务状态段(Task State Segment),每进程一个:type=9,dpl=3
  其它类型可以参见linux-2.6.32.59archx86includeasmsegment.h,里面有非常详细的说明。
  它们都存储在“全局描述符表(GDT)”。Linux本身并不使用“局部描述符表(LDT)”,当一个进程被创建时,其指向的是一个默认的LDT,不过系统并不阻止进程创建它。也就是说一个进程最多两个段描述符:TSS与LDT。由于Segment Selector为16位(为什么只有16位,这个就是历史原因了,由于X86在Real Mode下段地址只有20位,其中有效的就是16位,详见:x86
  memory segmentation,但Linux段内偏移地址高达32位,所以线性地址总共是48位),其中有效的索引位仅有13位,所以GDT的最大长度为213-1=8192,除去系统保留的12个,留给进程的只有8180个入口,那么就意味Linux进程的最大数为8180/2=4090。需要注意的是,进程在创建的时候并不会马上创建自己的LDT,其指向的是GDT一个默认的LDT,里面的SD为null。只有在需要的时候进程才创建自己的LDT并把它放入GDT中。所以不管是LDT也好,TSS也好,它们都存放在GDT里面。而对于UCS与UDS,所有的进程共享一个。这样地址空间不会重复吗?不会,因为线性不是最终的物理地址,每个进程还有自己的页表,所以最终映射到物理地址是不同的。


共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]