/cicv-r4l-ziqing-x

cicv-r4l-ziqing-x created by GitHub Classroom

Primary LanguageC

Logo

熊义

第二阶段 rust for linux 作业报告

索引


作业1-编译Linux内核

  • 生成适用于x86_64架构的默认配置
cd linux
make x86_64_defconfig

图1-1

  • 配置内核对Rust语言的支持
make LLVM=1 menuconfig
General setup
        ---> [*] Rust support

图1-2

  • 编译内核
make LLVM=1 -j$(nproc)
ls vmlinux

图1-3


作业2-对Linux内核进行一些配置

  • 编译e1000网卡驱动
make LLVM=1

图2-1

  • 使用qemu运行作业一中编译的内核
cd src_e1000
chmod +x ./build_image.sh
./build_image.sh
ifconfig # 发现作业一的e1000网卡驱动被启用了

图2-2

  • 禁用Linux内核默认的C版本的e1000网卡驱动
make LLVM=1 menuconfig

Device Drivers 
    ---> Network device support
        ---> Ethernet driver support
            ---> Intel devices, Intel(R) PRO/1000 Gigabit Ethernet support

图2-3

  • 编译内核
make LLVM=1 -j$(nproc)
ls vmlinux

图2-4

  • 使用qemu运行刚编译的内核
./build_image.sh
ifcofig # 发现c语言写的驱动已经被禁用

图2-5

  • 加载使用rust写的e1000网卡驱动
insmod r4l_e1000_demo.ko

图2-7

  • 启用eth0网卡
ip link set eth0 up

图2-8

  • 将广播IP地址(10.0.2.255)添加到eth0网络接口上
ip addr add broadcast 10.0.2.255 dev eth0

图2-9

  • 将IP地址 10.0.2.15 与子网掩码 255.255.255.0 分配给 eth0 网络接口
ip addr add 10.0.2.15/255.255.255.0 dev eth0

图2-10

  • 将默认路由设置为通过IP地址为10.0.2.1的网关进行转发
ip route add default via 10.0.2.1

图2-11

  • 查看网口信息
ifconfig

图2-12

  • 测试网络是否正常
ping 10.0.2.2

图2-13

  • 问题1、编译成内核模块,是在哪个文件中以哪条语句定义的?
答:Kbuild文件里的obj-m := r4l_e1000_demo.o
  • 问题2、该模块位于独立的文件夹内,却能编译成Linux内核模块,这叫做out-of-tree module,请分析它是如何与内核代码产生联系的?
答:Makefile里通过make的-C选项把当前工作目录转移到了linux目录下,内核的构建系统通过M=$$PWD 来定位独立模块的源代码,从而实现驱动的编译

作业3-使用rust编写一个简单的内核模块并运行

  • 进入到Linux目录下samples/rust文件夹
  • 添加一个rust_helloworld.rs文件
  • 在该文件中添加如下内容
// SPDX-License-Identifier: GPL-2.0
//! Rust minimal sample.
      
use kernel::prelude::*;
      
module! {
  type: RustHelloWorld,
  name: "rust_helloworld",
  author: "whocare",
  description: "hello world module in rust",
  license: "GPL",
}
      
struct RustHelloWorld {}
      
impl kernel::Module for RustHelloWorld {
  fn init(_name: &'static CStr, _module: &'static ThisModule) -> Result<Self> {
      pr_info!("Hello World from Rust module");
      Ok(RustHelloWorld {})
  }
}

图3-1

  • 修改Makefile
# 在倒数第二行追加这行代码
obj-$(CONFIG_SAMPLE_RUST_HELLOWORLD)	+= rust_helloworld.o

图3-2

  • 修改Kconfig
# 在倒数第二行添加下面代码
config SAMPLE_RUST_HELLOWORLD
	tristate "Print hello world module"
	help
	  To compile this as a module, choose M here:

	  If unsure, say N.

图3-3

  • 更改该模块的配置,使之编译成模块
Kernel hacking
  ---> Sample Kernel code
      ---> Rust samples
              ---> <M>Print Helloworld in Rust (NEW)

图3-4

  • 编译内核
time make LLVM=1 -j$(nproc)

图3-5

  • 在qemu环境运行驱动
cp linux/samples/rust/rust_helloworld.ko src_e1000/rootfs
cd src_e1000 && ./build_image.sh
# 系统起来后
insmod rust_helloworld.ko

图3-6


作业4-为e1000网卡驱动添加remove代码

  • 加载驱动
insmod r4l_e1000_demo.ko
  • 配置网络
# 为了方便测试,写到了test_net.sh脚本里了
ip link set eth0 up
ip addr add broadcast 10.0.2.255 dev eth0
ip addr add 10.0.2.15/255.255.255.0 dev eth0
ip route add default via 10.0.2.1
  • 测试网络是否正常 图4-1
  • 重新加载驱动
rmmod r4l_e1000_demo
insmod r4l_e1000_demo.ko
  • 配置网络
# 为了方便测试,写到了test_net.sh脚本里了
ip link set eth0 up
ip addr add broadcast 10.0.2.255 dev eth0
ip addr add 10.0.2.15/255.255.255.0 dev eth0
ip route add default via 10.0.2.1
  • 再次测试网络是否正常 图4-2

作业5-注册字符设备

  • 更改配置
Kernel hacking
  ---> Sample Kernel code
      ---> Rust samples
              ---> <*>Character device (NEW)

图3-6

  • 编译并运行
make LLVM=1 -j$(nproc)
cp samples/rust/rust_chrdev.ko ../src_e1000/rootfs/
cd ../src_e1000/
./build_image.sh

图3-6

  • 加载驱动并验证结果
insmod rust_chrdev.ko
echo "Hello" > /dev/cicv
cat /dev/cicv

图3-6

  • 问题1、作业5中的字符设备/dev/cicv是怎么创建的?
答: 作业5中的字符设备/dev/cicv是在Linux的启动脚本/etc/init.d/rcS.sh里通过mknod /dev/cicv c 248 0命令创建的。
  • 问题2、它的设备号是多少?
答: /dev/cicv的主设备号是248, 次设备号是0。
  • 问题3、它是如何与我们写的字符设备驱动关联上的?
答: 通过设备号248进行关联的。

图3-6


结语

纸上得来终觉浅,绝知此事要躬行 🤘