0

在使用 make 编译操作系统时,我从 make 中得到了一个我不理解的奇怪错误。

从制作:

source/paging.c:179:6: error: conflicting types for ‘page_fault’
headers/paging.h:68:6: note: previous declaration of ‘page_fault’ was here
make: *** [obj/paging.o] Error 1

有问题的功能是以下功能。我没有包含 paging.c 的整个文件,因为它非常大,paging.h tbh 也是如此,但是如果您想查看头文件,我将发布其余部分。

分页.c:

....
....
void page_fault(registers_t regs)
{
// A page fault has occurred.
// The faulting address is stored in the CR2 register.
u32int faulting_address;
asm volatile("mov %%cr2, %0" : "=r" (faulting_address));

// The error code gives us details of what happened.
int present   = !(regs.err_code & 0x1); // Page not present
int rw = regs.err_code & 0x2;           // Write operation?
int us = regs.err_code & 0x4;           // Processor was in user-mode?
int reserved = regs.err_code & 0x8;     // Overwritten CPU-reserved bits of page entry?
int id = regs.err_code & 0x10;          // Caused by an instruction fetch?

// Output an error message.
monitor_write("Page fault! ( ");
if (present) {monitor_write("present ");}
if (rw) {monitor_write("read-only ");}
if (us) {monitor_write("user-mode ");}
if (reserved) {monitor_write("reserved ");}
monitor_write(") at 0x");
monitor_write_hex(faulting_address);
monitor_write("\n");
PANIC("Page fault");
}

分页.h:

....
....
void page_fault(registers_t *regs);
....
....

注意:这是来自教程(所以它应该可以工作,但是在一个函数拼写不正确之前,我遇到了提供的源代码的问题)。

知道为什么make会抱怨吗?

谢谢。

在没有 * 的情况下出错:

obj/interrupt.o: In function `isr_common_stub':
asem/interrupt.s:(.text+0x1c9): undefined reference to `isr_handler'
obj/interrupt.o: In function `irq_common_stub':
asem/interrupt.s:(.text+0x1ee): undefined reference to `irq_handler'
obj/main.o: In function `main':
main.c:(.text+0x6e): undefined reference to `placement_address'
obj/descriptor_tables.o: In function `init_descriptor_tables':
descriptor_tables.c:(.text+0x23): undefined reference to `interrupt_handlers'
obj/timer.o: In function `init_timer':
timer.c:(.text+0x30): undefined reference to `register_interrupt_handler'
obj/paging.o: In function `initialise_paging':
paging.c:(.text+0x298): undefined reference to `kmalloc'
paging.c:(.text+0x2cc): undefined reference to `kmalloc_a'
paging.c:(.text+0x328): undefined reference to `placement_address'
paging.c:(.text+0x341): undefined reference to `register_interrupt_handler'
obj/paging.o: In function `get_page':
paging.c:(.text+0x3da): undefined reference to `kmalloc_ap'
obj/initrd.o: In function `initialise_initrd':
initrd.c:(.text+0x1f1): undefined reference to `kmalloc'
initrd.c:(.text+0x2f5): undefined reference to `kmalloc'
initrd.c:(.text+0x402): undefined reference to `kmalloc'
obj/task.o: In function `initialise_tasking':
task.c:(.text+0x24): undefined reference to `kmalloc'
task.c:(.text+0x9a): undefined reference to `kmalloc_a'
obj/task.o: In function `fork':
task.c:(.text+0x2b3): undefined reference to `clone_directory'
task.c:(.text+0x2c2): undefined reference to `kmalloc'
task.c:(.text+0x314): undefined reference to `kmalloc_a'
obj/syscall.o: In function `initialise_syscalls':
syscall.c:(.text+0x8b): undefined reference to `register_interrupt_handler'
make: *** [kern/kernel] Error 1

中断.s:

....
; In isr.c
extern irq_handler
....
....
; In isr.c
extern isr_handler

main.c: .... extern u32intplacement_address; ……

描述符表.c:

void init_descriptor_tables()
{

// Initialise the global descriptor table.
init_gdt();
// Initialise the interrupt descriptor table.
init_idt();
// Nullify all the interrupt handlers.
memset(&interrupt_handlers, 0, sizeof(isr_t)*256);
}

计时器.c:

void init_timer(u32int frequency)
{
// Firstly, register our timer callback.
register_interrupt_handler(IRQ0, &timer_callback);

// The value we send to the PIT is the value to divide it's input clock
// (1193180 Hz) by, to get our required frequency. Important to note is
// that the divisor must be small enough to fit into 16-bits.
u32int divisor = 1193180 / frequency;

// Send the command byte.
outb(0x43, 0x36);

// Divisor has to be sent byte-wise, so split here into upper/lower bytes.
u8int l = (u8int)(divisor & 0xFF);
u8int h = (u8int)( (divisor>>8) & 0xFF );

// Send the frequency divisor.
outb(0x40, l);
outb(0x40, h);
}

分页.c:

....
void initialise_paging()
{
// The size of physical memory. For the moment we 
// assume it is 16MB big.
u32int mem_end_page = 0x1000000;

nframes = mem_end_page / 0x1000;
frames = (u32int*)kmalloc(INDEX_FROM_BIT(nframes));
memset(frames, 0, INDEX_FROM_BIT(nframes));

// Let's make a page directory.
kernel_directory = (page_directory_t*)kmalloc_a(sizeof(page_directory_t));
current_directory = kernel_directory;

// We need to identity map (phys addr = virt addr) from
// 0x0 to the end of used memory, so we can access this
// transparently, as if paging wasn't enabled.
// NOTE that we use a while loop here deliberately.
// inside the loop body we actually change placement_address
// by calling kmalloc(). A while loop causes this to be
// computed on-the-fly rather than once at the start.
int i = 0;
while (i < placement_address)
{
    // Kernel code is readable but not writeable from userspace.
    alloc_frame( get_page(i, 1, kernel_directory), 0, 0);
    i += 0x1000;
}
// Before we enable paging, we must register our page fault handler.
register_interrupt_handler(14, page_fault);

// Now, enable paging!
switch_page_directory(kernel_directory);
}
4

2 回答 2

4

对于同名的函数,您有两个不同的签名。请注意,第一个声明采用 a registers_t,但第二个声明采用 a registers_t*

/* paging.h */
void page_fault(registers_t *regs);

/* paging.c */
void page_fault(registers_t regs)

根据变量的用法,函数签名paging.c是正确的regs,因此更改.h文件中的声明以匹配。

它真的很臭,但我之前在分布式源代码中遇到过这样的问题(尤其是在学校......)。不确定甚至无法编译的代码如何像这样进入野外,但它确实发生了。

于 2012-04-17T22:24:35.350 回答
2

函数签名不匹配:

文件中的声明.h

void page_fault(registers_t *regs)

文件中的定义.c

void page_fault(registers_t regs)

更正头文件中的签名以匹配文件中的签名.c(即删除*from paging.h)。

于 2012-04-17T22:26:14.257 回答