前言

  最近在学习Linux驱动,记录下自己学习的历程。

驱动的基本框架

  Linux驱动的基本框架包含两部分,“模块入口、出口的注册”和“模块入口、出口函数的实现”,如下方代码。  

 static int __init shanwuyan_init(void)    //驱动入口函数
{
return ;
} static void __exit shanwuyan_exit(void) //驱动出口函数
{ } module_init(shanwuyan_init); //注册入口函数
module_exit(shanwuyan_exit); //注册出口函数

  其中,module_init()和module_exit()两个函数的作用是注册驱动的入口“shanwuyan_init”和出口“shanwuyan_exit”。加载驱动时会运行入口函数,卸载驱动时会运行出口函数。入口函数的作用是加载驱动时做一些初始化工作,比如注册设备、申请设备号、生成设备节点等等,其返回值为int类型;出口函数的作用是卸载驱动时做一些善后操作,比如注销设备、注销设备号、销毁类等等。

一个基本驱动的编写

  本文的主要目的是让读者了解驱动的基本框架,我们先不实现注册设备、申请设备号、注销设备等复杂的工作。

  为了让驱动的加载和卸载工作更直观得为程序员所观察,我们可以在入口函数和出口函数中添加打印语句,这样每次加载和卸载驱动的时候,程序员都能在终端观察到相应的信息,如下方代码。  

 static int __init shanwuyan_init(void)    //驱动入口函数
{
printk(KERN_EMERG "shanwuyan_init\r\n");
return ;
} static void __exit shanwuyan_exit(void) //驱动出口函数
{
printk(KERN_EMERG "shanwuyan_exit\r\n");
}

  “printk”函数是什么?说到打印,有C语言基础的读者首先想到的可能就是“printf”函数,但是“printf”只能在应用层面工作,而设备驱动是工作在内核态下的,所以“printf”不能在设备驱动中工作。在内核态下的打印函数是“printk”函数。KERN_EMERG是打印优先级,这里采用了最高优先级。

  再加上头文件以及注册用的函数,可以得到一个相对完整的代码。    

 /* 源代码文件名为:shanwuyan.c */
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/uaccess.h> static int __init shanwuyan_init(void) //驱动入口函数
{
printk(KERN_EMERG "shanwuyan_init\r\n");
return ;
} static void __exit shanwuyan_exit(void) //驱动出口函数
{
printk(KERN_EMERG "shanwuyan_exit\r\n");
} module_init(shanwuyan_init); //注册入口函数
module_exit(shanwuyan_exit); //注册出口函数

  该设备驱动实现的功能是:加载驱动时打印字符串“shanwuyan_init”,卸载驱动时打印字符串“shanwuyan_exit”。

Makefile文件的编写

  Makefile文件没什么可说的,代码如下。  

 #!/bin/bash

 obj-m += shanwuyan.o    #此处要和你的驱动源文件同名

 KDIR := /home/topeet/Android/iTop4412_Kernel_3.0    #这里是你的内核目录

 PWD ?= $(shell pwd)

 all:
make -C $(KDIR) M=$(PWD) modules #make操作 clean:
make -C $(KDIR) M=$(PWD) clean #make clean操作

应用

  编译,并加载生成的“shanwuyan.ko”文件,加载驱动和卸载驱动的命令如下。  

 insmod shanwuyan.ko #加载驱动
rmmod shanwuyan.ko #卸载驱动,如果该命令不起作用,请用下方的命令
rmmod shanwuyan #卸载驱动

  进入到驱动文件所在的路径下,并在命令行输入加载驱动的命令“insmod shanwuyan.ko”,可以看到驱动入口函数打印出来的字符串信息“shanwuyan_init”。

  但是终端还打印了两行警告信息“shanwuyan: module license 'unspecified' taints kernel”和“Disabling lock debugging due to kernel”,这是因为我们没有在代码中加入同意开源协议,所以终端打印该信息。需要注意的是,该警告信息只有在系统启动后第一次加载驱动时才会打印,卸载掉之后,如果不重启系统,再加载驱动时就不会再打印这两行警告信息了。

  打开源文件,加入GPL开源协议,一个完整的基本驱动框架就完成了,全部代码如下。

 /* 源代码文件名为:shanwuyan.c */
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/uaccess.h> static int __init shanwuyan_init(void) //驱动入口函数
{
printk(KERN_EMERG "shanwuyan_init\r\n");
return ;
} static void __exit shanwuyan_exit(void) //驱动出口函数
{
printk(KERN_EMERG "shanwuyan_exit\r\n");
} module_init(shanwuyan_init); //注册入口函数
module_exit(shanwuyan_exit); //注册出口函数 MODULE_LICENSE("GPL"); //同意GPL开源协议,就不会打印警告信息了
MODULE_AUTHOR("shanwuyan"); //还可以再添加上作者名称

  再次编译,重启系统,并加载驱动,这次不会再打印警告信息了,只打印了我们在入口函数中写的字符串,如下图。

  使用“rmmod shanwuyan”命令卸载驱动,出现错误,如下图。  

  这是我们需要创建文件夹“/lib/modules”,创建后再次卸载驱动,又出现了错误,如下图。

  我们按照错误信息,创建文件夹“/lib/modules/3.0.15”(根据内核版本的不同而不同),再次卸载驱动,成功,打印出来我们想要的字符串信息“shanwuyan_exit”。

