内核编译但不会与unistd.h引用链接

时间:2015-12-09 17:06:05

标签: c gcc linker kernel cross-compiling

我正在编写一个支持键盘/光标的小内核。一切都很好,直到我从unistd.h添加一个函数

kernel.c

@EmbeddedId

kernel.asm

@Embeddable

link.ld

#include "keyboard_map.h"
#include "keyboard.c"
#include "video.c"
#include <unistd.h>

void kmain(void)
{
    terminal_initialize();
    terminal_writestring("Hello, kernel World!\n");
    idt_init();
    kb_init();
    kprint_newline();
    writeSector();
    sleep(1);
    unsigned char c = readSector2();
    kprint((const char *)c);

    while(1);
}

我通过终端用gcc交叉编译器编译它,并在qemu上运行

bits 32

%define     COLS    80

section .text

    ;multiboot spec

    align 4

    dd 0x1BADB002              ;magic

    dd 0x00                    ;flags

    dd - (0x1BADB002 + 0x00)   ;checksum. m+f+c should be zero




global start

global keyboard_handler

global read_port

global write_port

global load_idt


extern kmain        ;this is defined in the c file

extern keyboard_handler_main



read_port:

mov edx, [esp + 4]

        ;al is the lower 8 bits of eax

in al, dx   ;dx is the lower 16 bits of edx

ret




write_port:

mov   edx, [esp + 4]

mov   al, [esp + 4 + 4]

out   dx, al

ret




load_idt:

mov edx, [esp + 4]

lidt [edx]

sti                 ;turn on interrupts

ret




keyboard_handler:                 

call    keyboard_handler_main

iretd




start:

cli                 ;block interrupts

mov esp, stack_space

call kmain

hlt                 ;halt the CPU




section .bss

resb 8192; 8KB for stack

stack_space:

我是c编程的新手,所以希望对于那里的人来说这是一个简单的问题。项目中还有其他几个c文件,但我确信问题必须在某个地方。如果unistd.h和sleep()被删除,一切都会有效,但是会在kc.o&#34;中创建一个错误,表示&#34;未定义的函数sleep()的引用。当试图链接该引用时。

这些参考文献在项目的其他地方也可以正常工作......

OUTPUT_FORMAT(elf32-i386)

ENTRY(start)

SECTIONS

 {

   . = 0x100000;

   .text : { *(.text) }

   .data : { *(.data) }

   .bss  : { *(.bss)  }

 }

...这进一步让我感到困惑,为什么unistd.h不会链接......但会编译。

1 个答案:

答案 0 :(得分:1)

包含unistd.h只是告诉编译器库中定义的东西(函数等)。它描述了库的接口,但没有描述库功能的实现。

这就是你的程序编译的原因。 unistd.h中有一个sleep()声明。它可能看起来像这样:

unsigned sleep(unsigned);

您可以查看它,它是一个文本文件。

问题在于,当您尝试链接时,没有任何内容定义sleep()。通常,sleep()和其他标准函数存在于预编译库中。名称类似于libc.a的东西.a文件是包含目标文件的存档,这些目标文件实现了库的功能,链接器可以将其与目标文件链接以解析对sleep()等内容的引用。

stddef.h stdint.h工作的原因是它们主要定义在编译时使用的类型和宏,但在链接时不需要任何其他目标代码。

您的链接行不包含任何库。我怀疑这是因为你的裸机环境没有。

你有几个选择。您可以尝试移植预先存在的库以在您的环境中工作,或者您可以编写自己的sleep()函数。

您可以查看ELLCC,它是提供库的一个(多个)交叉开发工具链。 ELLCC的裸机库正在进行中,但查看ELK blog posts可能会给你一些想法。