linux 驱动——字符设备驱动

编程入门 行业动态 更新时间:2024-10-25 00:37:06

linux 驱动——<a href=https://www.elefans.com/category/jswz/34/1771063.html style=字符设备驱动"/>

linux 驱动——字符设备驱动

文章目录

    • 字符设备驱动
    • 字符设备 APP
    • 模块操作
      • 模块安装
      • 创建设备节点
      • APP 操作模块
      • 卸载与删除模块
    • `shell` 脚本自动化

字符设备驱动

#include "linux/uaccess.h"
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>      /* struct file_operations  */
#include <linux/uaccess.h> /* copy_to_user() & copy_from_user */#define CHRDEVBASE_MAJOR 200         /* 主设备号 */
#define CHRDEVBASE_NAME "chrdevbase" /* 设备名 */static char write_buf[100];
static char read_buf[100];static char *string_test = "kernel data this tyustli test";static int chrdevbase_open(struct inode *inode, struct file *file)
{printk("k: chrdevbase open\r\n");return 0;
}static ssize_t chrdevbase_read(struct file *file, char __user *buf,size_t count, loff_t *ppos)
{unsigned long ret = 0;printk("k: chrdevbase read\r\n");memcpy(read_buf, string_test, strlen(string_test));ret = copy_to_user(buf, read_buf, count);if (ret == 0) {printk("k: read data success\r\n");} else {printk("k: read data failed ret = %ld\r\n", ret);}return ret;
}static ssize_t chrdevbase_write(struct file *file, const char __user *buf,size_t count, loff_t *ppos)
{unsigned long ret = 0;printk("k: chrdevbase write\r\n");ret = copy_from_user(write_buf, buf, count);if (ret == 0) {printk("k: write data success write data is: %s\r\n", write_buf);} else {printk("k: write data failed ret = %ld\r\n", ret);}return count;
}static int chrdevbase_release(struct inode *inode, struct file *file)
{printk("k: chrdevbase release\r\n");return 0;
}static struct file_operations chrdevbase_fops = {.owner = THIS_MODULE,.open = chrdevbase_open,.read = chrdevbase_read,.write = chrdevbase_write,.release = chrdevbase_release,
};static int __init chrdevbase_init(void)
{int ret = 0;ret = register_chrdev(CHRDEVBASE_MAJOR, CHRDEVBASE_NAME, &chrdevbase_fops);if (ret < 0) {printk("k: char dev register failed\r\n");}printk("k: base module init\r\n");return 0;
}static void __exit chrdevbase_exit(void)
{unregister_chrdev(CHRDEVBASE_MAJOR, CHRDEVBASE_NAME);printk("k: base module exit!\r\n");
}module_init(chrdevbase_init);
module_exit(chrdevbase_exit);MODULE_LICENSE("GPL");
MODULE_AUTHOR("tyustli");
MODULE_INFO(intree, "Y"); /* loading out-of-tree module taints kernel */

字符设备 APP

#include "stdio.h"
#include "unistd.h"
#include "sys/types.h"
#include "sys/stat.h"
#include "fcntl.h"
#include "stdlib.h"
#include "string.h"static char usrdata[] = { "user data!" };int main(int argc, char *argv[])
{int fd, retvalue;char *filename;char readbuf[100], writebuf[100];if (argc != 3) {printf("u: error Usage!\r\n");return -1;}filename = argv[1];/* 打开驱动文件 */fd = open(filename, O_RDWR);if (fd < 0) {printf("u: can't open file %s\r\n", filename);return -1;}/* 从驱动文件读取数据 */if (atoi(argv[2]) == 1) {retvalue = read(fd, readbuf, 50);if (retvalue < 0) {printf("u: read file %s failed!\r\n", filename);} else {/*  读取成功,打印出读取成功的数据 */printf("u: read data:%s\r\n", readbuf);}}/* 向设备驱动写数据 */if (atoi(argv[2]) == 2) {memcpy(writebuf, usrdata, sizeof(usrdata));retvalue = write(fd, writebuf, 50);if (retvalue < 0) {printf("u: write file %s failed!\r\n", filename);}}/* 关闭设备 */retvalue = close(fd);if (retvalue < 0) {printf("u: can't close file %s\r\n", filename);return -1;}return 0;
}

模块操作

模块安装

查看模块文件是否存在

ls /lib/modules/6.5.7+/my_module.ko 

安装

modprobe my_module

