在树莓派裸机编程中创建 C-library 个存根
creating C-library stubs in raspberry pie bare metal programming
我目前正在使用 raspberry pie 并遵循 Chap 2 of valvers.com 上写得很好的第 2 章教程。我设法理解了所有内容,但我几乎没有停留在标题为 "C-Library stubs" 的最后一节中。因为我面临下面提到的一些疑问:
#include <sys/stat.h>
/* A helper function written in assembler to aid us in allocating memory */
extern caddr_t _get_stack_pointer(void);
/* Increase program data space. As malloc and related functions depend on this,
it is useful to have a working implementation. The following suffices for a
standalone system; it exploits the symbol _end automatically defined by the
GNU linker. */
caddr_t _sbrk( int incr )
{
extern char _end;
static char* heap_end;
char* prev_heap_end;
if( heap_end == 0 )
heap_end = &_end;
prev_heap_end = heap_end;
if( ( heap_end + incr) > _get_stack_pointer() )
{
while(1)
{
/* TRAP HERE! */
}
}
heap_end += incr;
return (caddr_t)prev_heap_end;
}
到目前为止我只明白这是_sbrk函数的实现。
1). 根据 link?
中给出的教程,我无法理解这段代码的具体作用
2). 我无法理解的另一件事在 armc-008c 和 009c 中很常见,即我们为什么以及如何从 main 函数更改为 kernel_main 功能?唯一可用的文本提到
NOTE: We've now changed from main to kernel_main, and there's a reason for this - the bootloader is actually expecting a slightly different entry definition compared to the standard C main function. So as we're setting up our own C-Runtime anyway, we can define the correct entry format
我是 C 语言的初学者,这些问题听起来可能很菜鸟,但我做了很多研究,并在同一教程上花了 3 到 4 天,然后才在这里问这个问题。我仍在努力理解这些程序背后的逻辑。你们能阐明这个问题吗?这不仅仅是帮助。
提前致谢
您问题中的 _sbrk
函数试图 增加 extern 符号 _end
允许应用程序malloc 更多内存。 (它不直接递增 _end
而是 return 递增的值, heap_end
声明为 static 通过多个 _sbrk
保留值电话)
(我个人怀疑这个 _sbrk
实现是否经过测试,_end
声明为 char 而不是 pointer (* 丢失) 是可疑的并且 heap_end
假设被初始化为 0)
关于main
和kernel_main
,几乎每个C代码都需要一个入口点,对于普通的libc应用程序是 main
(是一个 libc 约定),但正如引用所说,在这种情况下使用了 bootloader 并且它期望(寻找)一个 kernel_main
符号跳入(引导加载程序通常不使用 libc)。 (至少 gcc)编译器的真正入口点是 _start
但 libc 隐藏它并使用它来准备 环境 以启动应用程序,可能是 this帮助您了解它的工作原理。
我目前正在使用 raspberry pie 并遵循 Chap 2 of valvers.com 上写得很好的第 2 章教程。我设法理解了所有内容,但我几乎没有停留在标题为 "C-Library stubs" 的最后一节中。因为我面临下面提到的一些疑问:
#include <sys/stat.h>
/* A helper function written in assembler to aid us in allocating memory */
extern caddr_t _get_stack_pointer(void);
/* Increase program data space. As malloc and related functions depend on this,
it is useful to have a working implementation. The following suffices for a
standalone system; it exploits the symbol _end automatically defined by the
GNU linker. */
caddr_t _sbrk( int incr )
{
extern char _end;
static char* heap_end;
char* prev_heap_end;
if( heap_end == 0 )
heap_end = &_end;
prev_heap_end = heap_end;
if( ( heap_end + incr) > _get_stack_pointer() )
{
while(1)
{
/* TRAP HERE! */
}
}
heap_end += incr;
return (caddr_t)prev_heap_end;
}
到目前为止我只明白这是_sbrk函数的实现。
1). 根据 link?
中给出的教程,我无法理解这段代码的具体作用2). 我无法理解的另一件事在 armc-008c 和 009c 中很常见,即我们为什么以及如何从 main 函数更改为 kernel_main 功能?唯一可用的文本提到
NOTE: We've now changed from main to kernel_main, and there's a reason for this - the bootloader is actually expecting a slightly different entry definition compared to the standard C main function. So as we're setting up our own C-Runtime anyway, we can define the correct entry format
我是 C 语言的初学者,这些问题听起来可能很菜鸟,但我做了很多研究,并在同一教程上花了 3 到 4 天,然后才在这里问这个问题。我仍在努力理解这些程序背后的逻辑。你们能阐明这个问题吗?这不仅仅是帮助。
提前致谢
您问题中的 _sbrk
函数试图 增加 extern 符号 _end
允许应用程序malloc 更多内存。 (它不直接递增 _end
而是 return 递增的值, heap_end
声明为 static 通过多个 _sbrk
保留值电话)
(我个人怀疑这个 _sbrk
实现是否经过测试,_end
声明为 char 而不是 pointer (* 丢失) 是可疑的并且 heap_end
假设被初始化为 0)
关于main
和kernel_main
,几乎每个C代码都需要一个入口点,对于普通的libc应用程序是 main
(是一个 libc 约定),但正如引用所说,在这种情况下使用了 bootloader 并且它期望(寻找)一个 kernel_main
符号跳入(引导加载程序通常不使用 libc)。 (至少 gcc)编译器的真正入口点是 _start
但 libc 隐藏它并使用它来准备 环境 以启动应用程序,可能是 this帮助您了解它的工作原理。