LDD3边读边学(第三章)字符设备驱动 scull 实验全过程

一、实验背景

        在 Linux 系统中,设备驱动是连接硬件设备与操作系统内核的重要组件。Linux 将设备分为三大类:

        • 字符设备(Character Device)

        • 块设备(Block Device)

        • 网络设备(Network Device)

        (这部分内容在第一章有详细介绍)其中 字符设备驱动 是最基础的一类驱动,本实验基于经典的 Linux 驱动示例 scull(Simple Character Utility for Loading Localities),实现一个简单的字符设备驱动,并通过用户程序与驱动进行交互,从而理解 Linux 设备驱动的基本机制。

        本实验的主要目标

1. 编写一个简单的字符设备驱动 scull

2. 学习 Linux 内核模块的编译与加载

3. 通过设备文件 /dev/scull 与驱动进行通信

4. 使用用户程序测试 open/read/write/release 等驱动接口

二、字符设备驱动基本原理

        在 Linux 中,用户程序与设备驱动之间并不是直接调用关系,而是通过 设备文件系统调用 进行交互。

        整体调用流程如下:

用户程序
   │
   │ open / read / write
   ▼
系统调用 (syscall)
   │
   ▼
VFS (虚拟文件系统)
   │
   ▼
file_operations
   │
   ▼
设备驱动函数

三、实验环境

        本书实验始终需要2.6.x以后的内核。

        实验目录结构:

ch3/
 ├── scull.c
 ├── scull.h
 ├── scull_test.c
 └── Makefile

四、驱动代码核心结构

        驱动中主要实现了以下函数:

scull_open()

scull_read()

scull_write()

scull_release()

scull_ioctl()

        并通过 file_operations 注册:

struct file_operations scull_fops =

{

    .owner = THIS_MODULE,

    .read = scull_read,

    .write = scull_write,

    .open = scull_open,

    .release = scull_release,

    .unlocked_ioctl = scull_ioctl,

};

同时在模块中声明:

MODULE_LICENSE("GPL");

否则模块编译时会报错。

五、编写 Makefile

用于编译内核模块:

obj-m += scull.o

all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
gcc -o scull_test scull_test.c


clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
rm -f scull_test

六、编译驱动模块

        进入实验目录执行:make

编译成功后生成:

scull.ko //内核模块

scull.o //编译中间文件

scull_test //用户测试程序

七、加载驱动模块

        使用 insmod 加载驱动:

sudo insmod scull.ko

        检查模块是否加载成功:

lsmod | grep scull

        输出(如上图所示):

scull 16384 0

        说明驱动已经成功加载到 Linux 内核中。

八、创建设备文件

        驱动加载成功后,需要在 /dev 目录创建字符设备文件:

sudo mknod /dev/scull c 111 0

sudo chmod 666 /dev/scull

        参数说明:

c   → 字符设备

111 → 主设备号

0   → 次设备号

九、用户程序测试驱动

        编写用户程序 scull_test.c,通过系统调用访问设备。

写入数据:

./scull_test write

读取数据:

./scull_test read

程序输出:

hello scull

说明驱动中的 read() 函数已经正常工作。

十、查看内核日志

        驱动中的 printk() 输出不会在终端显示,需要通过 dmesg 查看:

dmesg | tail

输出示例:

说明:

• 用户程序成功调用驱动

• open / write / release 函数均被执行

十一、实验总结

        通过本次实验,完成了一个简单的 Linux 字符设备驱动 scull 的实现,并掌握了以下关键知识:

1. Linux 字符设备驱动的基本结构

2. 内核模块的编译与加载过程

3. 设备文件 /dev 与驱动之间的关系

4. 用户空间程序与内核驱动之间的通信机制

5. copy_to_user() 与 copy_from_user() 的使用

        实验验证了 Linux 字符设备驱动中 open、read、write、release 等接口能够正常工作。

        字符设备驱动是 Linux 驱动开发中最基础的一类驱动,通过本实验可以对用户空间与内核空间的交互机制有更加直观的理解。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值