查看当前系统中的设备

cat proc/devices

输出

Character devices:1 mem2 pty3 ttyp4 /dev/vc/04 tty5 /dev/tty5 /dev/console5 /dev/ptmx7 vcs10 misc13 input29 fb90 mtd
116 alsa
128 ptm
136 pts
180 usb
189 usb_device
200 chrdevbase
204 ttyAMA
226 drm
249 rpmb
250 usbmon
251 ptp
252 pps
253 rtc
254 gpiochip

创建设备节点

创建设备节点起始就是在 /dev 目录下创建一个文件,这样 APP 就可以访问这个文件了

mknod /dev/chrdevbase c 200 0
  • mknod 创建设备节点命令
  • /dev/chrdevbase 是要创建的节点文件
  • c 表示是字符设备
  • 200 是设备的主设备号
  • 0 是设备的次设备号

创建完成以后就会存在 /dev/chrdevbase 这个文件

ls /dev/chrdevbase -l

结果日志

crw-r--r--    1 0        0         200,   0 Nov  5 03:10 /dev/chrdevbase

APP 操作模块

lib/modules/6.5.7+/my_app /dev/chrdevbase 1

读结果

k: chrdevbase open
k: chrdevbase read
k: read data success
u: read data:kernel data this tyustli test
k: chrdevbase release

lib/modules/6.5.7+/my_app /dev/chrdevbase 2

写结果

k: chrdevbase open
k: chrdevbase write
k: write data success write data is: user data!
k: chrdevbase release

卸载与删除模块

# 删除模块
rmmod my_module
# 删除设备节点文件
rm /dev/chrdevbase

shell 脚本自动化

shell 脚本自动编译模块和 APP 文件并启动 qemu

#                          参数解析
# ./my_module_build.sh      para1            para2(可选)
#   脚本名称            指定模块路径     是否执行 make clean 命令# 判断 shell 脚本有几个参数,如果没有指定 module 目录, shell 脚本就报错退出
if [ $# -eq 0 ]; thenecho "Incorrect number of arguments for command
Usage: my_module_build.sh <module_dir>  build your own module"exit
fi# 切换到指定的目录
cd $1# 如果是清除工程,就执行 make clean 命令
if [ "$2" == "clean" ]; thenmake cleanexit
fi# 编译指定目录的模块
make
python3 ../../tools/clang-tools/gen_compile_commands.py# 编译 APP 文件并将 APP 文件拷贝到根文件系统中
arm-none-linux-gnueabihf-gcc \
/home/tyustli/code/qemu_code/linux_driver/$1/my_app.c -o \
/home/tyustli/code/qemu_code/linux_driver/$1/my_appcp /home/tyustli/code/qemu_code/linux_driver/$1/my_app /home/tyustli/code/open_source/busybox/rootfs/lib/modules/6.5.7+# 将生成的 .ko 文件拷贝到根文件系统的 roorfs 中
cp ./my_module.ko /home/tyustli/code/open_source/busybox/rootfs/lib/modules/6.5.7+# 切换到根文件系统目录
cd /home/tyustli/code/open_source/busybox
# 生成虚拟 SD 卡系统镜像
sudo dd if=/dev/zero of=rootfs.ext3 bs=1M count=128
# 格式化镜像
sudo mkfs.ext3 rootfs.ext3#将文件复制到镜像中
sudo mkdir tmpfs_rootfs
sudo mount -t ext3 rootfs.ext3 tmpfs_rootfs/ -o loop
sudo cp -r rootfs/*  tmpfs_rootfs/
sudo umount tmpfs_rootfs
rmdir tmpfs_rootfs# 切换回指定的目录
cd /home/tyustli/code/qemu_code/linux_driver/$1# 启动 kernel
sudo qemu-system-arm -M vexpress-a9 -m 512M \
-kernel /home/tyustli/code/open_source/kernel/linux-6.5.7/arch/arm/boot/zImage \
-dtb /home/tyustli/code/open_source/kernel/linux-6.5.7/arch/arm/boot/dts/arm/vexpress-v2p-ca9.dtb -nographic \
-append "root=/dev/mmcblk0 rw console=ttyAMA0" \
-sd /home/tyustli/code/open_source/busybox/rootfs.ext3

仓库地址

更多推荐

linux 驱动——字符设备驱动

本文发布于:2023-11-16 11:19:43,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1619340.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:字符   设备   linux

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!