不落辰

知不可乎骤得,托遗响于悲风

0%

  • void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);

  • 本实验实现了简易的mmap syscall(阉割版). 实现所谓的将”文件映射到内存”

  • 对比

    • 现代OSmmap : disk -> kernel buf. user va映射到kernel bu
    • 实现的xv6mmap : disk -> kernel buf -> user physical mem. user va映射到 physical mem
      • 且没有实现MAP_PRIVATE,MAP_SHARED时的共享mem,也没实现MAP_PRIVATE的cow
  • 实现关键 : lazy allocation

    • mmap 先获取一块vma区域 但并不建立映射, 仅仅设定这块va合法 ; 当发生pgfault的时候,再读取文件相应内容 , 为va建立映射 , 然后返回.
    • munmap 就是解除vma内建立了映射的va
  • mmap优势

    • 效率高,高于普通的read file
      • 比起read少一次拷贝. 映射到kenerl buf
      • 减少陷入内核次数,减少上下文切换开销.(read每次都陷入)
      • lazy allocation(不必一次全部读入)
    • 更加方便user读写文件
      • 这也就是mmap所谓的 “映射文件到用户进程”。
      • user调用mmap之后 , 可以将对内存的读写看成对文件的读写,如何加载数据,如何落入磁盘 等都不需要user管.

prot : 对内存权限 ; flags : 对file权限。 二者不可冲突

阅读全文 »

  • part1 : 协程
    • thread_yield -> thread_schduler
  • cond_broadcast 唤醒后 没拿到lock的thread还需要再次被cond_broadcast吗 ?
    • 不需要
    • 因为cond将一系列等待该cond的thread(BCD thread)串在了一起,当Athread broadcast广播唤醒该cond时,这一系列thread(BCDthread)都不再受阻于该cond约束。
    • 之后谁拿到锁谁往下走就行了,与cond无关
阅读全文 »

  • 线程调度流程 : user thread A -> kernel thread A -> scheduler thread -> kernel thread B -> user thread B

  • xv6和OS的线程调度策略 : pre-emptive scheduling(定时器中断) + voluntary scheduling(kernel thread主动swtch)

  • xv6的3个thread

    • user process的user thread (上下文在trapframe)
    • user process的kernel thread (上下文在trapframe和context)
    • 每个cpu核 的 scheduler thread (上下文在cpu.context)
  • thread切换核心 : swtch

    • 用于实现 kernel thread 和 scheduler thread的切换
    • 切换return addr , kernel stack pointer , callee saved regs
阅读全文 »

  • 本实验之前 fork之后 child process 立刻 拷贝 parent的physical mem 并建立映射.

  • 本实验之后 :不必拷贝. copy on write.

    • 思想:推迟为child分配和复制物理内存页,直到实际需要副本。
    • 实现
        1. fork , 进行假分配
        1. copy on write , 进行真分配
        • 根据physical page的ref cnt(是否为1)来判断是否需要cow
        • cow分为三部分
          • 复制物理内存
          • 取消pte的cow标志位
          • proc的pgtbl上建立映射
        1. cow之后 返回到造成pgfault的指令继续执行.
  • 哪个process copy on write ?

    • 哪个process先写,就哪个porcess的pgtbl进行copy on write.
  • 当parent process A fork 出 BCDE process 后

      1. A写. 触发pgfault
      • 则A进行cow. 且A只会影响自己的pgtbl. 不会改变BCDE的pgtbl
      1. BCD写. 触发pgfault
      • 则BCD进行cow. 同1
      1. E写.
      • 尽管此时只有E一个proc引用该mem,但仍然会pagefault. 因为E的pgtbl上的pte并没有任何改变. 仍然有cow的标志位
      • 故E也进入pgfault handler.(walkaddrforwrite)
      • E发现physical page的ref cnt = 1 , 故不再需要复制物理内存,重新建立映射. 直接去掉cow标志位即可返回.
阅读全文 »

  • Interrupt中断概述
    • 驱动(管理设备的代码)架构:Handler + Bottom
    • interrupt Handler : 即 Bottom
    • 例子 : kernel读取用户字符传给shell,并显示在终端上
      • PLIC路由中断;UART传输字符
    • Interrupt的并发性
      • 发出Interrupt的设备与cpu并行
      • 中断会停止当前进程(user -> uservec / kernel -> kernelvec)
      • 驱动的top和bottom是并行的.(一个cpu上跑top , 一个cpu上跑bottom)

本篇有待复习、总结

阅读全文 »

易知x86-64都实现了lazy allocation
例如malloc一块很大的内存,直到对这个内存进行写/读之前,都不会

为xv6实现懒分配lazy allocation

  • lazy allocation
    • 目的 : 为防止sbrk大量内存但实际上并没有使用的情况
    • 实现 : 通过 虚拟内存 和 page fault handler
      • 阶段1. 设定va为合法
        • sbrk系统调用 : 仅仅设定user的这段va是合法的,而不分配内存建立映射。
      • 阶段2. 使用va触发pagefault, 进行响应(handle)
        • pagefault handelr : 为va 分配一块physical page 并 建立映射
        • 阶段2中对于va
          • user使用无效 userva
            • MMU –检测–> trap –> pagefault handler
          • kernel使用无效 userva
            • argaddr 中检测 –> pagefault handelr
        1. pgfault handelr之后 返回到造成pgfault的指令继续执行.
阅读全文 »