[英]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.