由于用的学习材料是《linux设备驱动开发详解(第二版)》,所以linux驱动学习笔记大部分文字描述来自于这本书,学习笔记系列用于自己学习理解的一种查阅和复习方式。

#make config(基于文本的最为传统的配置界面,不推荐使用)
#make menuconfig(基于文本菜单的配置界面)
#make xconfig(要求 QT 被安装)
#make gconfig(要求 GTK+被安装)
在配置 Linux 2.6 内核所使用的 make config、 make menuconfig、 make xconfig 和 make gconfig
这 4 种方式中,最值得推荐的是 make menuconfig,它不依赖于 QT 或 GTK+,且非常直观。

make menuconfig的配置主界面:

下图是Device Drive目录下的Real Time Clock菜单,图片对应的驱动位于source/linux-2.6.32-devkit8500/drivers/rtc下,

跟上图相对应的Kconfig如下,可以发现这个界面中的所有内容都是通过Kconfig文件定义的。

Kconfig:

#
# RTC class/drivers configuration
# config RTC_LIB
tristate menuconfig RTC_CLASS
tristate "Real Time Clock"
default n
depends on !S390
select RTC_LIB
help
Generic RTC class support. If you say yes here, you will
be allowed to plug one or more RTCs to your system. You will
probably want to enable one or more of the interfaces below. This driver can also be built as a module. If so, the module
will be called rtc-core. if RTC_CLASS config RTC_HCTOSYS
bool "Set system time from RTC on startup and resume"
depends on RTC_CLASS = y
default y
help
If you say yes here, the system time (wall clock) will be set using
the value read from a specified RTC device. This is useful to avoid
unnecessary fsck runs at boot time, and to network better. config RTC_HCTOSYS_DEVICE
string "RTC used to set the system time"
depends on RTC_HCTOSYS = y
default "rtc0"
help
The RTC device that will be used to (re)initialize the system
clock, usually rtc0. Initialization is done when the system
starts up, and when it resumes from a low power state. This
device should record time in UTC, since the kernel won't do
timezone correction. The driver for this RTC device must be loaded before late_initcall
functions run, so it must usually be statically linked. This clock should be battery-backed, so that it reads the correct
time when the system boots from a power-off state. Otherwise, your
system will need an external clock source (like an NTP server). If the clock you specify here is not battery backed, it may still
be useful to reinitialize system time when resuming from system
sleep states. Do not specify an RTC here unless it stays powered
during all this system's supported sleep states. config RTC_DEBUG
bool "RTC debug support"
depends on RTC_CLASS = y
help
Say yes here to enable debugging support in the RTC framework
and individual RTC drivers. comment "RTC interfaces" config RTC_INTF_SYSFS
boolean "/sys/class/rtc/rtcN (sysfs)"
depends on SYSFS
default RTC_CLASS
help
Say yes here if you want to use your RTCs using sysfs interfaces,
/sys/class/rtc/rtc0 through /sys/.../rtcN. If unsure, say Y. config RTC_INTF_PROC
boolean "/proc/driver/rtc (procfs for rtc0)"
depends on PROC_FS
default RTC_CLASS
help
Say yes here if you want to use your first RTC through the proc
interface, /proc/driver/rtc. Other RTCs will not be available
through that API. If unsure, say Y. endif # RTC_CLASS

源文件将近千行,这里只截取前面部分进行分析,

Kconfig
内核配置脚本文件的语法比较简单,主要包括如下几个方面。
( 1 )菜单入口 。
大多数的内核配置选项都对应 Kconfig 中的一个菜单入口:
config MODVERSIONS
  bool "Module versioning support"

  help
     Usually, you have to use modules compiled with your kernel.
    Saying Y here makes it ...
“ config” 关键字定义新的配置选项,之后的几行定义了该配置选项的属性。配置选项的属性包括类型、数据范围、输入提示、依赖关系、选择关系及帮助信息和默认值等。
每个配置选项都必须指定类型,类型包括 bool、 tristate、 string、 hex 和 int,其中 tristate 和string 是两种基本的类型,其他类型都基于这两种基本类型。类型定义后可以紧跟输入提示,下面的两段脚本是等价的:
bool "Networking support"

