【背景】操作系统执行代码的组成

ucore通过gcc编译和ld链接,形成了ELF格式执行文件kernel(位于bin目录下),这样kernel的内部组成与一般的应用程序差别不大。一般而言,一个执行程序的内容是至少由 bss段、data段、text段三大部分组成。

  • BSS段:BSS(Block Started by Symbol)段通常是指用来存放执行程序中未初始化的全局变量的一块存储区域。BSS段属于静态内存分配的存储空间。
  • 数据段:数据段(Data Segment)通常是指用来存放执行程序中已初始化的全局变量的一块存储区域。数据段属于静态内存分配的存储空间。
  • 代码段:代码段(Code Segment/Text Segment)通常是指用来存放程序执行代码的一块存储区域。这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读, 某些CPU架构也允许代码段为可写,即允许修改程序。在代码段中,也有可能包含一些只读的常数变量,例如字符串常量等。

ucore和一般应用程序一样,首先是保存在像硬盘这样的非易失性存储介质上,当需要运行时,被加载到内存中。这时,需要把代码段、数据段的内容拷贝到内存中。对于位于BSS段中的未初始化的全局变量,执行程序一般认为其值为零。所以需要把BSS段对应的内存空间清零,确保执行代码的正确运行。可查看init文件中的kern_init函数的第一个执行语句“memset(edata, 0, end - edata);”。

随着ucore的执行,可能需要进行函数调用,这就需要用到栈(stack);如果需要动态申请内存,这就需要用到堆(heap)。堆和栈是在操作系统执行过程中动态产生和变化的,并不存在于表示内核的执行文件中。栈又称堆栈, 是用户存放程序临时创建的局部变量,即函数中定义的变量(但不包括static声明的变量,static意味着在数据段中存放变量)。除此以外,在函数被调用时,其参数也会被压入发起调用函数的栈中,并且待到调用结束后,函数的返回值也会被存放回栈中。由于栈的先进后出特点,所以栈特别方便用来保存/恢复调用现场。可以把栈看成一个寄存、交换临时数据的内存区。堆是用于存放运行中被动态分配的内存空间,它的大小并不固定,可动态扩张或缩减,这需要操作系统自己进行有效的管理。