简体   繁体   English

内核编译但不会与unistd.h参考链接

[英]Kernel compiles but won't link with unistd.h reference

I'm writing a small kernel that has keyboard/cursor support. 我正在写一个具有键盘/光标支持的小内核。 Everything works great until I add a function from unistd.h 一切正常,直到我从unistd.h添加了功能

kernel.c 内核

#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);
}

kernel.asm 内核

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:

link.ld 链接

OUTPUT_FORMAT(elf32-i386)

ENTRY(start)

SECTIONS

 {

   . = 0x100000;

   .text : { *(.text) }

   .data : { *(.data) }

   .bss  : { *(.bss)  }

 }

I'm compiling it via terminal with a gcc cross compiler, and running it on qemu 我正在使用gcc交叉编译器通过终端对其进行编译,然后在qemu上运行

nasm -f elf /Users/par/Desktop/kernel.asm -o kasm.o
/usr/local/gcc-4.8.1-for-linux32/bin/i586-pc-linux-gcc -m32 -c -std=c99     /Users/par/Documents/HelloC/HelloC/kernel.c -o kc.o
/usr/local/gcc-4.8.1-for-linux32/bin/i586-pc-linux-ld -m elf_i386 -T /Users/par/Desktop/link.ld -o kernel kasm.o kc.o
qemu-system-i386 -kernel kernel

I'm new to c programming so hopefully this is an easy question for someone out there. 我是c编程的新手,所以希望这对那里的人来说是一个简单的问题。 There are several other c files in the project, but I'm confident the problem has got to be somewhere above. 项目中还有其他几个c文件,但是我相信问题一定在上面。 Again everything works if the unistd.h and sleep() are removed, but will create an error that says "Undefined reference to function sleep() in kc.o" when trying to link with that reference. 同样,如果删除unistd.h和sleep(),一切都会正常,但是当尝试链接到kc.o时,会产生一个错误,指出“未定义对kc.o中sleep()函数的引用”。

Also these references work fine elsewhere in the project... 这些引用也可以在项目中的其他地方正常工作...

 #include <stddef.h> 
 #include <stdint.h>  

...which further confuses me why unistd.h won't link... but will compile. ...这进一步使我感到困惑,为什么unistd.h不会链接...但是会编译。

Including unistd.h just tells the compiler about the things (functions, etc.) defined in a library. 包括unistd.h只是告诉编译器有关库中定义的内容(函数等)的信息。 It describes the interface to the library but not the implementation of the libraries functionality. 它描述了库的接口,但没有描述库功能的实现。

That's why your program compiles. 这就是您的程序编译的原因。 unistd.h has a declaration of sleep() in it. unistd.h中有一个sleep()声明。 It probably looks something like this: 它可能看起来像这样:

unsigned sleep(unsigned);

You can look at it, it's a text file. 您可以看一下,它是一个文本文件。

The problem is that when you try to link, nothing defines sleep(). 问题是,当您尝试链接时,没有任何东西定义sleep()。 Normally sleep() and other standard functions exist in a precompiled library. 通常,sleep()和其他标准函数存在于预编译的库中。 Something with a name like libc.a The .a file is an archive containing object files that implement the library's functionality which the linker can link with your object files to resolve references to things like sleep(). 名称类似libc.a的文件.a文件是一个包含目标文件的归档文件,这些文件实现了库的功能,链接程序可以将这些文件与您的目标文件链接,以解析对sleep()之类的引用。

The reason that stddef.h stdint.h work is that they primarily define types and macros that are used at compile time but don't need any additional object code to be lined in at link time. stddef.h stdint.h之所以起作用,是因为它们主要定义了在编译时使用的类型和宏,但不需要在链接时插入任何其他目标代码。

Your link line doesn't include any libraries. 您的链接行不包含任何库。 I suspect that's because you don't have any for your bare-metal environment. 我怀疑那是因为您没有任何裸机环境。

You have a couple of options. 您有两种选择。 You could try to port a preexisting library to work in your environment, or you can write your own sleep() function. 您可以尝试移植一个预先存在的库以在您的环境中工作,或者可以编写自己的sleep()函数。

You can take a look at ELLCC which is one (of several) cross development tool chains that provide libraries. 您可以看一下ELLCC ,它是提供库的(几个)跨开发工具链之一。 ELLCC's bare-metal libraries are a work in progress, but looking at the ELK blog posts might give you some ideas. ELLCC的裸机库尚在开发中,但是查看ELK博客文章可能会给您一些想法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM