linux驱动开发之HelloWorld

最近实习,公司项目搞的是平板开发,而我分配的任务是将驱动加载到内核中。

  准备工作,必要知识了解:加载有两种方式,一种是动态加载和卸载即模块加载,另一种是直接编译进入内核;Linux内核把驱动程序划分为3种类型:字符设备、块设备和网络设备。字符设备和块设备可以像文件一样被访问。它们的主要区别不在于能否seek,而是
在于系统对于这两种类型设备的管理方式。应用程序对于字符设备的每一个I/O操作,都会直接传递给系统内核对应的驱动程序;而应用程序对于块设备的操作,
要经过系统的缓冲区管理,间接传递给驱动程序处理。块设备的这种管理方式是为存储提供优化的;而字符设备的管理方式是为操作提供优化的。至于网络设备,它
在Linux系统中是一类比较特殊的设备它不像字符设备或块设备那样通过对应的设备文件节点去访问,内核也不再通过read和write等调用去访问网络
设备。Linux的网络系统主要是基于BSD
UNIX的套接字机制,在系统和驱动程序之间有专门的数据结构进行数据传输,系统支持对数据发送和数据接收缓存,提供流量控制机制,提供更多的协议支持。

作为小白一个,从最简单的HelloWorld开始。

HelloWorld源程序:

#ifndef MODULE
#define MODULE
#endif

#include
<linux/init.h>
#include
<linux/module.h>

MODULE_LICENCE("GPL");

static int
hello_init(void)  
{   
 
        printk("Hello
world\n");
        return 0;

 
    
static void hello_exit(void)

 
        printk("Goodbye
World\n");
}   
  
 
module_init(hello_init);
module_exit(hello_exit);

此程序非常简单,但需注意的是对于一个驱动程序,有一个入口函数hello_init(),相当于main函数,此处两个头文件问题比较大,后面在说!

建立好源程序之后,需要一个makefile文件,来执行此程序:

obj-m := HelloWorld.o
KDIR  := /lib/modules/$(shell uname
-r)/build
PWD   := $(shell pwd)
default:
   
【tab】make -C $(KDIR) M=$(PWD)
modules
在Helloworld源文件和Makefile文件所在目录下直接make,这是以上一般网上教程的做法,但我这却无法编译通过,报的错误是:无法找到该文件或目录,经过一番努力,发现问题在内核源码树上。

为什么要装内核源码树呢?原因是源码树中有相应的头文件和函数的实现,没有源码树,自己写的应用程序就没办法执行起来。驱动程序中自己写的要包含哪些头文件,都是在源码树下的文件夹里,这个都包含在内核里了。

驱动程序作为一个模块连接到内核模块并运行在内核空间里。引用LDD上的一句话“因为2.6内核的模块要和内核源代码树中的目标文件连接,通过这种方式,
可得到一个更加健壮的模块加载器,但是需要这些目标文件存在于内核目录树中”。这里提到的内核目录树就是我们在运行我们自己构造的模块前,需要在我们的系统中已经配置好内核源代码树,然后在把构造好的目标模块和内核树连接起来再运行。

查看自己的系统里有没有配置好内核树的方法:在/lib/modules/2.6.35-30-generic目录下面,看看有没有build文件夹,如果有的话,说明我们的系统里已经有内核树了,如果没有的话,就需要自己构建一个内核树了。

  构造内核树的步骤如下:

1、安装编译内核所需的软件(要用 make menuconfig命令的话得安装,用make oldconfig的话就不用安装)。


sudo apt-get install build-essential kernel-package libncurses5-dev
fakeroot

2、下载内核源码


apt-cache search linux-source

执行用这条命令系统会提示你安装适合你内核版本的内核源码


 apt-get install Linux-source-2.6.35

执行这条命令就会自动下载并安装适合我系统内核的Linux-source-2.6.35这个内核源码

3、解压内核源码包

进入/usr/src/,能找到linux-source-2.6.35.tar.bz2,用解压命令解压之。


tar jxvf linux-source-2.6.32.tar.bz2

4、拷贝/boot目录下的config-2.6.35-30-generic到刚才解压好的目录下并改名为.config


 sudo cp /boot/config-2.6.35-30-generic
/usr/src/linux-source-2.6.35/.config

5、切换到root用户,进行内核配置


sudo -i
      cd
/usr/src/linux-source-2.6.35
      make
menuconfig

接着会出现一个配置界面,选择最后面的两个选项:
load an Alternate configuration File 和 save an
Alternate configuration File
分别保存并退出,再退出配置环境。
6、编译内核

这个内核的编译要在管理员账号下运行


#cd /usr/src/linux-source-2.6.35
      #make

如果电脑是双核的话可以在make后面加个参数,例如:


make -j4

make的过程时间比较长,我在虚拟机里编译用了2小时左右。。。

再执行


#make bzImage

结束后,可以看到在当前目录下产生一个vmlinux文件。

7、编译模块
在编译模块时候可能会出现如下问题:

(ld: /ubuntu/omnibook/sections.lds: No such file: No such file or directory)


解决方法是:

在/usr/src/linux-source-2.6.35/ubuntu/omnibook/Makefile中的ifeq($(KERNELRELEASE),)的前面增加一句:


 PWD=$(shell pwd)

然后再开始编译模块


#make modules

再执行


make modules_install

命令后在/lib/modules目录下面产生一个目录

后再测试HelloWorld模块:

1、加载模块到内核中:

#insmod ./HelloWorld.ko

2、lsmod 这个命令可以查看当前所有的驱动模块,结果应该显示hello 692 0

#lsmod|grep HelloWorld

3、把hello这个模块移除掉

#rmmod HelloWorld

4、由于printk不会把结果输出到终端中,所以用如下命令查看结果:

dmesg |grep world

编译通过,会产生HelloWorld.ko文件

但出现的另一个问题是可以加载,但无法卸载,待解决,返回的错误是ERROR: Removing ‘HelloWorld‘: Device or
resource busy。

网上资料说,这种加载驱动的做法是临时的,当电脑重启时,驱动会自动卸载,试了一次,果然如此。

linux驱动开发之HelloWorld

时间: 2024-10-25 05:49:11

linux驱动开发之HelloWorld的相关文章

嵌入式Linux驱动开发之helloword心得

自从选择了物联网这个专业,智能XX的字样牵动着每一个学习这个专业的孩子. 大家兴致勃勃的来到了学校,结果一切想象和自己的设想并不一样.想象中的各种智能般梦幻的场景变成了真实的高数/电路/模电等等诸如此类!不知道这个世界什么时候变得如此的浮躁,当大家的一段时间的努力看不到结果的时候就往往会不太感兴趣,模电大家都没听懂,于是大家自我安慰tmd学这玩意到底干什么?本人当初也是这样,可是到了后来接触了单片机,接触了应用电路的设计才知道那些课程那个没用啊!当初还是too young,too simple呀

linux驱动开发之misc类设备介绍

1.什么是misc设备? misc是英文的简称,中文名一般叫做杂项设备/杂散设备. 我们知道大部分的设备都有一个明确的分类class,有一些设备进行分类时不太好分,我们不知道一些设备到底应该分到哪一类设备中去,所以最后将这些不知道分到哪类中的设备给分到misc设备中,也就是分到了杂散类中.像蜂鸣器还有ADC设备都被分到了misc设备杂散类设备中.杂散类设备对应的是一个类的概念.随意进到系统中的/sys/class目录中就会看到一个misc目录,这个misc就是杂散类设备,进入到misc目录中,我

linux驱动开发之GCC问题

最近正在学习驱动开发,进展到字符设备驱动开发阶段. 先不多说,首先把刚看的一篇学习驱动步骤的帖子记录如下: 1. 学会写简单的makefile 2. 编一应用程序,可以用makefile跑起来 3. 学会写驱动的makefile 4. 写一简单char驱动,makefile编译通过,可以insmod, lsmod, rmmod. 在驱动的init函数里打印hello world, insmod后应该能够通过dmesg看到输出. 5. 写一完整驱动, 加上read, write, ioctl, p

linux驱动开发之framebuffer驱动介绍

framebuffer是linux里面的显示设备.在驱动底下如何操作lcd实现图形的显示. 1.什么是framebuffer? (1)首先想一下在裸机中我们是怎么操作LCD的. Soc内部有lcd的控制器,Soc外面有lcd的驱动器,lcd的驱动器连接着lcd的屏幕,Soc的内部还有CPU,外部还有DDR内存.这些设备都参与到了lcd的显示中. 在裸机中我们是怎么搞的呢,lcd的驱动器和lcd的控制器之间通过排线进行链接,连接的接口就是lcd所特有的一个接口.lcd控制器里面是很多和lcd相关的

linux驱动开发之framebuffer应用编程实践(一)

1.framebuffer应用编程 (1)打开设备文件 (2)获取设备信息 宏定义的命令在/linux/fb.h中 不可变信息FSCREENINFO,使用ioctl参数有FBIOGET_FSCREENINFO宏名,表示用ioctl从驱动中获取lcd设备的不变的信息 可变信息VSCREENINFO,使用ioctl参数有FBIOGET_VSCREENINFO宏名,表示用ioctl从驱动中获取lcd设备的可变信息 fb的驱动框架将屏幕的所有硬件信息分为了两类,一类为不可变的,是通过软件不可更改的(比如

(56)Linux驱动开发之二

内核基础 1.linux内核主要是由进程调度.内存管理.虚拟文件系统(字符设备驱动和块设备驱动).网络接口(网络设备驱动)和进程通信5个子系统组成的. 1)进程调度控制系统中的多个进程对CPU的访问,使得多个进程能在CPU中"微观串行,宏观并行"地执行. 2)内存管理的主要作用就是控制多个进程安全的共享主内存区域,当CPU提供内存管理单元时,linux内存管理完成为每个进程进行虚拟内存到物理内存的转换.一般而言,linux的每一个进程享有4GB的内存空间.0~3GB为用户空间,3~4G

linux驱动开发之misc设备与蜂鸣器驱动(一)

1.板载蜂鸣器的驱动测试 我手里有一个BSP,九鼎的Bsp,里面有蜂鸣器的驱动,我们先测试一下好不好用.我们拿到一个BSP时,如果要做或移植蜂鸣器的驱动,首先要确定下这个内核 中究竟有没有蜂鸣器的驱动,我们可以用sourceInsight将内核放进去,搜索buzzer这个文件,看有没有,如果不行,也可以在内核中输入make menuconfig,利用这个配置界面来搜索buzzer英文,看不能找到相应的信息,从而也会知道这个设备在哪个路径下,通过对九鼎的内核进行make menuconfig后,搜

Android驱动开发之Hello实例

Android驱动开发之Hello实例: 驱动部分 modified:   kernel/arch/arm/configs/msm8909-1gb_w100_hd720p-perf_defconfig modified:   kernel/arch/arm/configs/msm8909-1gb_w100_hd720p_defconfig modified:   kernel/drivers/input/misc/Kconfig modified:   kernel/drivers/input/

驱动开发之I2C总线

驱动开发之I2C总线: I2C:数据线和时钟线. 起始信号:时钟线为高电平,数据线由高到低跳变. 结束信号:时钟线为高电平,数据线由低到高跳变. 应答信号:第九个时钟周期,时钟线保持为高电平,数据线为低电平,此时为成功应答. 读写位:站在主机的角度考虑. 0代表主机给从机发送数据. 1代表主机接收从机的数据. 硬件原理: 数据帧的封装:主机给从机发送数据: 起始信号 + 7位从机地址 写位 + 从机给主机应答 + 主机给从机发送8位数据 + 从机给主机应答 ... + 主机给从机发送8位数据 +