bool
prompt "Networking support"
输入提示的一般格式为:
prompt <prompt> [if <expr>]
其中可选的 if 用来表示该提示的依赖关系。
默认值的格式为:
default <expr> [if <expr>]
一个配置选项可以存在任意多个默认值,这种情况下,只有第一个被定义的值是可用的。如果用户不设置对应的选项,配置选项的值就是默认值。
依赖关系的格式为:
depends on(或者 requires) <expr>
如果定义了多重依赖关系,它们之间用 “ &&” 间隔。依赖关系也可以应用到该菜单中所有的其他选项(同样接受 if 表达式),下面的两段脚本是等价的:
bool "foo" if BAR
default y if BAR

depends on BAR
bool "foo"
default y
选择关系(也称为反向依赖关系)的格式为:
select <symbol> [if <expr>]
A 如果选择了 B,则在 A 被选中的情况下, B 自动被选中。
kbuild Makefile 中的 expr(表达式)定义为:

<expr> ::= <symbol>
    <symbol> '=' <symbol>
   <symbol> '!=' <symbol>
   '(' <expr> ')'
   '!' <expr>
   <expr> '&&' <expr>
   <expr> '||' <expr>
也就是说 expr 是由 symbol、两个 symbol 相等、两个 symbol 不等以及 expr 的赋值、非、与
或运算构成。而 symbol 分为两类,一类是由菜单入口定义配置选项定义的非常数 symbol,另一
类是作为 expr 组成部分的常数 symbol。
数据范围的格式为:
range <symbol> <symbol> [if <expr>]
为 int 和 hex 类型的选项设置可以接受输入值范围,用户只能输入大于等于第一个 symbol,
小于等于第二个 symbol 的值。
帮助信息的格式为:
help(或---help---)
 开始

结束
帮助信息完全靠文本缩进识别结束。“---help---” 和“help” 在作用上没有区别,设计“---help---”
的初衷在于将文件中的配置逻辑与给开发人员的提示分开。
menuconfig 关键字的作用与 config 类似,但它在 config 的基础上要求所有的子选项作为独立
的行显示。
( 2)菜单结构。
菜单入口在菜单树结构中的位置可由两种方法决定。第一种方式为:
menu "Network device support"
 depends on NET
config NETDEVICES
 …
endmenu
所有处于“ menu” 和“ endmenu” 之间的菜单入口都会成为“ Network device support” 的子菜
单。而且,所有子菜单选项都会继承父菜单的依赖关系,比如,“ Network device support” 对“ NET”
的依赖会被加到了配置选项 NETDEVICES 的依赖列表中。
注意 menu 后面跟的“ Network device support”项目仅仅是 1 个菜单,没有对应真实的配置选
项,也不具备 3 种不同的状态。这是它和 config 的区别。
另一种方式是通过分析依赖关系生成菜单结构。如果菜单选项在一定程度上依赖于前面的选
项,它就能成为该选项的子菜单。如果父选项为“ N”,子选项不可见;如果父选项可见,子选项
才能可见。例如:
config MODULES
 bool "Enable loadable module support"
config MODVERSIONS
 bool "Set version information on all module symbols"
 depends on MODULES

comment "module support disabled"
depends on !MODULES
MODVERSIONS 直接依赖 MODULES,只有 MODULES 不为“ n”时,该选项才可见。
除此之外, Kconfig 中还可能使用“ choices … endchoice”、“ comment”、“ if…endif” 这样的语
法结构。其中 “ choices … endchoice” 的结构为:
choice
<choice options>
<choice block>
endchoice"
它定义一个选择群,其接受的选项(choice options)可以是前面描述的任何属性, 例如 LDD6410
的 VGA 输出分辨率可以是 1 024 !768 或者 800 !600,在 drivers/video/samsung/Kconfig 就定义了如
下的 choice:
choice
depends on FB_S3C_VGA
prompt "Select VGA Resolution for S3C Framebuffer"
default FB_S3C_VGA_1024 _768
config FB_S3C_VGA_1024 _768
bool "1 024 *768@60Hz"
---help---
TBA
config FB_S3C_VGA_640_480
bool "640*480@60Hz"
---help---
TBA
endchoic

下面介绍drivers/rtc下的Makefile:

#
# Makefile for RTC class/drivers.
# ifeq ($(CONFIG_RTC_DEBUG),y)
EXTRA_CFLAGS += -DDEBUG
endif obj-$(CONFIG_RTC_LIB) += rtc-lib.o
obj-$(CONFIG_RTC_HCTOSYS) += hctosys.o
obj-$(CONFIG_RTC_CLASS) += rtc-core.o
rtc-core-y := class.o interface.o obj-$(CONFIG_RTC_INTF_ALARM) += alarm.o
obj-$(CONFIG_RTC_INTF_ALARM_DEV) += alarm-dev.o
rtc-core-$(CONFIG_RTC_INTF_DEV) += rtc-dev.o
rtc-core-$(CONFIG_RTC_INTF_PROC) += rtc-proc.o
rtc-core-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o # Keep the list ordered. obj-$(CONFIG_RTC_DRV_AB3100) += rtc-ab3100.o
obj-$(CONFIG_RTC_DRV_AT32AP700X)+= rtc-at32ap700x.o
obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o
obj-$(CONFIG_RTC_DRV_AT91SAM9) += rtc-at91sam9.o
obj-$(CONFIG_RTC_DRV_AU1XXX) += rtc-au1xxx.o
obj-$(CONFIG_RTC_DRV_BFIN) += rtc-bfin.o
obj-$(CONFIG_RTC_DRV_BQ4802) += rtc-bq4802.o
obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o
obj-$(CONFIG_RTC_DRV_COH901331) += rtc-coh901331.o
obj-$(CONFIG_RTC_DRV_DM355EVM) += rtc-dm355evm.o
obj-$(CONFIG_RTC_DRV_DS1216) += rtc-ds1216.o
obj-$(CONFIG_RTC_DRV_DS1286) += rtc-ds1286.o
obj-$(CONFIG_RTC_DRV_DS1302) += rtc-ds1302.o
obj-$(CONFIG_RTC_DRV_DS1305) += rtc-ds1305.o
obj-$(CONFIG_RTC_DRV_DS1307) += rtc-ds1307.o
obj-$(CONFIG_RTC_DRV_DS1374) += rtc-ds1374.o
obj-$(CONFIG_RTC_DRV_DS1390) += rtc-ds1390.o
obj-$(CONFIG_RTC_DRV_DS1511) += rtc-ds1511.o
obj-$(CONFIG_RTC_DRV_DS1553) += rtc-ds1553.o
obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o
obj-$(CONFIG_RTC_DRV_DS1742) += rtc-ds1742.o
obj-$(CONFIG_RTC_DRV_DS3234) += rtc-ds3234.o
obj-$(CONFIG_RTC_DRV_EFI) += rtc-efi.o
obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o
obj-$(CONFIG_RTC_DRV_FM3130) += rtc-fm3130.o
obj-$(CONFIG_RTC_DRV_GENERIC) += rtc-generic.o
obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o
obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o
obj-$(CONFIG_RTC_DRV_M41T94) += rtc-m41t94.o
obj-$(CONFIG_RTC_DRV_M48T35) += rtc-m48t35.o
obj-$(CONFIG_RTC_DRV_M48T59) += rtc-m48t59.o
obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o
obj-$(CONFIG_RTC_MXC) += rtc-mxc.o
obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o
obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o
obj-$(CONFIG_RTC_DRV_MSM6242) += rtc-msm6242.o
obj-$(CONFIG_RTC_DRV_MV) += rtc-mv.o
obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o
obj-$(CONFIG_RTC_DRV_PCAP) += rtc-pcap.o
obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o
obj-$(CONFIG_RTC_DRV_PCF8583) += rtc-pcf8583.o
obj-$(CONFIG_RTC_DRV_PCF2123) += rtc-pcf2123.o
obj-$(CONFIG_RTC_DRV_PCF50633) += rtc-pcf50633.o
obj-$(CONFIG_RTC_DRV_PL030) += rtc-pl030.o
obj-$(CONFIG_RTC_DRV_PL031) += rtc-pl031.o
obj-$(CONFIG_RTC_DRV_PS3) += rtc-ps3.o
obj-$(CONFIG_RTC_DRV_PXA) += rtc-pxa.o
obj-$(CONFIG_RTC_DRV_R9701) += rtc-r9701.o
obj-$(CONFIG_RTC_DRV_RP5C01) += rtc-rp5c01.o
obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o
obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o
obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o
obj-$(CONFIG_RTC_DRV_RX8025) += rtc-rx8025.o
obj-$(CONFIG_RTC_DRV_RX8581) += rtc-rx8581.o
obj-$(CONFIG_RTC_DRV_S35390A) += rtc-s35390a.o
obj-$(CONFIG_RTC_DRV_S3C) += rtc-s3c.o
obj-$(CONFIG_RTC_DRV_SA1100) += rtc-sa1100.o
obj-$(CONFIG_RTC_DRV_SH) += rtc-sh.o
obj-$(CONFIG_RTC_DRV_STARFIRE) += rtc-starfire.o
obj-$(CONFIG_RTC_DRV_STK17TA8) += rtc-stk17ta8.o
obj-$(CONFIG_RTC_DRV_STMP) += rtc-stmp3xxx.o
obj-$(CONFIG_RTC_DRV_SUN4V) += rtc-sun4v.o
obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o
obj-$(CONFIG_RTC_DRV_TWL4030) += rtc-twl.o
obj-$(CONFIG_RTC_DRV_TX4939) += rtc-tx4939.o
obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o
obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o
obj-$(CONFIG_RTC_DRV_WM831X) += rtc-wm831x.o
obj-$(CONFIG_RTC_DRV_WM8350) += rtc-wm8350.o
obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o

