• linux驱动笔记-设备驱动入门


    刚学习linux的时候我很迷惑,不清楚一个个设备是如何和系统联系起来的,最初我做了很多的无用功。我是学电子的,从大一就开始接触到单片机,但是我学了它之后我还没有一点点计算机系统的概念。

    下面对学习的快速入门经验(希望大家不要再像我一样走了弯路):

    对linux有一个最为初步的了解

    linux就是一个计算机系统,和windows7类似!那它的最为主要的原因是:开源(网上可以下载到它的源代码);如果以后要用到它,那就请多去了解下它。用上它之后,基本上每天都是和命令行打交道(现在的X图形界面虽好看,但个人认为不会shell是不行的)。原因是shell是一个非常基本的东西,它是直接和内核打交道的,用它的效率会提高很多。

    我们要做的工作简单来说:那就是做一个设备而这个设备是运行的一个操作系统,系统通过一些外部设备完成一些功能,系统对任务进行调度。

    那么我们要做的事也就是要做一个驱动程序去操控设备,那么设备如何明白这是一个驱动呢?那就需要这个驱动程序在结构、编译、执行上都有不同于一般程序的操作。系统提供一些IO接口,如file_operations结构体(一个字符驱动重要的结构体),结构中有很多指针函数,这些函数可以指向你的驱动程序中的某个函数。下面就以字符驱动为讲解,

    字符驱动程序要完成的工作如下:

     15 #define HELLO_MAJOR_NR 126      //device major number
     16 #define DEVICE_NAME "hello"     //device name

    为你的设备的创建一个file_operations结构,如:

     static struct file_operations hello_fops=
    {
             open:   hello_open,
             unlocked_ioctl: hello_ioctl,
              .release =      hello_release,
     };

    到系统中注册驱动(使用函数register_chrdev(HELLO_MAJOR_NR主设备号, DEVICE_NAME驱动名称,&hello_fops)

    使用你写的控制函数对设备进行操作。如:你写了一个hello_ioctl(struct file *filp,unsigned int cmd, unsigned long arg)。

    如果你是新手,现在可能会问如何调用这个控制函数呢?

    要完成注册后会在系统的/dev下面产生一个设备驱动对应的文件。文件名就是hello,

    还有一个不行不说一下的东东——

    驱动的安装insmod hello.ko     

    所以就必須要有一个安装时运行的函数module_init();  register_chrdev()向系统注册就是在这里完的。

    卸载时运行的函数module_exit();

    驱动的卸载rmmod hello.ko

    我们的驱动程序的主体就算是完成了,可控制函数到底在哪里用呢?

    答案:应用程序中。

    应用程序中,用open()打开/dev/hello得到文件指针,再使用ioctl()对设备进行操作,操作的完成就是用的通过参数的传递。

    下面给出驱动源码:

    #include<linux/module.h>
    #include<linux/sched.h>
    #include<linux/kernel.h>
    #include<linux/init.h>
    #include<linux/ioctl.h>
    #include<linux/fs.h>
    #include<linux/types.h>
    #include<linux/mm.h>
    #include "hello.h"
     
    static int hello_open(struct inode *inode,struct file *filp);
    static int hello_release(struct inode *inode,struct file *filp);
    static long hello_ioctl(struct file *filp,unsigned int cmd,unsigned long arg);
     
    #define HELLO_MAJOR_NR 126       //device major number
    #define DEVICE_NAME "hello"    //device name
     
    #define MAX_PORT 1        // 1 devices
    static struct file_operations hello_fops=
    {    
        open:    hello_open,
        unlocked_ioctl:    hello_ioctl,
        .release =    hello_release,
    };
    int __init hello_init(void)
    {
        int result;
        result = register_chrdev(HELLO_MAJOR_NR, DEVICE_NAME,&hello_fops);     //register facilities(¿¿)
        if(result<0) {
            printk(KERN_ERR DEVICE_NAME ":Unable to get major %d\n", HELLO_MAJOR_NR);
            return result;
        }
        printk(KERN_INFO DEVICE_NAME ":init OK, return %d\n",result);
        return 0;
    }
     
    void __exit hello_cleanup(void)
    {
        unregister_chrdev(HELLO_MAJOR_NR, DEVICE_NAME);
    }
     
    static int hello_open(struct inode *inode, struct file *filp)
    {
    //    M0D_INC_USE_COUNT;   
        return 0;
    }
    static int hello_release(struct inode *inode, struct file *filp)
    {
    //    MOD_DEC_USE_COUNT;   
        return 0;
    }
    static long hello_ioctl(struct file *filp,unsigned int cmd, unsigned long arg)
    {
    //参数arg没有用
        switch(cmd) {
        case  0:完成事件0

       case 1:完成事件1

       .....
        }
    return 0;
    }
    module_init(hello_init);
    module_exit(hello_cleanup);
    MODULE_LICENSE("GPL");     

    下面给出应用程序源码:

    #include<stdlib.h>
    #include<stdio.h>
    #include<fcntl.h>
    int main()
    {
        int fd;
        fd = open("/dev/hello",O_RDONLY);
        if(fd < 0) {
            printf("open error: %d\n",fd);
            return 0;
        }
        num = ioctl(fd,0,0);
        if(num == -1) {
            printf("ioctl errno\n");
            exit(1);
        }

         ioctl(fd,0,0);  //事件0

      ioctl(fd,1,0);  //事件1
        close(fd);
        exit(0);
    }

    由于水平有限,若有什么错误,欢迎大家指正!<xueyang1122@gmail.com>

  • 相关阅读:
    python笔记-13 mysql与sqlalchemy
    python笔记-12 redis缓存
    python笔记-11 rabbitmq
    python笔记-10(socket提升、paramiko、线程、进程、协程、同步IO、异步IO)
    python笔记-9(subprocess模块、面向对象、socket入门)
    python笔记-7(shutil/json/pickle/shelve/xml/configparser/hashlib模块)
    leetcode98
    leetcode543
    leetcode85
    leetcode84
  • 原文地址:https://www.cnblogs.com/xueyang/p/linux_driver.html
Copyright © 2020-2023  润新知