美文网首页
力卉编程 | 字符设备节点创建步骤

力卉编程 | 字符设备节点创建步骤

作者: 力卉编程 | 来源:发表于2020-04-04 16:00 被阅读0次

一、框架

先讲解驱动框架, 然后写出first_drv驱动程序,来打印一些信息

写出first_drv驱动程序需要以下几步:
(1)写出驱动程序first_drv_open first_drv_write
(2)需要定义file_operations结构体来封装驱动函数first_drv_open first_drv_write
对于字符设备来说,常用file_operations以下几个成员:


函数列表

(3) 模块加载函数,通过函数 register_chrdev(major, “first_drv”, &first_drv_fops) 来注册字符设备
(4)写驱动的first_drv_init 入口函数来调用这个register_chrdev()注册函数,
(5)通过module_init()来修饰入口函数,使内核知道有这个函数
(6)写驱动的first_drv_exit出口函数,调用这个unregister_chrdev()函数卸载,
(7) 通过module_exit()来修饰出口函数
(8) 模块许可证声明, 最常见的是以MODULE_LICENSE( "GPL v2" )来声明

二、实例:

主要思想如下:

  • module_init(first_drv_init);
  • module_exit(first_drv_exit);
  • MODULE_LICENSE( "GPL v2" );
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/irq.h>
#include <asm/arch/regs-gpio.h>
#include <asm/hardware.h>
#include <asm/uaccess.h>
#include <asm/io.h>
/*1写出驱动程序first_drv_open first_drv_write */
/*  inode结构表示具体的文件,file结构体用来追踪文件在运行时的状态信息。*/
static int first_drv_open(struct inode *inode, struct file  *file)
{
   printk(“first_drv_open\n”);      //打印,在内核中打印只能用printk()
   return 0;
}
/*参数filp为目标文件结构体指针,buffer为要写入文件的信息缓冲区,count为要写入信息的长度,ppos为当前的偏移位置,这个值通常是用来判断写文件是否越界*/
static ssize_t first_drv_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
{
  printk(“first_drv_write\n”);      //打印,在内核中打印只能用printk()
   return 0;
}
/*2定义file_operations结构体来封装驱动函数first_drv_open first_drv_write */
 static struct file_operations first_drv_fops = {
    .owner  =   THIS_MODULE,     //被使用时阻止模块被卸载
    .open   =   first_drv_open,      
    .write   =   first_drv_write,   
  };
/*4写first_drv_init入口函数来调用这个register_chrdev()注册函数*/
int first_drv_init(void)
{
   /*3 register_chrdev注册字符设备,并设置major=111*/
  /*如果设置major为0,表示由内核动态分配主设备号,函数的返回值是主设备号*/
register_chrdev (111, “first_drv”, &first_drv_fops); //111:主设备号,”first_drv”:设备名
/*
register_chrdev作用:在VFS虚拟文件系统中找到字符设备,然后通过主设备号找到内核数组里对应的位置,最后将设备名字和fops结构体填进去
*/
   return 0;
}
/*5 module_init修饰入口函数*/
module_init(first_drv_init);
/*6 写first_drv_exit出口函数*/
void first_drv_exit(void)
{
  unregister_chrdev (111, “first_drv”);  //卸载驱动,只需要主设备号和设备名就行 
}

/*7 module_exit修饰出口函数*/
module_exit(first_drv_exit);
/*8许可证声明, 描述内核模块的许可权限,如果不声明LICENSE,模块被加载时,将收到内核被污染 (kernel tainted)的警告。*/
MODULE_LICENSE( "GPL v2" );

写Makefile编译脚本:

KERN_DIR = /work/system/linux-2.6.22.6
all:                                
       make -C $(KERN_DIR) M=`pwd` modules   
// M=`pwd`:指定当前目录
//make -C $(KERN_DIR) 表示将进入(KERN_DIR)目录,执行该目录下的Makefile
//等价于在linux-2.6.22.6目录下执行: make M=(当前目录) modules
// modules:要编译的目标文件
clean:
       make -C $(KERN_DIR) M=`pwd` modules clean
       rm -rf modules.order
obj-m      += frist_drv.o

编译生成frist_drv.ko文件
加载之前首先通过 cat /proc/devices来查看字符主设备号frist_drv是否被占用
然后开发板通过nfs网络文件系统来加载frist_drv.ko
然后通过 insmod first_drv.ko来挂载, 通过 cat /proc/devices就能看到first_drv已挂载好

挂载 111 0设备,这里的111 0设备是在注册的时候指定的主设备号
mknod -m 660 /dev/mtd0 c 111 0

现在就可以像文件一样操作/dev/mtd0了.
注意:函数为空的地方是可以自行补充的,不一定只返回0,啥事也不做。

文 | 力卉编程

相关文章

网友评论

      本文标题:力卉编程 | 字符设备节点创建步骤

      本文链接:https://www.haomeiwen.com/subject/xasjphtx.html