关于 PintOS 编译(C 编程)中的“预处理”,有 2 个引用头文件和不完整类型错误的问题

问题描述 投票:0回答:1

我是练习 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 等解决方案,但是没有任何进展。

问题

  1. 如果
    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) {
                                                       ^~~

...
  1. 此外,我在
    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!

c compiler-errors c-preprocessor virtual-memory pintos
1个回答
0
投票

解决了!

最大的问题是我不知道问题是什么。 在询问了周围的人后,我了解到这个问题被称为“circularreference”和“duplicate header”问题。简而言之,这些是当对象相互引用或使用重复的标头编译标头时出现的问题。互联网上有很多材料,因此请将此作为里程碑。

这可以通过在标头中插入一次 #pragma#ifndef HEADER_H #define HEADER_H #endif 语法来解决。 就我而言,我可以通过将 后一种情况,#ifndef ...和 #ifdef适当插入标题来解决它。 我把答案留给自己,以供将来遇到同样问题的其他人使用。

祝大家好运!

© www.soinside.com 2019 - 2024. All rights reserved.