如何编写一个简单的Linux驱动(一)的更多相关文章

  1. 如何编写一个简单的Linux驱动(二)——设备操作集file_operations

    前期知识 如何编写一个简单的Linux驱动(一)--驱动的基本框架 前言 在上一篇文章中,我们学习了驱动的基本框架.这一章,我们会在上一章代码的基础上,继续对驱动的框架进行完善.要下载上一篇文章的全部 ...

  2. 如何编写一个简单的Linux驱动(二)——完善设备驱动

    前期知识 1.如何编写一个简单的Linux驱动(一)——驱动的基本框架 2.如何编写一个简单的Linux驱动(二)——设备操作集file_operations 前言 在上一篇文章中,我们编写设备驱动遇 ...

  3. Linux内核分析第三周学习总结:构造一个简单的Linux系统MenuOS

    韩玉琪 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.Linux内 ...

  4. 第三节 构造一个简单的Linux系统MenuOS——20135203齐岳

    第三节 构造一个简单的Linux系统MenuOS By 20135203齐岳 Linux内核源代码 arch/ 支持不同cpu的源代码 Documentations/ 文档存储 init/ 内核启动相 ...

  5. 使用Java编写一个简单的Web的监控系统cpu利用率,cpu温度,总内存大小

    原文:http://www.jb51.net/article/75002.htm 这篇文章主要介绍了使用Java编写一个简单的Web的监控系统的例子,并且将重要信息转为XML通过网页前端显示,非常之实 ...

  6. 20135202闫佳歆--week3 构造一个简单的Linux系统MenuOs--学习笔记

    此为个人学习笔记存档 week 3 构造一个简单的Linux系统MenuOs 复习: 计算机有三个法宝:存储程序计算机,函数调用堆栈,中断 操作系统有两把剑: 1.中断上下文的切换,保存现场和恢复现场 ...

  7. Linux内核分析-构造一个简单的Linux系统MenuOS

    构造一个简单的Linux系统MenuOS linux内核目录结构 arch目录包括了所有和体系结构相关的核心代码.它下面的每一个子目录都代表一种Linux支持的体系结构,例如i386就是Intel C ...

  8. 20135220谈愈敏Blog3_构造一个简单的Linux系统MenuOS

    构造一个简单的Linux系统MenuOS 谈愈敏 原创作品转载请注明出处 <Linux内核分析>MOOC课程 http://mooc.study.163.com/course/USTC-1 ...

  9. 20135327郭皓--Linux内核分析第三周 构造一个简单的Linux系统MenuOS

    Linux内核分析第三周  构造一个简单的Linux系统MenuOS 前提回顾 1.计算机是如何工作的三个法宝 1.存储程序计算机 2.函数调用堆栈 3.中断 2.操作系统的两把宝剑 中断上下文的切换 ...

随机推荐

  1. 微信小程序--家庭记账小账本(三)

    家庭记账小账本打算先通过微信小程序来实现,昨天就去注册了解了一下微信小程序,感觉比较复杂而且困难.如何将ecplise源代码与小程序连接,如何建立数据库等等都困扰了我.查阅网上的资料也没有很大的进展. ...

  2. 在龙芯mips64el平台编译bmon

    bmon 是一个 实时命令行流量监控软件,但作者在github并没有提供mips64el的版本.下面记录一下编译过程.可以在这里下载bmon.v4.0.linux-mips64el.tar.gz. 环 ...

  3. 盘点 35 个 Apache 顶级项目,我拜服了…

    Apache 软件基金会 Apache 软件基金会,全称:Apache Software Foundation,简称:ASF,成立于 1999 年 7 月,是目前世界上最大的最受欢迎的开源软件基金会, ...

  4. angular中阿里矢量图标使用

    <!DOCTYPE html> <html lang="en" ng-app="app"> <head> <meta ...

  5. 洛谷P1036.选数(DFS)

    题目描述 已知 n个整数 x1,x2,-,xn,以及11个整数k(k<n).从n个整数中任选k个整数相加,可分别得到一系列的和.例如当n=4,k=3,4个整数分别为3,7,12,19时,可得全部 ...

  6. Linux域名服务器部署

    环境:vmware workstation          系统:Red Hat7.4 DNS服务部署: IP地址:192.168.100.151        DNS:192.168.100.15 ...

  7. 【Leetcode 做题学算法周刊】第八期

    首发于微信公众号<前端成长记>,写于 2020.05.07 背景 本文记录刷题过程中的整个思考过程,以供参考.主要内容涵盖: 题目分析设想 编写代码验证 查阅他人解法 思考总结 目录 15 ...

  8. 浏览器自动化的一些体会6 增强的webBrowser控件

    这里谈两点 1.支持代理服务器切换 一种方法是修改注册表,不是太好的做法,而且,只能改全局设置,不能改局部(比如只让当前的webBrowser控件使用代理,而其他应用不用代理) 另外一个较好的方法,示 ...

  9. 微信小程序内置组件web-view的缓存问题探讨

    前言:博客或者论坛上面,还有自习亲身经历,发现微信小程序的webview组件的页面缓存问题相当严重,对开发H5的小童鞋来说应该困扰了不少.很多小童鞋硬是抓破脑袋也没有办法解决这个问题,那我们今天就来探 ...

  10. XSS的构造技巧

    XSS的构造技巧 By:Mirror王宇阳 E-mail:2821319009@qq.com 本文为长期持续维护,一旦遇到新的技术技巧将及时更新本文内容 非常的欢迎技术大佬纠正并补充,也欢迎技术同僚讨 ...