这里主要对内核源代码各级子目录中的 kbuild( 内核的编译系统) Makefile 进行简单介绍,这部分是内核模块或设备驱动的开发者最常接触到的。
Makefile 的语法包括如下几个方面。
( 1 )目标定义。
目标定义就是用来定义哪些内容要作为模块编译,哪些要编译并连接进内核。
例如:
obj -y += foo.o
表示要由 foo.c 或者 foo.s 文件编译得到 foo.o 并连接进内核,而 obj-m 则表示该文件要作为模
块编译。除了 y、 m 以外的 obj-x 形式的目标都不会被编译。
而更常见的做法是根据.config 文件的 CONFIG_变量来决定文件的编译方式,如:
obj -$(CONFIG_ISDN) += isdn.o
obj -$(CONFIG_ISDN_PPP_BSDCOMP) += isdn_bsdcomp.o
除了 obj-形式的目标以外,还有 lib-y library 库, hostprogs-y 主机程序等目标,但是基本都应
用在特定的目录和场合下。
( 2)多文件模块的定义。
最简单的 Makefile 如上一节一句话的形式就够了,如果一个模块由多个文件组成,会稍微复
杂一些,这时候应采用模块名加-y 或-objs 后缀的形式来定义模块的组成文件。如以下例子:
#
# Makefile for the linux ext2-filesystem routines.
#
obj -$(CONFIG_EXT2 _FS) += ext2.o
ext2-y := balloc.o dir.o file.o fsync.o ialloc.o inode.o \
   ioctl.o namei.o super.o symlink.o
ext2-$(CONFIG_EXT2 _FS_XATTR) += xattr.o xattr_user.o xattr_trusted.o
ext2-$(CONFIG_EXT2 _FS_POSIX_ACL) += acl.o
ext2-$(CONFIG_EXT2 _FS_SECURITY) += xattr_security.o
ext2-$(CONFIG_EXT2 _FS_XIP) += xip.o
模块的名字为 ext2,由 balloc.o、 dir.o、 file.o 等多个目标文件最终链接生成 ext2.o 直至 ext2.ko
文件,并且是否包括 xattr.o、 acl.o 等则取决于内核配置文件的配置情况,例如, 如果 CONFIG_
EXT2
_FS_POSIX_ACL 被选择,则编译 acl.c 得到 acl.o 并最终链接进 ext2。

( 3)目录层次的迭代。
如下例:
obj -$(CONFIG_EXT2 _FS) += ext2/
当 CONFIG_EXT2_FS 的值为 y 或 m 时, kbuild 将会把 ext2 目录列入向下迭代的目标中。

