我是练习 PintOS 项目的学生。 在编程项目3(虚拟内存)中,我遇到了关于“编译中的预处理”(C程序)的问题。 我已经尝试了所有尽我所能的尝试,但此时我完全不知道如何解决它。 终于来到这里,不得不问你这个问题了。
错误
我完成了堆栈增长部分,所以我正在修改
syscall.c
来实现mmap
,但是在buid过程中遇到了问题。 spt
字段被识别为不完整类型并且未被排除。
现状
所讨论的线程结构在
thread.h
中声明,并且supplemental_page_table
结构中的元素spt的类型thread
在vm.h
中声明。当前thread.h中的线程结构体上方
#ifdef VM #include "vm/vm.h"
正在预处理vm.h格式。我目前正在通过 SSH 连接到 VS code 使用 EC2 服务器(ubuntu 18.04),并尝试了诸如 make clean、make、插入和更改 #include 预处理和前向声明代码的顺序以及重新启动 + 重新安装 EC2 等解决方案,但是没有任何进展。
问题
vm.h
中声明了spt
结构体的thread.h
,包含在线程结构体之前,是不是应该可以正常使用了?...
#ifdef VM // I'm in project3(VM)
#include "vm/vm.h"
...
struct thread {
...
#ifdef VM
/* Table for whole virtual memory owned by thread. */
struct supplemental_page_table spt; // The spt structure is defined in vm.h.
...
/* Print in terminal */
In file included from ../../include/userprog/process.h:4:0,
from ../../include/vm/vm.h:7,
from ../../vm/vm.c:4:
../../include/threads/thread.h:151:33: error: field ‘spt’ has incomplete type
struct supplemental_page_table spt;
^~~
In file included from ../../vm/vm.c:4:0:
../../include/vm/vm.h:200:1: warning: "/*" within comment [-Wcomment]
/* 현재 프로세스의 메모리 공간을 나타내는 구조체입니다.
../../vm/vm.c: In function ‘vm_init’:
../../vm/vm.c:21:23: warning: unused variable ‘start’ [-Wunused-variable]
struct list_elem *start = list_begin(&frame_table);
^~~~~
../../vm/vm.c: In function ‘vm_alloc_page_with_initializer’:
../../vm/vm.c:84:1: warning: label ‘err’ defined but not used [-Wunused-label]
err:
^~~
../../vm/vm.c: In function ‘spt_insert_page’:
../../vm/vm.c:105:6: warning: unused variable ‘succ’ [-Wunused-variable]
int succ = false;
^~~~
../../vm/vm.c: In function ‘spt_remove_page’:
../../vm/vm.c:111:55: warning: unused parameter ‘spt’ [-Wunused-parameter]
void spt_remove_page (struct supplemental_page_table *spt, struct page *page) {
^~~
...
tid_t
中有一个名为 process.h
的自定义,它也在 thread.h
中定义,并且我已包含它,但它没有引用它。我通过在 process.h 中再次定义它来解决这个问题,它是重复的,但我想我会问与上面相同的问题上下文。作为参考,我之后遇到了上述问题。/* Code in process.h */
#ifndef USERPROG_PROCESS_H
#define USERPROG_PROCESS_H
#include "threads/thread.h"
bool install_page (void *upage, void *kpage, bool writable);
// typedef int tid_t; // If i remove annotation in this line, going to problem mentioned above
tid_t process_create_initd (const char *file_name);
tid_t process_fork (const char *name, struct intr_frame *if_);
int process_exec (void *f_name);
int process_wait (tid_t);
void process_exit (void);
void process_activate (struct thread *next);
#endif /* userprog/process.h */
/* Print */
In file included from ../../include/vm/vm.h:7:0,
from ../../include/threads/thread.h:12,
from ../../threads/init.c:24:
../../include/userprog/process.h:9:1: error: unknown type name ‘tid_t’; did you mean ‘size_t’?
tid_t process_create_initd (const char *file_name);
^~~~~
size_t
/* here is modified code i did, but i think it is not problem */
void *mmap (void *addr, size_t length, int writable, int fd, off_t offset) {
if (offset % PGSIZE != 0) {
return NULL;
}
if (pg_round_down(addr) != addr || is_kernel_vaddr(addr) || addr == NULL || (long long)length <= 0)
return NULL;
if (fd == 0 || fd == 1) {
exit(-1);
}
if (spt_find_page(&thread_current()->spt, addr))
return NULL;
struct file *target = find_file_by_fd(fd);
if (target == NULL)
return NULL;
void * ret = do_mmap(addr, length, writable, target, offset);
return ret;
}
void munmap (void *addr) {
do_munmap(addr);
}
/* Do the mmap */
void *do_mmap (void *addr, size_t length, int writable, struct file *file, off_t offset) {
struct file *mfile = file_reopen(file);
void * ori_addr = addr;
size_t read_bytes = length > file_length(file) ? file_length(file) : length;
size_t zero_bytes = PGSIZE - read_bytes % PGSIZE;
while (read_bytes > 0 || zero_bytes > 0) {
size_t page_read_bytes = read_bytes < PGSIZE ? read_bytes : PGSIZE;
size_t page_zero_bytes = PGSIZE - page_read_bytes;
struct supplemental_page_table *spt = (struct supplemental_page_table*)malloc
(sizeof(struct supplemental_page_table));
spt->file = mfile;
spt->offset = offset;
spt->read_bytes = page_read_bytes;
if (!vm_alloc_page_with_initializer (VM_FILE, addr, writable, lazy_load_segment, spt)) {
return NULL;
}
read_bytes -= page_read_bytes;
zero_bytes -= page_zero_bytes;
addr += PGSIZE;
offset += page_read_bytes;
}
return ori_addr;
}
/* Do the munmap */
void do_munmap (void *addr) {
while (true) {
struct page* page = spt_find_page(&thread_current()->spt, addr);
if (page == NULL)
break;
struct supplemental_page_table * aux = (struct supplemental_page_table *) page->uninit.aux;
// dirty(사용되었던) bit 체크
if(pml4_is_dirty(thread_current()->pml4, page->va)) {
file_write_at(aux->file, addr, aux->read_bytes, aux->offset);
pml4_set_dirty (thread_current()->pml4, page->va, 0);
}
pml4_clear_page(thread_current()->pml4, page->va);
addr += PGSIZE;
}
}
这是我的团队 git 存储库 目前,我们已将这个 git 保存为完整(无错误)的状态,但我们将创建一个具有相同错误的状态并尽快推送它。
Thank you very much for your time!
解决了!
最大的问题是我不知道问题是什么。 在询问了周围的人后,我了解到这个问题被称为“circularreference”和“duplicate header”问题。简而言之,这些是当对象相互引用或使用重复的标头编译标头时出现的问题。互联网上有很多材料,因此请将此作为里程碑。
这可以通过在标头中插入一次 #pragma 或 #ifndef HEADER_H #define HEADER_H #endif 语法来解决。 就我而言,我可以通过将 后一种情况,#ifndef ...和 #ifdef适当插入标题来解决它。 我把答案留给自己,以供将来遇到同样问题的其他人使用。
祝大家好运!