免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1625 | 回复: 0

我的Debian2.6.26 入门驱动 [复制链接]

论坛徽章:
0
发表于 2010-01-15 20:49 |显示全部楼层
    在linux写驱动要比windows下简单的多,不过刚开始驱动环境的搭建耗了我不少时间,下面主要说下我的第一个驱动的完整过程。
    一、下载内核源码.
    很简单,apt-get install linux-source-2.6.26,下载之后解压tar jxvf linux-source-2.6.26.tar.bz2。
    二、配置并编译内核
    配置使用默认的就可以,make oldconfig。然后是编译,make。编译的时间比较长。编译之后会在当前文件夹生成一个文件vmlinux。
    三、编译和安装模块
    make module, make module_install
    执行结束之后,会在/lib/modules下生成新的目录/lib/modules/2.6.26/。 在随后的编译模块文件时,要用到这个路径下的build目录。至此,内核编译完成。可以重启一下系统。
   
    这时候编译的时候就不会找不到delay.h之类的头文件了。下面写一个驱动的框架。

#ifndef __KERNEL__
#define __KERNEL__
#endif
#ifndef MODULE
#define MODULE
#endif
#define DEVICE_NAME "can_bus"
#include linux/module.h>
#include linux/kernel.h>
#include linux/sched.h>
#include linux/fs.h>
#include asm/uaccess.h>
#include asm/io.h>
typedef unsigned char BYTE;
int major;
ssize_t can_read (struct file *file,
                  char *buf,
                  size_t count,
                  loff_t *f_ops)
{
    printk ("can_read\n");
    return 0;
}
ssize_t can_write (struct file *file,
                   const char *buf,
                   size_t count,
                   loff_t *f_ops)
{
    printk ("can_write\n");
    return 0;
}
int can_ioctl (struct inode *inode,
               struct file *file,
               unsigned int ioctl_num,
               unsigned long ioctl_param)
{
    printk ("ioctl\n");
    return 0;
}
int can_open (struct inode *inode,
              struct file *file)
{
    printk ("open can bus\n");
    try_module_get (THIS_MODULE);
    return 0;
}
int can_release (struct inode *inode,
                 struct file *file)
{
    module_put (THIS_MODULE);
    return 0;
}
struct file_operations can_fops =
{
    open: can_open,
    read: can_read,
    write: can_write,
    ioctl: can_ioctl,
    release: can_release,
};
int can_init (void)
{
    int retval = 0;
    major = retval = register_chrdev (0, DEVICE_NAME, &can_fops);
    if (retval  0)
    {
        printk ("%s: register_chrdev () failed with %d\n",
            DEVICE_NAME, retval);
        return -ENODEV;
    }
    printk ("can_bus major num = %d\n", major);
    return 0;
}
void can_cleanup (void)
{
    iounmap (io_base);
    unregister_chrdev (major, DEVICE_NAME);
   
}
MODULE_LICENSE ("GPL");
module_init (can_init);
module_exit (can_cleanup);

这是我写的CAN总线的驱动,摘了个框架出来,在2.6内核下,模块计数的加减要用try_module_get和module_put,然后就是makefile的编写
obj-m:=can_bus.o
KERNELDIR:=/lib/modules/2.6.26/build
PWD:=$(shell pwd)
modules:
    $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
modules_install:
    $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install
clean:
    rm *.o *.ko *.mod.c *.order *.symvers

然后make就可以了,写驱动程序的时候,如果定义一个没有形参的函数,括号里一定要写上void,否则会有一个警告,虽然没什么大碍,不过有警告很不爽,看来养成良好的变成习惯也很重要,make之后会生成一个can_bus.ko,下面的就简单了
1、安装模块insmod can_bus.ko
    如果要想看到输出信息,可以用cat /var/log/messages或者切换到文本界面,直接就能在控制台看到输出:can_bus major num = 249,这是我这里显示的,就是说生成的主设备号是249,用lsmod可以查看模块是否加载了
2、创建设备文件
    mknod /dev/can_bus c 249 0,上面提到的249就用到了,我一直在想,当我使用open打开can_bus设备的时候,怎么跟我的驱动关联起来,这个249就是关键了,刚开始的时候,我就随便写了个主设备号,结果怎么也打不开设备。
3、测试
    int fd;
    fd = open ("/dev/can_bus", O_RDWR);
    if (fd  0)
    {
        printf ("open can_bus failed\n");
    }
    else
    {
        printf ("open can_bus success\n");
    }
如果成功打开就能看到控制台open can bus的输出,这时,一个完整的驱动就差不多了。要卸载模块,使用rmmod can_bus即可。
4、开机自动加载
    差不多就是还差一点,驱动不可能每次都要手动去加载,我想让驱动开机的时候自动加载,这就要修改rc.local文件,输入vim /etc/init.d/rc.local,在文件的最后两行添上
insmod /can/can_bus.ko
mknod /dev/can_bus c 249 0
我的can_bus.ko是放在/can目录下的,读者可自行修改,这下就完整了,重启电脑,在做下上面的测试,OK了,不用手动去加载了,大功告成。



本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u3/104756/showart_2150255.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP