【学习笔记】linux
Linux三大设备驱动shell
IO的传输过程是以字符为单位的,没有缓冲。好比I2C,SPI都是字符设备ubuntu
IO传输过程当中是以块为单位的。跟存储相关的,都属于块设备,好比:tf卡bash
与前两个不同,是以socket套接字来访问的。网络
其中,理解和掌握字符设备驱动的概念最重要,由于在工做中咱们遇到大部分都是字符设备socket
(1)头文件ide
(2)驱动模块的入口和出口学习
(3)声明信息命令行
(4)功能实现code
第一步,包含头文件
第二步,驱动模块的入口和出口
module_init();
module_exit();
第三步,生命模块具备开源许可证
MODULE_LICENSE("GPL");
第四步,功能的实现
简单的helloworld驱动程序编写
/两个必要的头文件 #include <linux/init.h> #include <linux/module.h> //内核加载的时候打印hello world,内核模块卸载的时候打印bye bye static int hello_init(void){ printk("hello world\n"); //内核里不能使用c语言库,因此不能用printf return 0; } static void hello_exit(void){ printk("bye bye\n"); } //入口和出口 module_init(hello_init); module_exit(hello_exit); //声明许可证 MODULE_LICENSE("GPL");
把驱动编译成模块,而后使用命令把驱动加载到内核里面。
步骤
一、编译成模块
(1)先写一个makefile
在linux下
touch Makefile #建立Makefile文件
obj-m +=HelloWorld.o #obj-m 意为把驱动编译为模块 KDIR:={core_path} #PATH根据开发板内核路径来填写 PWD?=$(shell pwd) #自动获取当前位置路径 all: make -C $(KDIR) M=$(PWD) modules #切换到内核路径,用make把代码编译成模块
(2)编译驱动
编译驱动以前须要注意的问题:
内核源码必定要编译经过
编译驱动用的内核源码必定要和开发板上运行的内核镜像是同一套
看一下开发代码的ubuntu环境是否是arm,若是不是,要改为arm环境
查看环境的 方法
在内核源码的目录下输入
make menuconfig #显示系统环境 #左上角若是显示是X86,而不是arm,则输入 export ARCH=arm #改成arm环境
为了以防万一,编译前,先命令行输入两行代码,设置环境和编译器
export ARCH=arm export CROSS_COMPILE={编译器名称} #能够直接输入arm查看 #若是查看到:arm-linux-gnueabihf-gcc-4.9.4
编译成功后就能够看到 ko 文件了,这个 ko 文件就是编译好的驱动。
在开发板上加载驱动用insmod
insmod HelloWorld.ko
查看加载的模块,使用lsmod命令
lsmod
卸载驱动模块
rmmod HelloWorld #注意这里没有后缀
卸载时,若是提示没有相应的目录,直接在对应的目录下建立就能够了
直接把驱动编译到内核。
在下面有实际的例子。
若是芯片的内核不支持设备的驱动,那么就须要把这个驱动移植到内核。
移植驱动须要驱动源码和makefile。
(1)先去内核源码搜索,若是有的话,能够直接选择这个驱动,而后直接使用。
(2)假如没有这个驱动,则许哟啊本身编译一个驱动,而后加载到内核里边去运行。
一、如何进入make menuconfig图形化配置
首先进入到内核源码的路径下,而后输入make menuconfig 便可打开这个界面。
二、make menuconfig图形化界面的操做
(1)搜索功能
输入“/”便可弹出搜索界面
(2)配置驱动状态
把驱动编译成模块(用[ M ]来表示)
把驱动编译到内核里(用[ * ]来表示)
不编译(用[ ]来表示)
可使用“空格”键来配置这三种不一样的状态
(3)如何退出
分为保存退出和不保存退出,按照提示选择便可
(4)和make menuconfig 有关的文件
Makefile:里边是编译规则,高速咱们在make的时候须要如何编译(至关于菜的作法)
Kconfig:内核配置的选项(至关于服务员给的菜单)
.config:配置完内核之后生成的配置选项(至关于我门勾选的菜单)
(5)make menuconfig会读取不一样环境目录下的Kconfig文件
会读取Arch/$ARCH/目录下(目录下有不少不一样的环境文件夹)的Kconfig文件(选择不一样的环境,和export ARCH=arm效果相似)。
/arch/arm/configs 下面有不少配置文件(至关于特点菜,默认配置,在不知道如何配置的时候能够按照这个来),若是移植内核的时候,配置文件太多,就能够把这个文件夹下面的配置复制成.config里边(即默认系统的配置)【复制用cp命令】
(6)为何要复制成.config,而不是其余名字
由于内核会默认读取Linux内核根目录下的.config做为默认的配置选项,因此不能够更名字
(7)若是复制的默认配置.config不知足咱们的要求,如何解决
直接输入make menuconfig,进入Kconfig配置界面,来进行修改配置,保存退出,配置会自动更新到.config里面。
(8)配置文件选项怎样和Makefile文件创建联系
当make menuconfig保存退出之后,Linux会将全部的配置选项以宏定义的形式保存在include/generated/下面的autoconf.h头文件中。
#例子 source "drivers/redled/Kconfig" config LED_4412 tristate "Led Support for GPIO Led" depends on LEDS_CLASS help This option enable support for led #解读 source "drivers/redled/Kconfig"#会让config菜单里边包含drivers/redled/这个路径下的驱动文件,方便咱们对菜单进行管理 config LED_4412 #配置选项的名称,全名是CONFIG_LED_4412,这里作了一些省略 tristate "Led Support for GPIO Led" #tristate表示驱动的状态:1.把驱动编译成模块 2.把驱动编译到内核 3.不编译。与之对用的还有bool关键字:表示编译到内核,和不编译两种状态。 #"Led Support for GPIO Led"是make menuconfig里边的某个菜单的名字 depends on LEDS_CLASS # A depends on B表示只有在选择B的时候才能够选择A,即A依赖于B。 #好比想要去掉LED相关的驱动,咱们虽然能够直接改.config文件,可是不推荐这样作。由于若是有依赖项的话,直接改.config文件是不成功的。 #select:反向依赖,该选项被选中时,后面的定义也会被选中。 help This option enable support for led #显示帮助信息
把HelloWorld驱动编译到内核。
(1)首先进入到内核源码的目录下(内核根目录)
(2)把HelloWorld.c驱动,复制到drivers/char/hello文件夹【char通常就是放字符设备的文件夹,hello文件夹使用mkdir命令建立】
(3)写Kconfig文件
mkdir hello #建立hello文件夹 cd hello/ #切换到hello文件夹 cp /home/pyma/HelloWorld.c #把驱动文件复制到hello文件夹中 touch Kconfig #建立一个Kconfig文件 vi Kconfig #打开Kconfig进行编辑 #写程序 config HELLO #起个名字叫HELLO tristate "hello world" #选择三种状态的方式,并把菜单名字命名为hello world #过于简单没有依赖,不用写 help hello help #帮助信息为hello help
保存退出
(4)写Makefile文件
touch Makefile #建立Makefile文件夹 vi Makefile #打开Makefile编辑 #写程序 obj-$(CONFIG_HELLO)+=HelloWorld.o
CONFIG_HELLO这个变量名字来源:是刚刚在Kconfig中命名的,可是Kconfig中至关于省略了CONFIG_,在这里至关于补上,即:makfile中要写全名。
$(CONFIG_HELLO)变量做用:会根据咱们选择的状态来改变,(1)若是是选择把它编译到内核中,那么表示-y(即:obj-y)(2)若是选择编译成模块,那么它表示-m(即:obj-m)
到此,全部的文件都准备完成,接下来须要
(5)把hello驱动配置包,包含进去
须要修改上一级目录的Makefile和Kconfig
cd .. #返回上一级目录,即路径.../char/ vi Makefile #修改Makefile,若是没有则须要本身建立,本身写 #写程序,在首行添加如下代码 obj-y +=hello/ #这里注意hello是个文件夹,所以最后要加"/" ... #原有的makefile代码 #保存退出 vi Kconfig #打开Kconfig文件,把刚才写的驱动代码的Konfig包含进config菜单界面中 #在前面相应位置添加好Kconfig的路径 source "drivers/char/hello/Kconfig" #Kconfig相对路径 #保存退出
(6)回到内核根目录下,打开菜单,选择不一样状态
make menuconfig #进入配置菜单
在界面中选择Device Drivers选项进入
再进入到Character devices目录下
就会看到新添加的hello world驱动菜单项(名字是在Kconfig中命名的)
用空格键选择状态:
(7)编译进内核,选择<*>(编译到内核)
保存退出,而后确保配置正确与否
打开.config文件,搜索
vi .config #打开配置文件 #搜索HELLO #搜索命令 /HELLO 若是出现CONFIG_HELLO=y是编译到内核中了,m是编译成模块 这里能够看出,若是没有依赖项,也能够直接改.config文件的CONFIG_HELLO项
(8)编译前更改
这时还不能立马编译,由于编译会调用默认的的编译配置,须要作相应修改
这里为了理解的透彻,先看一下编译脚本:vi create.sh
#!/bin/bash export ARCH=arm ... make imx_v7_defconfig #这个就是内核的默认用法,意思是在编译的时候会本身去找arch/arm/configs下面的imx_v7_defconfig配置文件,做为.config来编译内核。 ...
虽然前面咱们改了.config文件,但不是直接用它来编译的,而是使用默认的arch/arm/configs/imx_v7_defconfig文件来编译的。
所以还要再改一下
make distclean,清除全部的编译文件,也删掉了.config文件
把缺省配置复制到.config中
cp arch/arm/configs/imx_v7_defconfig .config
再进行第(6)步操做(这里感受有点乱,步骤重复了?(6)、(7)两步能够不要)
(9)键修改后的.config复制回默认编译菜单里
cd arch/arm/configs/ #切换到默认配置目录 mv imx_v7_defconfig imx_v7_defconfig_noHELLO #更改默认配置的名字 cp ../../../.config imx_v7_defconfig #把修改好的配置,更改成默认的名称
(10)运行脚本,等待编译完成
./create.sh
(11)检验是否编译成功
方法一:烧写到开发板上,运行看看有没有加载驱动
cp arch/arm/boot/zImage /home/pyma/ #把镜像复制到好找的位置
方法二:进入到建立的驱动目录,查看有没有把.c文件编译成.o文件
cd drivers/char/hello/ ls
若是没有相应的.o文件,则说明编译出错,检查Makefile和其余文件。
修改好,再回到根目录编译
.o文件检查没有问题后,再回到根目录检查是否有zImage镜像
ls arch/arm/boot/