Linux 基础驱动 <1>

本文深入探讨了Linux驱动程序的开发过程,从初始化与退出、读写操作、装入与卸载模块,到模块信息展示及测试方法。通过具体代码解析,展示了如何实现设备的读写操作,并提供了测试驱动程序的两种方法。

使用Linux越来越多,千头万绪,冥冥之中走上这条路.........................

程序暂时是在ubuntu系统中测试的.

首先写驱动程序:

#include<linux/module.h>
#include<linux/init.h>
#include<linux/kernel.h>
#include<linux/fs.h>
#include<linux/miscdevice.h>
#include<linux/uaccess.h>
#define DEVICE_NAME "m_driver03"
/*
static struct file_operations dev_fops={
.owner = THIS_MODULE
};
static struct miscdevice misc={
.minor=MISC_DYNAMIC_MINOR,
.name=DEVICE_NAME,
.fops=&dev_fops
};
*/

static unsigned char mem[10000];
static int written_count=0;
static char read_flag='y';
/*
static int m_driver03_init(void){

    int ret;

    ret=misc_register(&misc);

    printk("m_driver03_init;\n");

    return 0;
}
*/

static ssize_t m_driver03_read(struct file *file,char __user *buf,size_t count,loff_t *ppos){
    
    printk("read function entrance !\n");

    unsigned char temp[4];

    temp[0]=written_count>>24;
    temp[1]=written_count>>16;
    temp[2]=written_count>>8;
    temp[3]=written_count;

    if(read_flag=='n'){
        copy_to_user(buf,(void*)temp,4);
        printk("read count : %d\t\n",(int)written_count);
        read_flag='y';

        return count;

    }else{
        return 0;
    }
}

static ssize_t m_driver03_write(struct file *file,const char __user *buf,size_t count,loff_t *ppos){
    copy_from_user(mem,buf,count);
    read_flag='n';

    printk("write function entrance !\n");

    written_count=count;
    printk("written count : %d\n",(int)count);

    return count;

}

static struct file_operations dev_fops={
.owner=THIS_MODULE,
.read=m_driver03_read,
.write=m_driver03_write
};

static struct miscdevice misc={
.minor=MISC_DYNAMIC_MINOR,
.name=DEVICE_NAME,
.fops=&dev_fops
};

static __init int m_driver03_init(void){

    int ret;

    ret=misc_register(&misc);

    printk("m_driver03_init;\n");

    return 0;
}

static __exit void m_driver03_exit(void){

    misc_deregister(&misc);

    printk("m_driver03_exit;\n");

}

module_init(m_driver03_init);
module_exit(m_driver03_exit);

MODULE_AUTHOR("stephen");
MODULE_DESCRIPTION("show how to develop linux module!");
MODULE_ALIAS("using linux module!");
MODULE_LICENSE("GPL");

 下面肢解上面各个部分:

<1> : 初始化时和退出时必须要的单元:

static __init int m_driver03_init(void){

    int ret;

    ret=misc_register(&misc);

    printk("m_driver03_init;\n");

    return 0;
}

这一段初始化代码,只要编译后,在终端输入insmod module_name装载模块就会进行初始,其中:

ret=misc_register(&misc);

是向系统注册一个设备,misc是一个结构体变量名.

static struct miscdevice misc={
.minor=MISC_DYNAMIC_MINOR,
.name=DEVICE_NAME,
.fops=&dev_fops
};

其中minor是动态分配一个次设备ID,
name是设备名,包括路径,格式="/dev/device_name"

fops是指向操作入口.

static struct file_operations dev_fops={
.owner=THIS_MODULE,
.read=m_driver03_read,
.write=m_driver03_write
};

其中read指向m_driver03_read是读取时使用的函数;
write指向m_driver03_write是写入设备时使用的函数;

下面是卸载设备操作时会调用的:

static __exit void m_driver03_exit(void){

    misc_deregister(&misc);

    printk("m_driver03_exit;\n");

}

反注册设备.
<2> : 具体读写操作如下:

另外附加信息:

