初级驱动DAY2

(一)内核模块的驱动程序框架

    //1,头文件
  1 #include "linux/init.h"
  2 #include "linux/module.h"
  3 
  4 // 2,模块加载函数
  5 static int __init drv_hello_init(void)
  6 {
  7     printk("------------%s--------------\n",__FUNCTION__);
  8     return 0;
  9 }
 10 //3,模块的卸载函数
 11 static void __exit drv_hello_exit(void)
 12 {
 13     printk("------------%s--------------\n",__FUNCTION__);
 14 }
 15//4,模块的认证与声明
 16 module_init(drv_hello_init); //模块入口函数声明
 17 module_exit(drv_hello_exit); //模块出口函数声明
 18 MODULE_LICENSE("GPL");
 
 编译内核模块:Makefile
  #指定内核源码的路径
  1 KERNEL_DIR =/home/andrew/S5pv210/kernel/linux-3.0.8
  #你需要编译的文件所在的路径
  2 CUR_DIR    =$(shell pwd)
  3 
  4 all:#将内核源码和目录中的源文件一起编译,编译生成.ko的模块文件
  5         make -C $(KERNEL_DIR) M=$(CUR_DIR) modules
            arm-none-linux-gnueabi-gcc $(Myapp).c -o $(Myapp)
  6 clean:#将内核源码和目录中的源文件一起编译,编译生成.ko的模块文件删除
  7         make -C $(KERNEL_DIR) M=$(CUR_DIR) clean
            
  8 install:#复制生成的.ko的文件到文件系统中
  9         cp ./*.ko /opt/rootfs/drv_module                             */
  #指定要编译的内核模块文件的名称
  10 obj-m = drv_hello_v1.o
     obj-m +=
  
  
  [root@farsight /drv_module]# insmod drv_hello_v1.ko   //在开发板中加载某一个模块
    ------------drv_hello_init--------------
    [root@farsight /drv_module]# rmmod drv_hello_v1//在开发板中卸载某一个模块
    ------------drv_hello_exit--------------
    [root@farsight /drv_module]# lsmod   //列出加载的模块
    drv_hello_v1 763 0 - Live 0x7f004000

(二)一个完整的驱动的组成
    1》申请设备号
        1>设备号的概念
            用一个32位的正数来表示,分为两部分:主设备号和次设备号
            主设备号:用32位正数的高12位表示,表示一类设备
            次设备号:用32位正数的低20位表示,表示设备编号
        2>如何申请设备号:
            //申请主设备号
            static inline int register_chrdev(unsigned int major, const char *name,  const struct file_operations *fops)
            //参数1:参数1为0,动态申请设备号
                  // 参数1大于,静态指定一个主设备号
            //参数2:字符串,自定义,设备描述信息
            //参数3:设备操作接口
            //返回值:参数1为0,调用成功,返回主设备号,调用失败返回错误码
                    //参数1大于,调用成功,返回0,调用失败返回错误码
                    
        3>unregister_chrdev(major,"drv_hello");//卸载设备号
        
        4>[root@farsight /drv_module]# cat /proc/devices   //参看申请的设备号
            Character devices:
              1 mem
              2 pty
              3 ttyp
              4 /dev/vc/0
              4 tty
              4 ttyS
              5 /dev/tty
              5 /dev/console
              5 /dev/ptmx
              7 vcs
             10 misc
             13 input
             21 sg
            128 ptm
            136 pts
            198 drv_hello
            
    2》创建设备文件(节点):应用层根据设备文件可以操作对应的设备
        1>手动创建
            mknod  设备文件的名称   类型  主设备号 次设备号
            [root@farsight /drv_module]# mknod /dev/drv_hello c 254 5
            [root@farsight /drv_module]# ls -l /dev/drv_hello   //参看设备文件
            crw-r--r--    1 0        0         254,   5 Jan  1 01:17 /dev/drv_hello
            
            //测试:设备文件是否能被应用层打开
             1 #include "stdio.h"
              2 #include <sys/types.h>
              3 #include <sys/stat.h>
              4 #include <fcntl.h>
              5 #include <stdlib.h>
              6 #include <unistd.h>
              7 int main(void)
              8 {
              9     int fd;
             10     fd=open("/dev/drv_hello",O_RDWR);
             11     if(fd<0){
             12         perror("open");
             13         exit(1);
             14     }
             15     close(fd);
             16     return 0;
             17 }

            实现设备接口:
            int drv_hello_open(struct inode *inode, struct file *filp)
            {
                printk("------------%s--------------\n",__FUNCTION__);
                return 0;
            }
            int drv_hello_close(struct inode *inode, struct file *filp)
            {
                printk("------------%s--------------\n",__FUNCTION__);
                return 0;
            }
            
            const struct file_operations fops={  
                .open=drv_hello_open,
                .release=drv_hello_close,
            };
            
            
        2>自动创建设备节点
            2.1>创建类
            struct class *class_create(struct module *owner, const char *name)
            //参数1:当前模块-----THIS_MODULE
            //参数2: 字符串----类的名称
            //返回值:成功----struct class的地址,失败---NULL
            
            cls=class_create(THIS_MODULE,"drv_hello");
            if(IS_ERR(cls)){//专门用来判断指针,是否为NULL指针和野指针,如果为NULL指针和野指针,返回值为真
                printk("class_create is error\n");
                ret=PTR_ERR(cls);//获取NULL指针和野指针的错误码
                goto register_err;
            }
            
            //rmmod命令时需要卸载
            class_destroy(cls);//卸载类
            
            2.2>创建设备节点
            extern struct device *device_create(struct class *cls, struct device *parent,
                    dev_t devt, void *drvdata,
                    const char *fmt, ...)
            //参数1: struct class结构体指针
            //参数2:父类;一般为NULL
            //参数3:设备号(包含主设备和次设备号)
                #define MINORBITS    20
                #define MINORMASK    ((1U << MINORBITS) - 1)

                #define MAJOR(dev)    ((unsigned int) ((dev) >> MINORBITS))//得到主设备号
                #define MINOR(dev)    ((unsigned int) ((dev) & MINORMASK))//得到次设备号
                ma:主设备号 
                mi:此设备号
                #define MKDEV(ma,mi)    (((ma) << MINORBITS) | (mi))//得到设备号
            //参数4:私有数据。一般为NULL
            //参数5:设备节点的名称
            //参数6:变参,和参数5一起使用,来表示设备节点的名称
            //返回值:struct device *指向设备文件的结构体
            
            
                // 2.2 创建设备节点
                devi=device_create(cls,NULL,MKDEV(major,5),NULL,"drv_hello");
                if(IS_ERR(devi)){//专门用来判断指针,是否为NULL指针和野指针,如果为NULL指针和野指针,返回值为真
                    printk("device_create is error\n");
                    ret=PTR_ERR(devi);//获取NULL指针和野指针的错误码
                    goto class_err;
                }
            
            
            device_destroy(cls,MKDEV(major,5));//卸载设备文件
            

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

__Lewis

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值