尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

Linux .ko字符串驱动模块

Linux .ko字符串驱动模块
📅 发布时间:2026/6/19 6:39:25

Linux分为内核态和用户态

实则就是分为了用户操作空间和内核操作空间

Linux驱动开发分为两种,可以将驱动编译到内核kernel中即image,或者module中,即.ko文件,内核文件编译比较繁杂,通常编译到.ko文件中

#include <linux/module.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("You");
MODULE_DESCRIPTION("Simple test character device module");static int __init mymodule_init(void){    printk("mymodule_init\n");    return 0;}static void __exit mymodule_exit(void){    printk("mymodule_exit\n");}
/*
*   模块的出口与入口函数
*/
module_init(mymodule_init);
module_exit(mymodule_exit);

这是一个最简单的字符串设备的驱动注册程序,这个代码的编写并没有难度,完全按照Linux官方的格式编写。难点在于这个程序的编译,Linux的编译多数使用Makefile文件,发展到今天已经形成了标准化的格式。对于模块驱动(.ko)的编译也不例外,使用标准格式即可。以下是Makefile文件的编写

KERNEL := /home/pro/prj/k230_linux_sdk/output/k230_canmv_lckfb_defconfig/build/linux-7d4e1f444f461dbe3833bd99a4640e7b6c2cd529
INC := /opt/toolchain/Xuantie-900-gcc-linux-6.6.0-glibc-x86_64-V3.0.2/include
CURRENT_PATH := $(shell pwd)
obj-m := mymodule.o
# Cross-compiler prefix (no trailing gcc) — used by kernel build system
CROSS_COMPILE := /opt/toolchain/Xuantie-900-gcc-linux-6.6.0-glibc-x86_64-V3.0.2/bin/riscv64-unknown-linux-gnu-
# Target architecture
ARCH ?= riscvbuild: kernel_moduleskernel_modules:
    $(MAKE) -C $(KERNEL) M=$(CURRENT_PATH) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modulesclean:
    $(MAKE) -C $(KERNEL),$(INC) M=$(CURRENT_PATH) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) clean

字符串设备

注册设备我们需要使用一个函数register_chrdev,并且在卸载设备的时候也需要先注销一个注册的设备使用函数unregister_chrdev。
register_chrdev函数用于注册字符设备,此函数一共有三个参数,这三个参数的含义如下:

  • major:主设备号,Linux下每个设备都有一个设备号,设备号分为主设备号和次设备号两 部分,关于设备号后面会详细讲解。
  • name:设备名字,指向一串字符串。
  • fops:结构体file_operations类型指针,指向设备的操作函数集合变量。
    unregister_chrdev函数用户注销字符设备,此函数有两个参数,这两个参数含义如下:
  • major:要注销的设备对应的主设备号。
  • name:要注销的设备对应的设备名。
//设备号的原始类型,即一个无符号的32位整型
typedef u32 __kernel_dev_t;typedef __kernel_fd_set     fd_set;
typedef __kernel_dev_t      dev_t;

Linux内核将设备号分为两类,主设备号和次设备号,故主设备号会占用高12位,次设备号占用低20位。

register_chrdev(unsigned int major, const char *name, const struct file_operations *fops);
unregister_chrdev(unsigned int major, const char *name);

这两个函数的注册方式在现在看来过于片面,可以在第一个参数中看出,在注册设备时只能填写major,但在一个设备注册时应该有主设备和次设备号互相作用的。这样就导致了注册到一个MAJOR时会直接忽略掉次设备号的全部字段, 2^12 = 4096个设备号被浪费。

const struct file_operations

这是Linux设备的属性结构体,其中定义了许多设备功能,就比如一个设备只有在注册的时候拥有open、close、read和write等等,这样在C语言中调用open函数这些函数时才有效。在内核文件Linux/include/fs.h中有着完整的结构体定义。

struct file_operations {
    struct module *owner;
    loff_t (*llseek) (struct file *, loff_t, int);
    ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
    ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
    ssize_t (*read_iter) (struct kiocb *, struct iov_iter *);
    ssize_t (*write_iter) (struct kiocb *, struct iov_iter *);
    int (*iopoll)(struct kiocb *kiocb, struct io_comp_batch *,
            unsigned int flags);
    int (*iterate_shared) (struct file *, struct dir_context *);
    __poll_t (*poll) (struct file *, struct poll_table_struct *);
    long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
    long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
    int (*mmap) (struct file *, struct vm_area_struct *);
    unsigned long mmap_supported_flags;
    int (*open) (struct inode *, struct file *);
    int (*flush) (struct file *, fl_owner_t id);
    int (*release) (struct inode *, struct file *);
    int (*fsync) (struct file *, loff_t, loff_t, int datasync);
    int (*fasync) (int, struct file *, int);
    int (*lock) (struct file *, int, struct file_lock *);
    unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
    int (*check_flags)(int);
    int (*flock) (struct file *, int, struct file_lock *);
    ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
    ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
    void (*splice_eof)(struct file *file);
    int (*setlease)(struct file *, int, struct file_lock **, void **);
    long (*fallocate)(struct file *file, int mode, loff_t offset,
              loff_t len);
    void (*show_fdinfo)(struct seq_file *m, struct file *f);
#ifndef CONFIG_MMU
    unsigned (*mmap_capabilities)(struct file *);
#endif
    ssize_t (*copy_file_range)(struct file *, loff_t, struct file *,
            loff_t, size_t, unsigned int);
    loff_t (*remap_file_range)(struct file *file_in, loff_t pos_in,
                   struct file *file_out, loff_t pos_out,
                   loff_t len, unsigned int remap_flags);
    int (*fadvise)(struct file *, loff_t, loff_t, int);
    int (*uring_cmd)(struct io_uring_cmd *ioucmd, unsigned int issue_flags);
    int (*uring_cmd_iopoll)(struct io_uring_cmd *, struct io_comp_batch *,
                unsigned int poll_flags);
} __randomize_layout;

字符设备驱动的函数实现

上面了解到一个字符串设备是否有功能,完全取决于动作结构体的实现。


待更新

相关新闻

  • YOLOFuse vs DEYOLO:多模态检测模型性能与资源消耗全面对比
  • YOLOFuse术语表整理:统一技术词汇翻译标准
  • YOLOFuse训练脚本train_dual.py使用说明及参数配置建议

最新新闻

  • 机器学习模型上线后如何应对系统性风险与数据漂移
  • 什么是伯乐电穿孔仪 - 实了个验
  • CTF密码学实战:Python AES加解密核心原理与攻击技巧
  • 2026 南宁钻石回收最新行情,克拉钻裸钻实时报价参考 - 讯息早知道
  • 北京东城区黄金回收指南:收的顶专业机构VS银行VS金店怎么选? - 奢侈品回收测评
  • 2026西安黄金行情解析|高位变现时机与门店测评 - 奢侈品回收测评

日新闻

  • 5分钟掌握Python进化算法:Geatpy高性能优化工具完全指南
  • Microchip 24AA044 EEPROM选型与应用全指南:从参数解析到实战编程
  • 华为的鸿蒙到底有多牛?为什么称作遥遥领先?

周新闻

  • 3步解锁iOS设备:applera1n激活锁绕过完全指南
  • 39 2026 人工智能证书终极盘点,普通人选 AI 证书可以从这些方向入手
  • Redis 暴露公网有多危险?从端口检查到补救步骤

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号