[{"content":"TL;DR 本文介绍wsl的一些实用配置。\n安装 WSL安装见官方文档\n建议阅读文档中的其余内容来学习维护wsl的知识。\n建议使用Debian或者Ubuntu，微软的支持比较好。\n配置 这里列举出配置供参考。\n.wslconfig 具体选项内容对照文档高级wsl配置一节。\n不建议使用稀疏磁盘（issue中有不少被破坏文件系统的），可以定期使用hyperv的磁盘管理工具释放多余空间（见文档）。\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 # C:/Users/\u0026lt;username\u0026gt;/.wslconfig [wsl2] processors=4 memory=8GB swap=4GB vmIdleTimeout=30000 guiApplications=true nestedVirtualization=true # 嵌套虚拟化 networkingMode=mirrored dnsTunneling=true firewall=true [experimental] autoMemoryReclaim=dropcache # 可以在 gradual 、dropcache 、disabled 之间选择 # sparseVhd=true # maybe cause some error hostAddressLoopback=true # 外部可访问wsl内部服务 wsl.conf 开启systemd支持，command 处设置kvm组权限，以便发行版使用kvm。\n1 2 3 4 5 6 7 # /etc/wsl.conf [boot] systemd=true command=/bin/bash -c \u0026#39;chown -v root:kvm /dev/kvm \u0026amp;\u0026amp; chmod 660 /dev/kvm\u0026#39; [interop] appendWindowsPath=false # need add path on profile /etc/profile 隔离wsl与windows的path后添加部分实用app到PATH中。\n1 2 3 4 5 # windows path export PATH=\u0026#34;$PATH:/mnt/c/Users/schulice/AppData/Local/Microsoft/WindowsApps\u0026#34; export PATH=\u0026#34;$PATH:/mnt/c/Program Files/Docker/Docker/resources/bin\u0026#34; export PATH=\u0026#34;$PATH:/mnt/c/Windows\u0026#34; export PATH=\u0026#34;$PATH:/mnt/c/Program Files/Microsoft VS Code/bin\u0026#34; windows启动时同时启动wsl 放在 C:\\Users\u0026lt;username\u0026gt;\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\n1 2 set ws=wscript.CreateObject(\u0026#34;wscript.shell\u0026#34;) ws.run \u0026#34;wsl -d Debian\u0026#34;, 0 Debian处更改为发行版名称。然后可以在任务管理器-启动中将wsl作为启动项管理。\n维护 wsl启动失败 关闭后再开启wsl，虚拟机平台等windows功能，有概率恢复正常，具体原因不明。\nwsl空间使用过多 RTFM\n其他的虚拟机 可以使用windows自带的hyperv管理作为hypervisor，有一些网络nat的设置需要具体的指令（gui中没有）。\nCUDA toolkit 阅读cuda官方文档。只需要安装toolkit包，已有驱动支持（与wsl的驱动有冲突）。\ndocker 安装docker-desktop，后续使用阅读docker文档。\n","date":"2024-08-17T16:57:55+08:00","permalink":"https://schulice.github.io/p/wsl-configuration/","title":"WSL Configuration"},{"content":"前言 cs144是斯坦福大学的计算机网络入门课程，在2024.4.6-4.15我陆续完成了该Lab的除了书面报告外的内容，在此总结整个过程，同时作分享交流使用。\n该Lab使用现代C++，使用Cmake作为管理工具。主要的内容有：简单的网络工具的使用，在框架代码的基础上实现1. 简化的tcp协议栈（lab0-lab4），2. ARP请求与回应过程（lab5），3. 路由中最长前缀匹配的逻辑（lab6），总体而言难度不大，全程单线程，不大需要前置知识，对C++及数据结构有一定了解即可。\n个人觉得做这个lab最大的收获是看框架代码的组织形式，观察课程导师Keith Winstein是怎样设计各个类的公共接口和行为，怎样方便地组织测试过程。得到了很多设计上的补益。 接下来我会介绍我是怎样实现各个lab的，具体的代码可以查看我fork的仓库，如果有希望自己做的同学朋友还请不要看。这里附上一张lab文档中的介绍图。\n环境配置 如果你使用的是滚动发行版或者最新的ubuntu23.10，默认安装的gcc版本就是13.2了。 如果你使用debian12，希望使用新的gcc，请查看gcc的安装文档，编译安装gcc。相关的资料很多，这里只介绍我遇到的一些小问题：\nvscode调试时，不能使用native debugger插件，我尝试为之设置LD_LIBRARY_PATH的环境变量（通过json配置和.gdbinit文件），始终无法正确加载symbol，故弃用。临时的解决办法是用Microsoft的cpp插件，它在启动时会新建shell，将环境变量设置在.bashrc中即可。 tidy target无法正常构建，默认clang版本太低，升级即可。 LAB0 ByteStream 任务 使用telnet工具发起http请求和其他请求。 在webget.cc中使用TCPSocket发起简单的http请求。注意结束时需要向流中输入额外的空行，http中换行符为/r/n。 实现可靠的字节流。 解决方法 在ByteStream类中添加string作为buffer即可。需要记录push和pop的字节数量。 注意流写入端关闭并且输出完毕后读端才finish。效率一般，测试框架给出的速度是1.5Gbit/s。\n印象 框架代码使用reader和writer类来对ByteStream类进行功能扩展，同时使ByteStream可以得到两类的实例，将读取和写入功能分离。\nLAB1 Reassember 任务 在ByteStream的基础上实现一个流重组器，即将乱序接受到的带索引的字节段转换为有序的字节流。\n解决方法 一开始的想法比较简单，因为它的capability（总的传输字串长度）是有限的，我们只需要维护一个从（已经输出的有序字节流的最后下标+1）开始的字符串，每次接受前重设string大小，根据接受到的段直接覆盖对应的空字符，输出时pop第一个空字符前的子串即可。但是这样存在问题，输入的字串中也会包含空字符。最后弃用。\n更加有效率的方法是使用map存储多个段并进行合并，判断map非空和首个段下标即可。 合并视图过程如下：\n1 2 ---- ---- ---- // 已有段，标号1，2，3 ~~~~~~~~~~~~ // 将插入的段 前向合并后后向合并即可。需要注意的是如下情况需要排除：\n1 2 ------------- ~~~~~~ 还有很多边界上的检查，以及需要根据它传入的标志来初始化结束下标，关闭时机就是output_index == end_index。\n印象 各项测试用例相当细节，会有在写算法题的错觉。最后测试的速度为15GBit/s，还不错。\nLAB2 TCPReceiver 任务 实现一个循环32位正整数，将64位正整数封装，可以根据零点和检查点输出。 实现一个简化后的TCPReceiver，利用Warp32来封装随机选取的开始点。 解决方案 Warp32包装时取模，去包装时根据checkpoint得到UINT32MAX的系数，左右移动下就可以得到最靠近的数值（极值点只有一个）。不需要枚举和二分来找这个系数（是的我犯蠢了）。 receiver的要注意的细节是，ackno和流中字节段下标有SYN和FIN两个东西，需要加加减减。选好zeropoint即可（我使用SYN前为零点）。 印象 一开始对Warp的理解有些问题，废了不少无谓的力气。将这个随机的起始下标封装起来，上层使用起来确实方便不少。\nLAB3 TCPSender 任务 实现TCPSender，可以与receive完成发送和接受字节流的任务。 它需要暂时存放已发送但未确认的message。\n解决方案 封装了timer来进行tick函数的计时，记录RTO重传超时时间，double RTO，reset。 记录已发送和已确认的abs seqno（见上表）。 在push过程， 假装windows size（receiver可以接受的段的长度）始终大于1。这样在windows size等于零时不断询问receiver，同时也包括了初始化时的逻辑。 建立空的msg（seqno为已发送下一位），判断是否需要SYN标志。 根据msg，windows size，input流中缓存的字串长度，msg buffer中字串长度和最大负载长度来得到负载字符串的长度。 根据输入流是否finish（payload拿走字串后），是否有足够的windows size，sender是否已经关闭（不能重复生成关闭信息）来判断是否设置FIN。 计算msg length，拒绝空msg。 发送并加入msg buffer（更新已发送seqno）。 更新唤醒计时器和重传次数。 在receive过程， 更新windows size和RST 根据ackno是否包含值来判断是否需要重新初始化。 根据ackno更新已确认seqno，并且逐出buffer中的无用msg 如果缓存长度为零则关闭计时器，否则重启计时器（当次传输未完成） 在tick过程，计时器更新时间，特化发送空msg的情况，不断重发buffer首包。 初始化中，sender发送SYN-\u0026gt;接受ackno-\u0026gt;正常发送。 关闭过程，sender发送FIN-\u0026gt;接受未包含FIN的ackno-\u0026gt;超时继续发送FIN-\u0026gt;接受包含FIN的ackno-\u0026gt;停止。 印象 比较长并且复杂，修改了好几遍逻辑。同实际上的tcp挥手相比，没有第四次和超时关闭。 需要注意的是，在lab5merge进来时添加了额外的测试用例，比如接受时是否过滤掉不在msgbuffer下标集合中的ackno，可能需要修改receive过程的细节。\nLAB4 Test CS144Socket 任务 更改TCPSocket为框架代码的CS144Socket，测试是否可是使用。\n解决方案 一遍跑通了。\n印象 框架代码的比较复杂，我片面概括下，有所缺漏，还望不吝赐教。 对于Socket，从FD到Socket到LocalStreamSocket到需要满足读写需求的类型的TCPMinnowSocket模版，用于将TCPPeer封装起来符合unix-like的sockets-api。 TCPOverIPv4OverTunFdAdapter作为其特化为CS144Socket的类型，主要是绑定到tun设备，实现ipv4数据包到tcp段的转换。 对于TCPPeer，封装了我们的sender和receiver，管理tcp connect过程，实现这个在之前也实验的一部分，不过这次没有。\nLAB5 ARP and IPv4 Datagram 任务 将ipv4 datagram转换为ethernet frame发送，实现ARP请求与回应。\n解决方案 发送ipv4 datagram时将其序列化在ethernet frame中，查找是否有ip到mac地址的映射，根据ipv4地址来向实际上的ethernet address发送frame。查找不到时就需要ARP了。 ARP过程有两个超时要pop的地方，一是发送的arp请求不能在5s内再发送，二是ip到mac的映射只维护30s。 所以我维护了两张LRU链表，得益于自由的C++，可以将iterator脱离生命周期垂悬（unsafe了），用以list::iterator为值的hashmap和含有hashmap::iterator的结构体作为list成员即可以实现，当然需要小心不要访问错误的内存位置。时间更新时沿着链表删除即可。\n印象 C++的反向迭代器删除元素时要注意位置，建议找下最佳实现。\nLAB6 Prefix Match 任务 实现路由过程中最长前缀匹配目标ip的转发。\n解决方案 虽然任务书中指明O(n)的匹配时间复杂度时可以接受的，但是我们可以将pair\u0026lt;ip_prefix, prefix_length\u0026gt;作为key与rule做映射，使用hashmap需要额外定义一个hasher，可以抄下boost的hash连接函数hash_second + 0x9e3779b9 + ( hash_first \u0026laquo; 6 ) + ( hash_first \u0026raquo; 2 )。 找最长前缀匹配时右移32下即可（ip转为uint32_t)，注意对0.0.0.0/0的特殊匹配。 这样时间复杂度就近似O(1)了。 注意下ipv4header的校验和。\n印象 这个实验不需要算路由规则，很快就写完了。\nLAB7 Real World 任务 使用框架代码中的应用，测试自己的实现是否可以参与真实的网络连接。\n起一个服务端和用户端，测试是否连接成功。 传输1mb的文件流，测试发送的和接受的文件sha256是否相等。 解决方案 直接上即可。\n印象 发送1mb的文件大概需要1min，一开始可以很快到300kb左右，然后发送速度会下降，因为我们的tick激活时只发送buffer中第一个包，一开始的发送结束后会是一个一个包的发，加上课程的服务器连接延迟较高，不要着急。 有写完的同学朋友也可以一起跨主机测试下。\n结语 我fork的仓库在https://github.com/schulice/CS144-Lab。\n","date":"2024-04-16T05:41:59Z","permalink":"https://schulice.github.io/p/cs144-lab%E6%80%BB%E7%BB%93/","title":"CS144-Lab总结"}]