Linux下第一个驱动程序

本文作者分享了初次接触Linux驱动开发的经历,通过学习《Linux设备驱动开发详解》,尝试编写和加载名为globalmem的虚拟字符设备驱动。在编译和加载驱动的过程中,遇到内核版本不匹配的问题,最终通过调整Makefile和安装对应内核版本解决问题。在用户空间测试设备文件,实现了信息传递。作者建议驱动开发在原生Linux环境下进行,并推荐使用Code:Blocks作为C/C++ IDE。
摘要由CSDN通过智能技术生成

        因为在Ubuntu环境下写的文章和做的实验,没有安装linux下比较好用的截图工具,所以没有附带太多截屏,还望海涵,不过该描述的都到位了。

 

       曾经还一直处于应用程序开发的我,以为驱动开发者是那么的厉害,以为只有牛人才能走到这一步,随着知识的积累,发现并非如此,驱动开发并不像想象中那么特别,俗话说术业有专攻,开发者只是使用的工具不同,且从事的领域不同,产品不同罢了。只要能作出好的产品,你就是一个”牛人”。

 

       从这里开始进行系统化的驱动学习,主线是《Linux设备驱动开发详解》,之前大致看过这本书,起初感觉有些晦涩,但看了两本内核的书籍以后,重新回来读起来就比较顺流了,一口气读了好几章(主要是前几章是知识介绍性文章)。所以这里顺便推荐两本内核的书籍:

       《Linux内核设计与实现》,我看的是第二版,写的非常棒,简单易懂,要在介绍内核原理与实现机制,广度到了,深度不够,所以最好还得配合下边这本书一块儿看。

 

       《UnderstandingLinux kernel》——深入理解linux内核,这本书的第三版是基于2.6内核的,06年出版。我看的是英文原版的,所以看得速度比较满,不过正好和《Linux设备驱动开发详解》对接上了,刚看过《Understanding Linux kernel》中的同步异步,应该是第五章那里,然后《Linux设备驱动开发详解》就在第七章也讲到了,这样,可能那么多机制:锁,读写锁,顺序锁,信号量,读写信号量……一下出来这么多东西的话有些接受不了,但如果你之前看了《Linux内核设计与实现》后,最起码不会感觉恐慌,其实学习新的知识就是这样,一回生两回熟,再难理解的东西,功夫到了,也就理解了。

 

       好的,开始第一个驱动程序的学习,实例来自 Linux设备驱动开发详解,这里是创建了一个虚拟的字符设备globalmem,也就是一片内核空间的内存区域,来实现内核空间和用户空间的信息传递。(确实,我举不出来比这更好的例子来作第一个例子了,不过请相信,哪怕就是这个例子也是我一个字母一个字母敲出来的,并未直接取材自隋书的源码,主要是看我的注释,和我遇到的问题以及解决它的全过程,成功者找方法,失败者找借口!呵呵)

 

       不废话,上代码,别心急,看注释。。。

下边是驱动的源码,附上了详尽的注释:

globalmem.c


#include <linux/module.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/uaccess.h>

#define GLOBALMEM_SIZE 0x1000  /*4k的空间*/
#define MEM_CLEAR 0x1          /*清空全局内存*/
#define GLOBALMEM_MAJOR 250   /*预设的主设备号*/

static int globalmem_major = GLOBALMEM_MAJOR;

/*用面向对象思想对cdev重新封装,以便于方便我们的操作*/
struct globalmem_dev{
  struct cdev cdev;
  unsigned char mem[GLOBALMEM_SIZE];
};

struct globalmem_dev *globalmem_devp;      /*声明一个全局的设备结构体*/

/*用来注册到file_operations结构中open */
int globalmem_open(struct inode *inode,struct file *filp)
{
    filp->private_data = globalmem_devp;        /*当有多个同类设备时,用私有变量访问很有必要也很方便*/
    return 0;
}

/*用来注册到file_operations结构中release */
int globalmem_release(struct inode *inode,struct file *filp)
{
    return 0;
}

/*用来注册到file_operations结构中ioctl */
static int globalmem_ioctl(struct inode *inodep,struct file *filp,unsigned int cmd,unsigned long arg)
{
    struct globalmem_dev *dev = filp->private_data;     /*从私有数据获取设备结构体指针*/
    switch (cmd){
    case MEM_CLEAR:
        memset(dev->mem,0,GLOBALMEM_SIZE);
        printk(KERN_INFO"globalmem is set to zero\n");
        break;

    default:
        return -EINVAL;
    }

    return 0;
}

/*用来注册到file_operations结构中read */
static ssize_t globalmem_read(str
  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值