Lec18-23: 学习笔记
- lec18 阅读论文《The Performance of µ-Kernel-Based Systems》
- lec19 阅读论文《Dune: Safe User-level Access to Privileged CPU Features》
- lec20 阅读论文《The benefits and costs of writing a POSIX kernel in a high-level language》
- lec21 阅读论文 Eliminating Receive Livelock in an Interrupt-driven Kernel
- lec22 阅读论文《Meltdown: Reading Kernel Memory from User Space》
- lec23 阅读论文《RCU Usage In the Linux Kernel: One Decade Later》
实验链接
https://pdos.csail.mit.edu/6.S081/2020/labs/net.html
实验
Lab: networking
实验的目的是为了让我们实现一个网卡驱动在数据链路层的数据收发函数,该函数的实现需要参考E1000的用户手册来完成。
不过,实验中作者给出的hint非常详细,按照hint一步一步实现即可(感觉不看用户手册和xv6代码,感兴趣的可以多看看哈)。
函数e1000_recv
需要注意的地方:
- 不需要加锁,因为该函数会一次性读取
rx_ring
上所有的数据,且该函数位于数据链路层,数据链路层还不涉及进程的概念。在读取完数据之后,该函数会调用net_rx
函数,将数据送给上层应用。 - 关于
index
的理解,在recv
函数中,寄存器里保存的index
是上次已经被处理过的位置,因此,拿到寄存器里的值后,需要加一移动至下个位置。且本次的数据被送至上层应用之后,会对其mbuf进行清理并申请新的mbuf用于保存下次接收的数据。
函数e1000_transmit
需要注意的地方:
- 该相关寄存器中保存的
index
值为本次需要处理的数据索引,因此,本次处理完之后,需要对该值加一并重新放入寄存器。
具体实现如下:
-
文件
e1000.c
,函数e1000_transmit
int e1000_transmit(struct mbuf *m) { // // Your code here. // // the mbuf contains an ethernet frame; program it into // the TX descriptor ring so that the e1000 sends it. Stash // a pointer so that it can be freed after sending. // // printf("e1000 transmit\n"); acquire(&e1000_lock); // First ask the E1000 for the TX ring index at which it's expecting // the next packet, by reading the E1000_TDT control register.