Main函数的第一个函数Init_BSS()
位于./src/geekos/mem.c中
/* * Initialize the .bss section of the kernel executable image. */ void Init_BSS(void) { extern char BSS_START, BSS_END; /* Fill .bss with zeroes */ memset(&BSS_START, '\0', &BSS_END - &BSS_START); }
可以看到Init_BSS函数清空了从BSS_START到BSS_END的内存。
先来看memset的实现
位于./src/common/string.c中
void* memset(void* s, int c, size_t n) { unsigned char* p = (unsigned char*) s; while (n > 0) { *p++ = (unsigned char) c; --n; } return s; }
再来看一下外部声明BSS_START,BSS_END
位于/include/geekos/defs.h
/* * The windows versions of gcc use slightly different * names for the bss begin and end symbols than the Linux version. */ #if defined(GNU_WIN32) # define BSS_START _bss_start__ # define BSS_END _bss_end__ #else # define BSS_START __bss_start # define BSS_END end #endif
在project0下使用命令
$find ./ | xargs grep GNU_WIN32
可以看到,GNU_WIN32标志在./build/Makefile中定义,
用于区别windows下的cygwin编译环境和linux下的gcc,两者生成的elf文件的符号有细微的差别。
明显在Linux中定义的是后者。
再次搜索
$find ./ | xargs grep __bss_start
可以看到__bss_start符号出现在内核符号表kernel.syms中
我把这一段贴出来
0001a5dc A __bss_start 00018b58 r __func__.1314 000185fb r __func__.1319 00018fcd r __func__.1319 00019289 r __func__.1319 00018ad2 r __func__.1331 000188f1 r __func__.1333 0001860c r __func__.1335 00018fde r __func__.1335 0001929a r __func__.1335 00018afc r __func__.1347 00018902 r __func__.1349 00018c00 r __func__.1369 00018c11 r __func__.1385 00018438 r __func__.1386 00018573 r __func__.1393 00018fb1 r __func__.1395 00018fed r __func__.1412 0001861b r __func__.1426 00018cbc r __func__.1430 0001841e r __func__.1433 00018c43 r __func__.1444 000185ef r __func__.1448 00018cd4 r __func__.1469 00018fab r __func__.1469 00018be8 r __func__.1481 00018c9f r __func__.1485 00018ae3 r __func__.1495 00018fa5 r __func__.1499 00018bdf r __func__.1508 00018fa0 r __func__.1523 000188df r __func__.1532 000188d5 r __func__.1557 000188c8 r __func__.1609 00018f9a r __func__.1618 00018b1f r __func__.1635 00018b16 r __func__.1676 000186b8 r __func__.1684 00019312 r __func__.1689 000186d9 r __func__.1700 00018b0b r __func__.1716 00018ac8 r __func__.1743 0001907c r __func__.1743 000192ec r __func__.1747 0001906d r __func__.1774 000186c9 r __func__.1785 00018964 r __func__.1785 0001905c r __func__.1797 000193a4 r __func__.1829 00019094 r __func__.1838 00019087 r __func__.1850 00019052 r __func__.1867 000193e7 r __func__.1887 00019046 r __func__.1901 00019037 r __func__.1927 000193d8 r __func__.2035 00019341 r __func__.2054 00019333 r __func__.2065 000193c3 r __func__.2085 000193d1 r __func__.2115 000192b4 r __func__.2165 00019352 r __func__.2181 00019394 r __func__.2235 0001937f r __func__.2246 0001936d r __func__.2269 00019364 r __func__.2282 0001935e r __func__.2300 0001934d r __func__.2319 0001932e r __func__.2341 0001930d r __func__.2399 00019305 r __func__.2412 000192e0 r __func__.2428 000192d2 r __func__.2443 000192c7 r __func__.2463 000192a9 r __func__.2476 00019274 r __func__.2492 0001a5dc A _edata 0001bbf8 A _end 000180b5 T atoi 00013907 T bget 00013b58 T bgetr 00013bf6 T bgetz 00013410 T bpool 00013558 T brel 00012b2f T crc32 0001b080 b crc_table 0001bbf8 A end
bss段是用来存放程序中未初始化的全局变量的一块内存区域。
在这里,可以看到bss段中存储着一些系统库函数的地址。
具体bss段详细内容,下次再补充。
Init_BSS函数到此结束。
----------------------------------------------------------------------------------------------------
再来看主函数中的下一个函数Init_Screen()的实现
位于./src/geekos/screen.c中
/* * Initialize the screen module. */ void Init_Screen(void) { bool iflag = Begin_Int_Atomic(); s_cons.row = s_cons.col = 0; s_cons.currentAttr = DEFAULT_ATTRIBUTE;//设置终端界面的当前属性,默认为黑底灰字 Clear_Screen(); End_Int_Atomic(iflag); }
位于./include/geekos/int.h
/** * Start interrupt-atomic region. * @return true if interrupts were enabled at beginning of call, * false otherwise. */ static __inline__ bool Begin_Int_Atomic(void) { bool enabled = Interrupts_Enabled(); if (enabled) Disable_Interrupts(); return enabled; }
再来看Begin_Int_Enable()下的Interrupts_Enabled()函数
位于/src/geekos/int.c中
/* * Query whether or not interrupts are currently enabled. */ bool Interrupts_Enabled(void) { ulong_t eflags = Get_Current_EFLAGS(); return (eflags & EFLAGS_IF) != 0; }接着看Interrupts_Enabled()中的Get_Current_EFLAGS()
位于/src/geekos/lowlevel.asm
; Return current contents of eflags register. align 16 Get_Current_EFLAGS: pushfd ; push eflags pop eax ; pop contents into eax ret
/* * The interrupt flag bit in the eflags register. * FIXME: should be in something like "cpu.h". */ #define EFLAGS_IF (1 << 9)
再回到内联函数Begin_Int_Atomic中,它完成:若中断状态为开启,则执行Disable_Interrupts()关闭中断响应,返回1,否则返回0。
Disable_Interrupts()函数位于./include/geekos/int.h中
#define Disable_Interrupts() \ do { \ KASSERT(Interrupts_Enabled()); \ __Disable_Interrupts(); \ } while (0)
位于./include/geekos/kassert.h
define KASSERT(cond) \ do { \ if (!(cond)) { \ Set_Current_Attr(ATTRIB(RED, GRAY|BRIGHT)); \ Print("Failed assertion in %s: %s at %s, line %d, RA=%lx, thread=%p\n",\ __func__, #cond, __FILE__, __LINE__, \ (ulong_t) __builtin_return_address(0), \ g_currentThread); \ while (1) \ ; \ } \ } while (0)
位于./include/geekos/int.h
/* * Block interrupts. */ static __inline__ void __Disable_Interrupts(void) { __asm__ __volatile__ ("cli"); }
其实它就是完成:如果之前中断是开着的,则关中断,关中断之前判断中断确实是开着的;如果中断是关的,不做操作。
再来看临界区结束的End_Int_Atomic()开中断函数
位于./include/geekos/int.h中
/** * End interrupt-atomic region. * @param iflag the value returned from the original Begin_Int_Atomic() call. */ static __inline__ void End_Int_Atomic(bool iflag) { KASSERT(!Interrupts_Enabled()); if (iflag) { /* Interrupts were originally enabled, so turn them back on */ Enable_Interrupts(); } }
/* * Unblock interrupts. */ static __inline__ void __Enable_Interrupts(void) { __asm__ __volatile__ ("sti"); } #define Enable_Interrupts() \ do { \ KASSERT(!Interrupts_Enabled()); \ __Enable_Interrupts(); \ } while (0)
至此main.c中的第二个函数Init_Screen()分析完毕。
下一篇来分析下一个函数Init_Mem()。