Linuxwilliam hill官网
直播中

Mr_RMS

7年用户 327经验值
擅长:可编程逻辑 嵌入式技术 处理器/DSP 接口/总线/驱动 控制/MCU
私信 关注
[经验]

记录第一个字符设备驱动程序——first_drv.ko 步骤

第一个字符设备驱动程序——first_drv

1、编写驱动程序first_drv.c

(1)编写函数first_drv_open()等

(2)在内核中挂载驱动程序

       1)定义一个staticstruct file_operations first_drv_fops={

       .owner =   THIS_MODULE,    /* 这是一个宏,推向编译模块时自动创建的__this_module变量*/

       .open  =   first_drv_open,     

       .write      =     first_drv_write,

}

2)把这个结构在内核注册:

              register_chrdev(unsigned intmajor, const char * name, const struct file_operations * fops)

       3)驱动入口调用注册函数:

              intfirst_drv_init(viod)

{

                     register_chrdev(111,"first_drv", &first_drv_fops);

return 0;

}

4)修饰调用入口函数:

module_init(first_drv_init)

(3)卸载驱动程序

       void first_drv_exit(void)

       {

              unregister_chrdev(111,”first_dev”)

}

修饰卸载函数:

module_exit(first_drv_exit);

(4)MODULE_LICENSE(GPL);

2、编译first_drv.c:

使用Makefile:

KERN_DIR =/work/system/linux-2.6.22.6    //使用/work/system/linux-2.6.22.6/Makefile

all:

              make-C $(KERN_DIR) M=`pwd` modules

clean:

              make-C $(KERN_DIR) M=`pwd` modules clean

              rm-rf modules.order

obj-m      += first_drv.o

得到first_drv.ko 文件

3、加载first_drv.ko

       (1)/first_drv$ cp  first_drv.ko /home/first_fs     //复制到之前制作的根文件系统

       (2)将first_fs根文件系统下载到开发板上并启动

       (3)#insmod first_drv.ko      //加载first_drv.ko模块

(4)#cat /proc/devices        //打印出目前内核中支持的设备

4、创建first_drv设备节点

       #mknod /dev/xxx  c 111  0

       设备节点的名称可以随便取,这里设为xxx

       问题:如何确定创建设备节点的主设备号?

       方法一:#cat  proc/devices      //查看单板中还有哪些空缺主设备号,选一个未使用的即可

       方法二:

       int major;

int first_drv_init(viod)

{

              major = register_chrdev(0, "first_drv",&first_drv_fops);

return 0;

}

void first_drv_exit(void)

       {

              unregister_chrdev(major, ”first_dev”)

}

将主设备号设为0,系统自动分配

(1)手动设置:将分配的主设备号为设备节点的主设备号

(2)自动设置:使用mdev,当我们注册(加载)一个驱动设备时,系统会在/sys目录下自动生成这个设备节点的相关信息,  mdev会根据系统信息自动创建设备节点

       1)在first_drv.c中添加:

              static struct class *firstdrv_class;

static struct class_device *firstdrv_class_dev;

       2)int first_drv_init(viod)

{

              major= register_chrdev(0, "first_drv", &first_drv_fops);

firstdrv_class = class_create(THIS_MODULE,"firstdrv");

firstdrv_class_dev = class_device_create(firstdrv_class,NULL, MKDEV(major, 0), NULL, "xxx");

return 0;

}

相应的,在卸载驱动是同样添加:

       voidfirst_drv_exit(void)

       {

              unregister_chrdev(major,”first_dev”);

              class_device_unregister(firstdrv_class_dev);

class_destory (firstdrv_class);

}

       重新编译即可

5、写一个测试程序firstdrvtest.c

       #include

#include

#include

#include

      staticstruct class *firstdrv_class;

static struct class_device *firstdrv_class_dev;

int main(int argc, char **argv)

{

              int fd;

              int val = 1;

              fd = open("/dev/xxx",O_RDWR);    //相应的执行驱动程序里的first_drv_open函数

              if (fd < 0)

              {

                     printf("can'topen!n");

              }

              write("/dev/xxx",O_RDWR);     // //相应的执行驱动程序里的first_drv_write函数

              return 0;

}

Question: 为什么open、write与first_drv_open、first_drv_write相对应?

6、编译firstdrvtest.c

       first_drv$  ARM-linux-gcc  –o  firstdrvtest firstdrvtest.c

       first_drv$  chmod +x  firstdrvtest   //增加可执行属性,否则执行时会出现-sh:./firstdrvtest: Permission denied

       first_drv$  cp  firstdrvtest /home/book/first_fs

7、#./firstdrvtest   //执行

附first_drv.c:

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

staticint first_drv_open(struct inode *inode, struct file *file)

{

       printk("first_drv_openn");

       return 0;

}

staticssize_t first_drv_write(struct file *file, const char __user *buf, size_tcount, loff_t * ppos)

{

       printk("first_drv_writen");

       return 0;

}

staticstruct file_operations first_drv_fops = {

       .owner =   THIS_MODULE,    /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */

       .open  =   first_drv_open,     

       .write      =     first_drv_write,         

};

intfirst_drv_init(void)

{

       major=register_chrdev(0,"first_drv", &first_drv_fops);

firstdrv_class =class_create(THIS_MODULE, "firstdrv");

firstdrv_class_dev =class_device_create(firstdrv_class, NULL, MKDEV(major, 0), NULL,"xxx");

       return 0;

}

voidfirst_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");


更多回帖

发帖
×
20
完善资料,
赚取积分