字符驱动-1

参考文章http://dev.yesky.com/186/2623186.shtml,本文浅显易懂,写得非常好,看完了再去看《Linux设备驱动》就会更容易理解。

不过文章内有错误,好像作者没有自己运行过似的,将用红色字体指明。

 

 

//------------------------------------globalvar.c----------------------------------

#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
MODULE_LICENSE("GPL");

#define MAJOR_NUM 250  //原文是254,不过我的设备已经占用了

static ssize_t globalvar_read(struct file *,char *,size_t,loff_t *);
static ssize_t globalvar_write(struct file *,const char *,size_t,loff_t *);

struct file_operations globalvar_fops =
{
    read:globalvar_read,
    write:globalvar_write,
};

static int global_var=0;

static int __init globalvar_init(void)
{
    int ret;
    ret=register_chrdev(MAJOR_NUM,"globalvar",&globalvar_fops);
    if(ret)
    {
        printk("globalvar register failture");
    }
    else
    {
        printk("globalvar register success");
    }
    return ret;
}

static void __exit globalvar_exit(void)
{
    int ret;
   
    unregister_chrdev(MAJOR_NUM,"globalvar");

    //错误我已经注释掉了
/*
    ret = unregister_chrdev(MAJOR_NUM,"globalvar");

    if(ret)
    {
        printk("globalvar unregister failure");
    }
    else
    {
        printk("globalvar unregister success");
    }
*/
}

static ssize_t globalvar_read(struct file *filp,char *buf,size_t len,loff_t *off)
{
    if(copy_to_user(buf,&global_var,sizeof(int)))
    {
        return -EFAULT;
    }
    return sizeof(int);
}
static ssize_t globalvar_write(struct file *filp,const char *buf,size_t len,loff_t *off)
{
    if(copy_from_user(&global_var,buf,sizeof(int)))
    {
        return -EFAULT;
    }
    return sizeof(int);
}
module_init(globalvar_init);
module_exit(globalvar_exit);

//---------------------------end------------------------------------

 

使用原文章编译的方法我是没成功,就用我给出的Makefile吧,make一下就行了,记得把hello.o改成globalvar.o

 

生成驱动程序

make

加载globalvar模块

sudo insmod globalvar.ko

 

观察一下设备文件,多出一个globalvar

cat /proc/devices

 

创建设备节点

mknod /dev/globalvar c 250 0

 

用户程序,这里不写了,看原文。

编译

gcc -o globalvartest globalvartest.c

 

 

下面是我执行的结果

king@king-laptop:~/programe/driver/2$ ./globalvartest
Device open failure
king@king-laptop:~/programe/driver/2$ sudo ./globalvartest //用超级用户
The globalvar is 0
Please input the num writen to globalvar
45
The globalvar is 45
king@king-laptop:~/programe/driver/2$ sudo ./globalvartest
The globalvar is 45
Please input the num writen to globalvar
567
The globalvar is 567
king@king-laptop:~/programe/driver/2$ sudo ./globalvartest
The globalvar is 567
Please input the num writen to globalvar
890
The globalvar is 890
king@king-laptop:~/programe/driver/2$

 

 

 

因为不是标准的C,所以没有main函数。为了标记驱动程序的入口点,就定义了一个module_init()函数来确定入口函数,由module_exit()来确定结束函数(清理垃圾)。由于编译程序是顺序编译的,所以module_init(),module_exit()必须在整个程序的结束位置才能保证编译顺利。
 
用C语言编写的驱动程序的最大不同就是没有入口函数main,代替他的函数是module_init,exit函数则由module_exit代替。
编写程序离不开自定义函数,驱动程序的又一点儿不同就是:如果自定义函数不在内核中注册,是不允许使用的。注册函数就是将自定义函数,内核和设备关联在一起,这样内核就知道该设备可以使用什么样的函数,而且你定义的函数在其他驱动中是无效的。用户程序在使用设备时,并不是显示地调用驱动程序定义的函数,内核函数与驱动函数有了对应关系。
 
什么是策略?我可以做什么。我可以做很多事情,比如1,2,3,4,5,6,...
什么是方法?我如何去做。我会做那么多的事情,我应该如何安排顺序呢?
驱动程序提供策略
应用程序提供方法
 
 
使用驱动的过程,就是注册和使用驱动函数的过程。
 
static int __init globalvar_init(void)
{
 int ret;
 
 //注册设备驱动
 ret = register_chrdev(MAJOR_NUM, "globalvar", &globalvar_fops);
 if (ret)        //这里的&globalvar_fops和使用信号的程序类似,自己先定义一个处理函数,然后再使用。
 {            //但是这里应该是在内核声明了内核函数的一个别名,如果不定义别名,直接使用内核函数原名应该也可以。
            //好象不是啊,后面有被声明函数的定义
  printk("globalvar register failure");
 }
 else
 {
  printk("globalvar register success");
 }
 return ret;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值