Linux驱动入门级编写

  时间:2020-07-10 22:59:24  阅读量:2.0k+  评论数:0  作者:抽屉疯了

该文着重介绍Linux驱动入门级编写相关知识,作者举例代码和分析说明恰到好处,遇到问题的朋友可以研究一下。

Linux驱动入门级操作

这个是在有开发板情况下,进行驱动编写
1.环境准备
看清楚很重要
在Ubuntu虚拟机上,前提配置好相对应版本arm-linux-gcc(不是说越高版本越好,最好是开发板配套的版本)
①准备开发板相对应Linux内核源码
②打补丁
③编译内核
(网上教程很多)

我的情况:
我的开发板是韦东山老师的S3C2440,提供的内核版本是2.6.22.6。
内核源码内通过查看arch/arm/configs目录,可以查看到不同开发板所需的编译参数设置。

不同版本arm-linux-gcc配置的glibc版本不一样,像之前用的arm-linux-gcc4.4.3使用的glibc是2.4,开发板不支持2.4,如果要升级的话会很麻烦,我就用了配套的arm-linux-gcc3.4.5,它的glibc是2.3.6。

2.编写驱动
搭建驱动框架
①首先要有
file_operations:
{
.open
.write
.read
}
按照我的理解是连接用户态和内核态程序的一个结构体

②入口函数注册驱动
出口函数卸载驱动

module_init(first_drv_init);
module_exit(first_drv_exit);

③给内核更多信息
利用udev机制自动创建设备节点
/dev/firstdrv

firstdrv_class = class_create(THIS_MODULE,"firstdrv");
firstdrv_class_dev=class_device_create(firstdrv_class,NULL,MKDEV(major,0),NULL,"firstdrv");

完整驱动框架代码

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/delay.h>
#include <linux/kernel.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/arch/regs-gpio.h>
#include <asm/hardware.h>

static struct class *firstdrv_class;
static struct class_device *firstdrv_class_dev;
//打开/dev设备对应的函数
static int first_drv_open(struct inode *inode,struct file *file)
{
    printk("first_drv_open\n");
    return 0;
}
//写入/dev设备对应的函数
static ssize_t  first_drv_write(struct file *file,const char __user *buf,size_t count,loff_t *ppos)
{
    printk("first_drv_write\n");
    return 0;
}
//用file_operations结构体保存对应的函数
static struct file_operations first_drv_fops={
    .owner = THIS_MODULE,
    .open  = first_drv_open,
    .write = first_drv_write,
};

//主设备号
int major;

//驱动注册
int first_drv_init(void)
{
    //0是自动分配主设备号,把file_operations保存到内核主设备号中,/proc/devices文件可以查看
    major=register_chrdev(0,"first_drv",&first_drv_fops);
    //创建类
    firstdrv_class = class_create(THIS_MODULE,"firstdrv");
    if(IS_ERR(firstdrv_class))
    {
        return PTR_ERR(firstdrv_class);
    }
    //在/dev自动创建设备
    firstdrv_class_dev=class_device_create(firstdrv_class,NULL,MKDEV(major,0),NULL,"firstdrv");
    if(unlikely(IS_ERR(firstdrv_class_dev)))
    {
        return PTR_ERR(firstdrv_class_dev);
    }   
    return 0;
}

//驱动注销
void first_drv_exit(void)
{
    unregister_chrdev(major,"first_drv");
    class_device_unregister(firstdrv_class_dev);
    class_destroy(firstdrv_class);
}

module_init(first_drv_init);
module_exit(first_drv_exit);

MODULE_LICENSE("GPL");

3.编写Makefile

CURRENT_PATH:=$(shell pwd)
#内核源码所在位置
LINUX_KERNEL_PATH:=/home/chouti/linux-2.6.22.6

all:
	make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules
    
clean:
	make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules clean
	rm -rf modules.order

obj-m  = first_drv.o

直接

make

如果成功的话回生成ko文件。

#安装驱动
insmod first_drv.ko
#查看驱动
lsmod
#卸载驱动
rmmod first_drv.ko

3.使用驱动代码

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>

int main(int argc,char **argv)
{
    int fd;
    int val=1;
    fd=open("/dev/firstdrv",O_RDWR);
    if(fd<0)
        printf("open fail!\n");
    
    write(fd,&val,4);
    
    return 0;
}

用arm-linux-gcc 编译

arm-linux-gcc first_drv_test.c -o first_drv_test
./first_drv_test
#输出
first_drv_open
first_drv_write

关键词:linux,驱动,入门,编写