linux 驱动学习笔记01--Linux 内核的编译的更多相关文章

  1. 小松之LINUX 驱动学习笔记(二)

    这两天一直在看字符驱动那块,后来从网上找啦几个例子,自己编译啦下,安装啥的都挺正常,就是用测试程序测试的时候总出问题,现在找到一个能测试的代码,自己先看看和原来的那个代码有啥不同,后面会继续更新,说下 ...

  2. linux 驱动学习笔记03--Linux 内核的引导

    如图所示为 X86 PC 上从上电/复位到运行 Linux 用户空间初始进程的流程.在进入与 Linux相关代码之间,会经历如下阶段. ( 1 ) 当系统上电或复位时, CPU 会将 PC 指针赋值为 ...

  3. linux 驱动学习笔记02--应用实例:在内核中新增驱动代码目录和子目录

    下面来看一个综合实例,假设我们要在内核源代码 drivers 目录下为 ARM 体系结构新增如下用于 test driver 的树型目录:| --test  | -- cpu  | -- cpu.c ...

  4. Linux Basic学习笔记01

    介绍课程: 中级: 初级:系统基础 中级:系统管理.服务安全及服务管理.Shell脚本: 高级: MySQL数据库: cache & storage 集群: Cluster lb: 4laye ...

  5. Linux 驱动学习笔记05--字符驱动实例,实现一个共享内存设备的驱动

    断断续续学驱动,好不容易有空,做了段字符驱动的例子.主要还是跟书上学习在此记录下来,以后说不定能回过头来温故知新. 首先上驱动源码 gmem.c: /************************* ...

  6. 小松之LINUX 驱动学习笔记(一)

    本篇主要是讲解驱动开发的基础知识以及一些环境配置方面的问题. 下面是一个hello world的简单的模块代码,很简单./*********************** 模块的简单例子* author ...

  7. linux 驱动学习笔记04--简单驱动

    首先贴代码helloworld.c和Makefile /************************************************************************ ...

  8. linux驱动学习笔记---实现中断下半部以及驱动编写规范(七)【转】

    转自:https://blog.csdn.net/weixin_42471952/article/details/81609141 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协 ...

  9. 小松之LINUX驱动学习笔记之模块间函数调用通讯

    1. 符号导出函数 EXPORT_SYMBOL() EXPORT_SYMBOL标签内定义的函数对全部内核代码公开,不用修改内核代码就可以在您的内核模块中直接调用. EXPORT_SYMBOL_GPL( ...

随机推荐

  1. Python开发库

    在我多年的 Python 编程经历以及在 Github 上的探索漫游过程中,我发掘到一些很不错的 Python 开发包,这些包大大简化了开发过程,而本文就是为了向大家推荐这些开发包. 请注意我特别排除 ...

  2. PAT (Basic Level) Practise:1016. 部分A+B

    [题目链接] 正整数A的“DA(为1位整数)部分”定义为由A中所有DA组成的新整数PA.例如:给定A = 3862767,DA = 6,则A的“6部分”PA是66,因为A中有2个6. 现给定A.DA. ...

  3. (实用篇)jQuery二级联动代码

    jquery二级联动城市代码 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "htt ...

  4. 设置Android studio内容的主题

    下载主题Jar包 http://color-themes.com/?view=theme&id=563a1a6e80b4acf11273ae76 导入主题: File->Import s ...

  5. hdu4690 EBCDIC ——水题,考耐心

    link:http://acm.hdu.edu.cn/showproblem.php?pid=4690 考的是耐心何细心啊,用map把两个表格映射一下就行~ #include <iostream ...

  6. oracle 常用语法

    一.ORACLE的启动和关闭1.在单机环境下要想启动或关闭ORACLE系统必须首先切换到ORACLE用户,如下su - oraclea.启动ORACLE系统oracle>svrmgrlSVRMG ...

  7. [转]MySQL服务器上添加一个允许远程访问的用户

    MySQL默认是没有开启远程控制的,必须添加远程访问的用户,如果是安装版的话,从MySQL提供的控制台进入. 用root用户登陆,然后: grant all privileges on 数据库名.表名 ...

  8. Window环境下 Git 下载Android源码

    1.需要的工具 git.vpn代理 2. 设置git代理(Google source 无法下载,git设置代理) git config --global http.proxy "localh ...

  9. CSS 类选择器

    在 CSS 中,类选择器以一个点号显示: .center {text-align: center} 在上面的例子中,所有拥有 center 类的 HTML 元素均为居中. 在下面的 HTML 代码中, ...

  10. Spring Boot中使用Swagger2构建强大的RESTful API文档

    由于Spring Boot能够快速开发.便捷部署等特性,相信有很大一部分Spring Boot的用户会用来构建RESTful API.而我们构建RESTful API的目的通常都是由于多终端的原因,这 ...