#include<linux/module.h>
#include<linux/init.h>
#include<linux/kernel.h>
#include<linux/fs.h>
#include<linux/miscdevice.h>
#include<linux/uaccess.h>
#define DEVICE_NAME "m_driver03"
/*
static struct file_operations dev_fops={
.owner = THIS_MODULE
};
static struct miscdevice misc={
.minor=MISC_DYNAMIC_MINOR,
.name=DEVICE_NAME,
.fops=&dev_fops
};
*/

static unsigned char mem[10000];
static int written_count=0;
static char read_flag='y';

读设备:

static ssize_t m_driver03_read(struct file *file,char __user *buf,size_t count,loff_t *ppos){
    
    printk("read function entrance !\n");

    unsigned char temp[4];

    temp[0]=written_count>>24;
    temp[1]=written_count>>16;
    temp[2]=written_count>>8;
    temp[3]=written_count;

    if(read_flag=='n'){
        copy_to_user(buf,(void*)temp,4);
        printk("read count : %d\t\n",(int)written_count);
        read_flag='y';

        return count;

    }else{
        return 0;
    }
}

上面对应读取操作,下面对应写入操作:

static ssize_t m_driver03_write(struct file *file,const char __user *buf,size_t count,loff_t *ppos){
    copy_from_user(mem,buf,count);
    read_flag='n';

    printk("write function entrance !\n");

    written_count=count;
    printk("written count : %d\n",(int)count);

    return count;

}

<3> 装在卸载模块:

module_init(m_driver03_init);
module_exit(m_driver03_exit);

<4> 模块信息:

MODULE_AUTHOR("stephen");
MODULE_DESCRIPTION("show how to develop linux module!");
MODULE_ALIAS("using linux module!");
MODULE_LICENSE("GPL");

可以用下面命令行显示出来:上面模块名实际将会生成m_driver03.ko

$ sudo modinfo m_driver03.ko

<5> 为了编译上面的模块,我写了一个shell脚本:

#!/bin/bash
make -C /usr/src/linux-headers-3.8.0-29-generic M=/home/user/linux-driver/driver03
sudo insmod m_driver03.ko
#sudo lsmod | grep m_driver03
sudo dmesg | grep m_driver03 | tail -n 2
#sudo echo 'I love you' > /dev/m_driver03
#sudo dmesg | grep driver03 | tail -n 2
sudo rmmod m_driver03

修改属性:

sudo chmod u+x build.sh

另外我又写了一个启动和查看基本信息的shell脚本:

#!/bin/bash
sudo insmod m_driver03.ko
sudo lsmod | grep m_driver03
sudo dmesg | grep m_driver03 | tail -n 2
ls -a /dev
ls -l /dev
#cat /proc/devices
sudo modinfo m_driver03.ko

修改build_s.sh属性同上.

上面的已经测试过了,可以生成ko模块.

 

<6> : 测试上面的Linux驱动有两种方法,先第一种:

在测试之前,先修改一个驱动的属性:

sudo chmod 777 /dev/m_driver03

这里只是做测试用.
测试如下:

echo 'I like' > /dev/m_driver03
dmesg

<7> 第二种就是写一个程序来操作:

#include<stdio.h>
#include<fcntl.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
int main(int argc,char *argv[]){

    int testdev;
    unsigned char buf[4];

    printf("driver test programm !\n");

    testdev=open("/dev/m_driver03",O_RDWR);

    if(testdev==-1){
        printf("can not open device! \n");
        return 0;
    }
    
    if(argc>1){
        write(testdev,argv[1],strlen(argv[1]));
        printf("string:%s\n",argv[1]);
    }
    
    read(testdev,buf,4);

    int n=0;
    n=((int)buf[0])<<24|((int)buf[1])<<16 | ((int)buf[2])<<8 | ((int)buf[3]);


    printf("word byte display:%d,%d,%d,%d\n",buf[0],buf[1],buf[2],buf[3]);

    printf("word count : %d\n",n);

    close(testdev);

    return 0;

 }


<8> : 测试如下:

user@ubuntu:~/linux-driver/driver03$ ./driver_test "hello linux"
driver test programm !
string:hello linux
word byte display:0,0,0,11
word count : 11

要看驱动那边的打印信息:

dmesg


这样写出来以后,就可以迅速开始更深的东西...

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值