构造一个简单的LINUX系统MENUOS
实验第一节
- 登录实验楼网站,进入linux虚拟机
- 打开Xfce终端(Terminal)clone linuxnet.git 并参照如下指令编译执行代码:
# 进入 Code 文件夹,并将仓库 clone 到这里 $ cd ~/Code $ git clone https://github.com/mengning/linuxnet.git $ cd ./linuxnet/lab1/ $ ls # 执行 ls 后可以看到有以下三个文件: # client.c server.c syswrapper.h # 编译代码 $ gcc server.c -o server $ gcc client.c -o client
- 执行server
shiyanlou:lab1/ (master*) $ ./server # 当我们执行一次 client 之后会显示如下的内容:(需要再打开一个Xfce终端,右键选择水平分割) recv "hello" from 127.0.0.1:58911 rely "hi" to 127.0.0.1:58911
实验第二节 跟踪分析 Linux 内核的启动过程
- 在上一节实验环境中继续。执行以下代码
$ cd ~/LinuxKernel/ $ qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img
内核启动完成后进入 menu 程序
$ qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S
关于 -s 和 -S 选项的说明:
-S freeze CPU at startup (use ’c’ to start execution)
-s shorthand for -gdb tcp::1234 若不想使用 1234 端口,则可以使用 -gdb tcp:xxxx 来取代 -s 选项 关于 -s 和 -S 选项的说明:
若不想使用 1234 端口,则可以使用 -gdb tcp:xxxx 来取代 -s 选项
# 打开 GDB 调试器 $ gdb # 在 GDB 中输入以下命令: # 在 gdb 界面中 targe remote 之前加载符号表 (gdb)file linux-3.18.6/vmlinux # 建立 gdb 和 gdbserver 之间的连接 (gdb)target remote:1234 # 断点的设置可以在target remote之前,也可以在之后 (gdb)break start_kernel # 按 c 让qemu上的Linux继续运行 (gdb)c
注意:按 Ctrl+Alt 从 QEMU 窗口里的 MenuOS 系统返回到当前系统,否则会误以为卡死在那
将网络通信程序的服务端集成到 MenuOS 系统中
接下来我们需要将 C/S 方式的网络通信程序的服务端集成到 MenuOS 系统中,成为 MenuOS 系统的命令 replyhi。
实际上我们已经给大家集成好了,我们 git clone 克隆一个 linuxnet.git,进入 lab2 目录执行 make 可以将我们集成好的代码 copy 到 menu 项目中。
然后进入 menu,我们写了一个脚本 rootfs,运行 make rootfs,脚本就可以帮助我们自动编译、自动生成根文件系统,还会帮我们运行起来 MenuOS 系统。
详细命令如下:
$ cd ~/LinuxKernel $ git clone https://github.com/mengning/linuxnet.git $ cd linuxnet/lab2 $ make $ cd ../../menu/ $ make rootfs
其中我们增加了命令 replyhi,功能是回复 hi 的 TCP 服务.
接下来您就可以参照前面“跟踪分析 Linux 内核的启动过程的具体操作方法”进行跟踪调试了,只是我们 socket 接口使用的是系统 sys_socketcall,可以将 sys_socketcall 设为断点跟踪看看。
第三节 初始化 MenuOS 系统的网络功能,跟踪分析 TCP 协议
之前我们已经将 TCP 网络程序的服务端 replyhi 集成到 MenuOS 中了,而且可以正常的启动 TCP 服务,方便我们跟踪 socket、bind、listen、accept 几个 API 接口到内核处理函数,但是我们启动的 TCP 服务并不能正常对外提供服务,因为 MenuOS 没有初始化网络设备(包括本地回环 loopback 设备),因此它无法接收到任何网络请求。
接下来我们需要搞清楚如何激活 Linux 网络设备,并将 MenuOS 系统的网络设备用简便的方式配置好,使我们将 TCP 客户端也集成进去后可以完整的运行 TCP 网络程序的服务端和客户端程序。
如何激活 Linux 网络设备接口
Linux 发行版一般在启动过程中自动激活网络设备接口的方式
具体内容可以参考配套的专栏文章或视频课程
在 MenuOS 中手工编码激活网络设备接口 lo
具体内容可以参考配套的专栏文章或视频课程
将 TCP 网络通信程序的客户端也集成到 MenuOS 系统中
接下来我们需要将 C/S 方式的网络通信程序的客户端也集成到 MenuOS 系统中,成为 MenuOS 系统的命令 hello,实际上我们已经给大家集成好了,我们 git clone 克隆一个 linuxnet.git;进入 lab3 目录执行 make rootfs,脚本就可以帮助我们自动编译、自动生成根文件系统,还会帮我们运行起来 MenuOS 系统。详细命令如下:
$ cd ~/LinuxKernel $ git clone https://github.com/mengning/linuxnet.git $ cd linuxnet/lab3 $ make rootfs
运行起来的 MenuOS 中执行 help 命令可以看到其中不止有 replyhi,也有了 hello 命令,我们可以先执行 replyhi,然后执行 hello。
跟踪分析 TCP 协议
$ cd ~/LinuxKernel/linuxnet/lab3 $ qemu -kernel ../../linux-3.18.6/arch/x86/boot/bzImage -initrd ../rootfs.img -s -S
右击水平分割或者另外打开一个 Xfce 终端(Terminal),执行gdb
shiyanlou:LinuxKernel/linuxnet/lab3 $ gdb # 在gdb界面中targe remote之前加载符号表 (gdb)file ../../linux-3.18.6/vmlinux # 建立gdb和gdbserver之间的连接 (gdb)target remote:1234 # 断点的设置可以在target remote之前,也可以在之后 (gdb)break start_kernel # 按c 让qemu上的Linux继续运行 (gdb)c
TCP 的三次握手源代码跟踪分析,跟踪找出设置和发送 SYN/ACK 的位置,以及状态转换的位置
TCP 的三次握手从用户程序的角度看就是客户端 connect 和服务端 accept 建立起连接时背后完成的工作,在内核 socket 接口层这两个 socket API 函数对应着 sys_connect 和 sys_accept 函数,进一步对应着 sock->opt->connect 和 sock->opt->accept 两个函数指针,在 TCP 协议中这两个函数指针对应着 tcp_v4_connect 函数和 inet_csk_accept 函数。