linux设备驱动程序学习笔记--helloworld

来源:互联网 发布:能直接利用geo数据库数 编辑:程序博客网 时间:2024/05/16 06:14

linux内核是以模块化的方式实现的,例如磁盘驱动,光盘驱动,键盘驱动等等,这些都是一个个的模块可以加载也可以动态的卸载。这样非常有利于驱动的开发调试,也可以保持内核的最小化运行(只加载需要运行的驱动或者模块)。

本系列文章就通过《linux设备驱动程序》一书学习一下内核模块的编写,编译,运行等知识,对文中主要内容记录以便后面理解使用。在这里统一使用“驱动”来表示内核模块。

首先从应用层来讲一下内核模块的使用,常用命令如下:

  • 1,insmod   在内核中插入模块,参数为需要插入驱动的名称,但是要保证执行insmod命令时能访问到相应模块(全路径或者相对路径),例如:

itsenlin@itsenlin-N43SL:~$ sudo insmod workspace/helloworld/helloworld.ko 

[sudo] password for itsenlin: 

itsenlin@itsenlin-N43SL:~$

  • 2,lsmod 查询系统中已经插入的驱动,例如:

itsenlin@itsenlin-N43SL:~$ lsmod | grep hello

helloworld             12496  0 

itsenlin@itsenlin-N43SL:~$ 

  • 3,rmmod 卸载驱动,与insmod命令一样参数是驱动的名称,注意,这个名称是由lsmod查询出来的名称,如上面的“helloworld”

itsenlin@itsenlin-N43SL:~$ sudo rmmod helloworld

itsenlin@itsenlin-N43SL:~$ 

  • 4,depmod 生成各驱动的依赖关系文件(modules.dep)以及map文件,用于内核启动时可以自动加载,或者使用modprobe命令时加载所有依赖的模块。一般使用“depmod -a”

  • 5,modprobe 相当于insmod和rmmod的合集,通过参数来驱分是插入还是卸载驱动(带“-r”参数表示卸载,不带则表示插入)。这个命令的好处是通过读取驱动依赖关系来自动插入所依赖的驱动(如果存在)然后再插入指定的驱动。


说明:上面在插入/卸载驱动时没有任何输出,也不知道是对是错。其实驱动也是在内核态运行,一般的信息输出使用的是printk函数,其日志是可以通过dmesg命令来查看,例如上面helloworld的输出如下:

itsenlin@itsenlin-N43SL:~/workspace/helloworld$ sudo insmod helloworld.ko 

itsenlin@itsenlin-N43SL:~/workspace/helloworld$ dmesg

[ 3502.422410] Hello, world!

itsenlin@itsenlin-N43SL:~/workspace/helloworld$ sudo rmmod helloworld 

itsenlin@itsenlin-N43SL:~/workspace/helloworld$ dmesg 

[ 3502.422410] Hello, world!

[ 3515.328210] Googbye!

itsenlin@itsenlin-N43SL:~/workspace/helloworld$ 


在linux下管理驱动就是这么简单,上面用到的helloworld.ko就是书中的第一个驱动实例“Hello world”。

源代码如下:

#include <linux/init.h>#include <linux/module.h>MODULE_LICENSE("Dual BSD/GPL");static int hello_init(void){    printk(KERN_ALERT "Hello, world!\n");    return 0;}static void hello_exit(void){    printk(KERN_ALERT "Googbye!\n");}module_init(hello_init);   //驱动插入的入口,参数为入口函数module_exit(hello_exit);  //驱动卸载的入口,参数为入口函数


驱动的编译与用户态的进程编译有一些不一样,驱动需要通过内核源码树访问内核的一些数据结构,驱动的编译一般是通过makefile,如下

ifneq ($(KERNELRELEASE),)        obj-m := helloworld.oelse        KERNELDIR ?= /lib/modules/$(shell uname -r)/build        PWD := $(shell pwd)default:        $(MAKE) -C $(KERNELDIR) M=$(PWD) modulesendif
注意:

makefile中使用的命令开头是TAB,而不是空格键,这个是刚开始编译makefile常犯的错误。

0 0