linux内核构建与编译

linux 内核开发基础

  1. linux的构成

    linux内核构建与编译_第1张图片

    • linux 由用户空间、内核空间两个部分来组成。
  2. linux 下体系结构、工作模式

    共有7种工作模式:

    1. 用户模式(usr)
    2. 快速中断(fiq)
    3. 外部中断(irq)
    4. 管理模式(svc)
    5. 数据访问终止(abt)
    6. 系统模式(sys)
    7. 未定义指令异常(und)
  3. linux内核的构成

linux内核构建与编译_第2张图片

  • Arch: arm架构(与cpu相关的内容)

  • Device Drivers: 设备驱动,完成对底层硬件的驱动

  • Memory Management: 地址映射、内存分配、内存空间管理

  • Network Stack: 网络协议栈,TCP、UDP、HTTP等多种网络通信协议

  • Process Management: 进程管理、调度、通信

  • Virtual File System: 虚拟文件系统

linux内核构建与编译_第3张图片
不同的文件系统有不同的访问接口。但是通过虚拟文件系统,就能够统一一个使用接口。

  • System Call Interface: 系统调用接口,系统与用户的合法合规对接点。

linux 内核源代码分析

  1. 目录结构

linux内核构建与编译_第4张图片

  • arch目录:内核所支持的每种CPU体系,在该目录下都有对应的子目录。每个CPU的子目录又划分为boot、mm、kernel等子目录,分别包含控制系统引导、内存管理、系统调用等。(下图为arch文件夹

    linux内核构建与编译_第5张图片

    在arch的子目录下,我们可以看到这里包含了众多的处理器对应的架构文件,比如arm架构的处理器应用的都是arm文件夹下的体系文件。(下图为arm文件夹

    linux内核构建与编译_第6张图片

    • mach-xxxx:代表的是一个开发板的文件,是三星审核通过,收录下来的公开文件集合。如图我们用到的是s3c2440的芯片,那么这里我们打开mach-s3c2440的文件夹查阅下。

      linux内核构建与编译_第7张图片

      可以看到,在这个系列的芯片中,我们可能涉及的东西,比如时钟clock、终端dma、外部中断irq等。同时我们可以看到又有一个分支:mach-mini2440.c,刚好就对应了我们使用的开发板!!!

  • block目录:部分块设备驱动程序(块设备即存储设备)

linux内核构建与编译_第8张图片

  • crypto目录:加密、压缩、CRC校验算法

  • documentation目录:内核的文档

  • drivers目录:设备驱动程序

  • fs目录:存放各种文件系统的实现代码,每个子目录对应一种文件系统的实现,共用的源程序用于实现虚拟文件系统vfs。

    ||–devpts /* /dev/pts虚拟文件系统 */

    ||–ext2 /* 第二扩展文件系统 */

    ||–fat /* Ms的fat32文件系统 */

    ||–isofs /* ISO9660光盘CD-rom上的文件系统 */

linux内核构建与编译_第9张图片

 linux支持的文件系统很多,可以查阅fs文件夹,上图可看到常用的:nfs、fat、ext3等等。
  • include 目录:内核所依赖的头文件。与平台无关的头文件在include/linux 子目录下,与平台相关的头文件则存放在相应的子目录中。(include文件夹)

linux内核构建与编译_第10张图片

  • lib 目录:库文件代码

  • mm 目录:mm目录中的文件用于实现内存管理中与体系结构无关的部分

  • net 目录:网络协议的实现代码

linux内核构建与编译_第11张图片

linux内核构建与编译_第12张图片

  • samples 目录:一些内核编程的范例
  • script 目录:配置内核的脚本
  • security 目录:SElinux的模块
  • sound 目录:音频设备的驱动程序
  • usr 目录:cpio命令的实现(用于处理内核与根文件系统的命令)
  • virt 目录:内核虚拟机

$$ 我们重点在关注的是arch 和 drivers两个目录

linux内核配置与编译(linux可定制特点)

A. 清除临时文件、中间文件和配置的文件

1. **make clean**	      {remove most generated files but keep the config}
2. **make mrproper**  {remove all generated files + config files}
3. **make distclean**   {mrproper + remove editor backup and patch files}

B. 确定目标系统的软硬件配置情况,比如CPU的型号、网卡型号,所需支持的网络协议等。

C. 使用如下命令之一配置内核:

make config:基于文本模式的交互式配置

make menuconfig: 基于文本模式的菜单选项型配置(推荐)

make oldconfig:基于已有的配置文件来询问新增的配置选项。

make xconfig: 图形化的配置

内核配置参考.doc

https://wenku.baidu.com/view/c8717f05b52acfc789ebc9b9.html

D. 内核配置选项:

​ 对于每一个配置选项,用户可以回答"y"、“m"或"n”。其中"y"表示将相应特性的支持或设备驱动程序编译进内核;"m"表示将相应特性的支持或设备驱动程序编译成可加载模块,在需要时,可由系统或用户自行加入到内核中去;"n"表示内核不提供相应特性或驱动程序的支持。只有<>才能选择M

\1. General setup(通用选项)

[*]Prompt for development and/or incomplete code/drivers,设置界面中显示还在开发或者还没有完成的代码与驱动,最好选上,许多设备都需要它才能配置。

[ ]Cross-compiler tool prefix,交叉编译工具前缀,如果你要使用交叉编译工具的话输入相关前缀。默认不使用。嵌入式linux更不需要。

[ ]Local version - append to kernel release,自定义版本,也就是uname -r可以看到的版本,可以自行修改,没多大意义。

[ ]Automatically append version information to the version string,自动生成版本信息。这个选项会自动探测你的内核并且生成相应的版本,使之不会和原先的重复。这需要Perl的支持。由于在编译的命令make-kpkg 中我们会加入- – append-to-version 选项来生成自定义版本,所以这里选N。

Kernel compression mode (LZMA),选择压缩方式。

[ ]Support for paging of anonymous memory (swap),交换分区支持,也就是虚拟内存支持,嵌入式不需要。

[*]System V IPC,为进程提供通信机制,这将使系统中各进程间有交换信息与保持同步的能力。有些程序只有在选Y的情况下才能运行,所以不用考虑,这里一定要选。

[*]POSIX Message Queues,这是POSIX的消息队列,它同样是一种IPC(进程间通讯)。建议你最好将它选上。

[*]BSD Process Accounting,允许进程访问内核,将账户信息写入文件中,主要包括进程的创建时间/创建者/内存占用等信息。可以选上,无所谓。

[*]BSD Process Accounting version 3 file format,选用的话统计信息将会以新的格式(V3)写入,注意这个格式和以前的 v0/v1/v2 格式不兼容,选不选无所谓。

[ ]Export task/process statistics through netlink (EXPERIMENTAL),通过通用的网络输出工作/进程的相应数据,和BSD不同的是,这些数据在进程运行的时候就可以通过相关命令访问。和BSD类似,数据将在进程结束时送入用户空间。如果不清楚,选N(实验阶段功能,下同)。

[ ]Auditing support,审计功能,某些内核模块需要它(SELINUX),如果不知道,不用选。

[ ]RCU Subsystem,一个高性能的锁机制RCU 子系统,不懂不了解,按默认就行。

[ ]Kernel .config support,将.config配置信息保存在内核中,选上它及它的子项使得其它用户能从/proc/ config.gz中得到内核的配置,选上,重新配置内核时可以利用已有配置

Enable access to .config through /proc/config.gz,上一项的子项,可以通过/proc/ config.gz访问.config配置,上一个选的话,建议选上。

(16)Kernel log buffer size (16 => 64KB, 17 => 128KB) ,内核日志缓存的大小,使用默认值即可。12 => 4 KB,13 => 8 KB,14 => 16 KB单处理器,15 => 32 KB多处理器,16 => 64 KB,17 => 128 KB。

[ ]Control Group support(有子项),使用默认即可,不清楚可以不选。

Example debug cgroup subsystem,cgroup子系统调试例子

Namespace cgroup subsystem,cgroup子系统命名空间

Device controller for cgroups,cgroups设备控制器

Cpuset support,只有含有大量CPU(大于16个)的SMP系统或NUMA(非一致内存访问)系统才需要它。

[ ]enable deprecated sysfs features to support old userspace tools,在某些文件系统上(比如debugfs)提供从内核空间向用户空间传递大量数据的接口,一般不选。

[ ]Kernel->user space relay support (formerly relayfs),内核系统区和用户区进行传递通讯的支持,这个选项在特定文件系统(relayfs)中提供数据接口支持,它可以支持从内核空间到用户空间的大批量数据传递的支持。不清楚可以不选。

[ ]Namespaces support,(有子项)命名空间支持,允许服务器为不同的用户信息提供不同的用户名空间服务,不清楚可以不选。

[ ]Initial RAM filesystem and RAM disk (initramfs/initrd) support,初始RAM的文件和RAM磁盘( initramfs /initrd)支持(如果要采用initrd启动则要选择,否则可以不选),不需要,不用选。嵌入式linux一般不选。

[ ]Optimize for size,优化大小,-Os代替-O2参数,可能会有二进制错误问题,一般不选。

(0)Default panic timeout,添0即可。

[*]Configure standard kernel features (for small systems),特殊内核用到,可以不选,嵌入式linux则必选。

[ ]Enable the Anonymous Shared Memory Subsystem,启用匿名共享内存子系统,不清楚可以不选。

[ ]Enable AIO support,支持AIO(Asynchronous I/O 异步事件非阻塞I/O),(包含aio.h, aio_read,向内核发出读命令,aio_write向内核写命令,详细见‘AIO介绍‘文档),AIO机制为服务器端高并发应用程序提供了一种性能优化的手段。加大了系统吞吐量,所以一般用于大型服务器,一般不用选。

[ ]Kernel Performance Events And Counters(有子项),不清楚,不选。

[*]Enable VM event counters for /proc/vmstat,允许在/proc/vmstat中包含虚拟内存事件记数器。

[*]Enable SLUB debugging support,支持SLUB内存分配管理器调试,

[ ]Disable heap randomization,禁用随即head,选不选均可。

Choose SLAB allocator (SLUB (Unqueued Allocator)) —>, 选择内存分配管理器,强烈推荐使用SLUB。

[ ]Profiling support,剖面支持,用一个工具来扫描和计算计算机的剖面图,支持系统测评,一般开发人员使用,不选。

[ ]Kprobes,调试人员使用,不选。

GCOV-based kernel profiling —>(有子项),默认即可。

\2. Enable loadable module support(可加载模块)

[ ]Forced module loading, 强行加载模块,不建议选。

[*]Module unloading,支持模块卸载,必须选上。

[ ]Forced module unloading,强行卸载模块,即使内核认为这样并不安全,也就是说你可以把正在使用中的模快卸载掉。如果你不是内核开发人员或者骨灰级的玩家,不建议选。

[ ]Module versioning suppor,这个功能可以让你使用其它版本的内核模块,除非特殊需要,一般不选。

[ ]Source checksum for all modules,这个功能是为了防止更改了内核模块的代码但忘记更改版本号而造成版本冲突,现在很少使用,不选。

\3. Enable the block layer(块设备层)

[*]Support for large (2TB+) block devices and files,仅在使用大于2TB的块设备时需要

[*]Block layer SG support v4,通用SCSI设备第四版支持。

[*]Block layer data integrity support,块设备数据完整性支持。

[*]IO Schedulers —>(有子项),IO调度器

[ ]Anticipatory I/O scheduler,抢先式I/O调度器,大多数块设备只有一个物理查找磁头(例如一个单独的SATA硬盘),将多个随机的小写入流合并成一个大写入流,用写入延时换取最大的写入吞吐量.适用于大多数环境,特别是写入较多的环境(比如文件服务器)

[ ]Deadline I/O scheduler,期限式I/O调度器,轮询的调度器,简洁小巧,提供了最小的读取延迟和尚佳的吞吐量,特别适合于读取较多的环境(比如数据库)。

[ ]CFQ I/O scheduler,使用QoS策略为所有任务分配等量的带宽,避免进程被饿死并实现了较低的延迟,可以认为是上述两种调度器的折中.适用于有大量进程的多用户系统CFQ调度器尝试为所有进程提供相同的带宽。它将提供平等的工作环境,对于桌面系统很合适。

Default I/O scheduler (CFQ) —>默认IO调度器有上面三个IO调度器:抢先式是传统的,它的原理是一有响应,就优先考虑调度。如果你的硬盘此时在运行一项工作,它也会暂停下来先响应用户。期限式则是:所有的工作都有最终期限,在这之前必须完成。当用户有响应时,它会根据自己的工作能否完成,来决定是否响应用户。CFQ则是平均分配资源,不管你的响应多急,也不管它的工作量是多少,它都是平均分配,一视同仁的。

\4. System Type(arm 占用配置,一般是厂家提供,与第7项代替了原有的Processor type and features)

\5. [ ]FIQ Mode Serial Debugger,一般不选。

\6. Bus support(总线支持)

PCI support,PCI总线支持,主板上最长用的插槽,最好选上,arm linux可以不选,arm一般没有PCI总线。

PCCard (PCMCIA/CardBus) support,一般笔记本有这种插槽,笔记本选上,arm linux 不选。

\7. Kernel Features(内核特征)

[ ] Tickless System (Dynamic Ticks),非固定平率系统,能让内核运行的更有效率,并且省电,pc下可选,特别是笔记本,arm linux一般不用选。

[ ] High Resolution Timer Support,支持高频率时间发生器,需要硬件兼容,但大多数PC和ARM都不支持,不选

Memory split (2G/2G user/kernel split) —>,内核与用户空间各占2G,内核空间0-0x7FFFFFFF,用户空间80000000-FFFFFFFF

Preemption Model (No Forced Preemption (Server)) —>,内核抢占模式。普通PC用户一般选2,arm linux 选1就可以。

No Forced Preemption (Server),禁止内核抢占,适合服务器环境。针对于高吞吐量的设计,但有可能延时较长,适用于服务器或科学运算,或向要最大的运算能力,而不理会调度上的延时。

Voluntary Kernel Preemption (Desktop),自愿内核抢占,适合普通的桌面环境。已降低吞吐量为代价,降低内核调度的最大延时,提供更快的应用程序响应,即使系统已经高负荷运转,应用程序仍然能运行的很“流畅”,适合用户桌面环境

Preemptible Kernel (Low-Latency Desktop),主动内核抢占,适合运行实时程序的环境。更低的吞吐量,进一步降低内核的调度延时,使应用程序更加流畅。

[ ]Compile the kernel in Thumb-2 mode,编译Thumb-2 mode内核,一般不选

[*] Use the ARM EABI to compile the kernel,与下面绑定配置。

[*] Allow old ABI binaries to run with this kernel (EXPERIMENTAL),对于嵌入式系统(jffs2 yaffs2),这两个要选上,否则很可能启动的时候报错(kernel panic- not syncing: Attempted to kill init!)

[ ] High Memory Support (EXPERIMENTAL)(有子项), 1G物理内存以下不选,超过1G才选。(配置略有变化,以前的选项是OFF(<1G),4G(>1G && <4G),64G(>4G))。

Allocate 2nd-level pagetables from highmem,1G物理内存以下不选,超过1G(小于4G)才选

Allocate 3nd-level pagetables from highmem,大于4G,选择此项目。

Memory model (Flat Memory) —>,一般选"Flat Memory",其他选项涉及内存热插拔。

[ ] Enable KSM for page merging,允许linux内核识别出包含相同内容的内存页,然后合并这些内存页,将数据整合在一个位置可以多次引用,特殊功能,不用选。

(4096) Low address space to protect from user allocation,默认4096即可

[ ] Use kernel mem{cpy,set}() for {copy_to,clear}_user() (EXPERIMENTAL),不清楚可以不选。


附:yaffs2 文件系统:Kernel panic - not syncing: Attempted to kill init!

在内核挂载根文件系统时,提示Kernel panic - not syncing: Attempted to kill init!的解决方法:

方法1:

Kernel Features —>

[*] Use the ARM EABI to compile the kernel

[*] Allow old ABI binaries to run with this kernel (EXPERIMENTA)

方法2:

修改busybox的Makefile

修改

CC=$(CROSS_COPILE)gcc

CC=$(CROSS_COPILE)gcc -march=armv4t

一般海思编译器选择此选项,linux-gcc-3.4.5 以下的编译器,不用选,如果用4.3.3(支持EABI的编译器)以上的最好选上。

\8. Boot options

一般不需要配置,u-boot会把启动参数传递给内核。如果bootloader没有传参数,可以配置启动参数,类似下面这样:

(0x0) Compressed ROM boot loader base address

(0x0) Compressed ROM boot loader BSS address

(mem=32M console=ttySAC0 root=/dev/ram initrd=0x30800000,4M ramdisk_size=4096 rw) Default kernel command string

\9. CPU Power Management

[ ] CPU idle PM support,允许软件控制的空闲进程电源管理,arm linux一般不用选。

\10. Floating point emulation(浮点运算,(arm专用)看arm是否支持硬浮点协处理器,支持的话选择VFP,不支持选择NWFPE)

[ ] NWFPE math emulation

[ ] FastFPE math emulation (EXPERIMENTAL)

[*] VFP-format floating point maths

[ ] Advanced SIMD (NEON) Extension support

\10. Userspace binary formats(二进制支持)

[*] Kernel support for ELF binaries,必须选,否则内核可能不能启动,其他可以全部不选,

[ ] Write ELF core dumps with partial segments

< > Kernel support for a.out and ECOFF binaries

< > Kernel support for MISC binaries

\11. Power management options(电源管理)

一般用于笔记本,PC和arm可以不选。

[*] Power Management support,选择此项,下面的项才能可见

[ ] Power Management Debug Support,调试用,不用选

[*] Suspend to RAM and standby,待机到内存,即内存供电而暂时关闭硬盘等外设。

< > Advanced Power Management Emulation,高级电源管理,

[ ] Run-time PM core functionality,允许对运行中接入的I/O设备进行电源管理。

\12. Networking support,(协议层的网络支持,socket等,硬件层的支持在Device Drivers中配置)

Networking options —>,网络选项

<*> Packet socket,这种socket能够让应用程序(tcpdump,iptables)直接与网络设备通讯,而不通过内核中的其他中介协议,最好选上。

<*> Unix domain sockets,一种仅运行于本机上的效率高于TCP/IP 的socket,简称Unix socket.许多程序都使用它在操作系统内部进行进程间通信(IPC),比如X Window 和syslog,最好选上。

< > Transformation user configuration interface,为IPsec(可在ip层加密)之类的工具提供XFRM 用户配置接口支持,不清楚可以不选。

[ ] Transformation sub policy support (EXPERIMENTAL),XFRM子策略支持,仅供开发者使用,不清楚不要选。

[ ] Transformation migrate database (EXPERIMENTAL),

[ ] Transformation statistics (EXPERIMENTAL),

< > PF_KEY sockets,用于可信任的密钥管理程序和操作系统内核内部的密钥管理进行通信,IPsec也依赖于它,可以不选。

[ ] PF_KEY MIGRATE (EXPERIMENTAL),子项,不用选。

[*] TCP/IP networking,TCP/IP协议,必须要选

[*] IP: multicasting,群组广播,选上

[] IP: advanced router,高级路由功能,做路由器的话选上,可以不选。

Choose IP: FIB lookup algorithm (choose FIB_HASH if unsure) (FIB_HASH),子项,不懂的话就选FIB_HASH吧

[ ] IP: policy routing,策略路由,不清楚可以不选。

[ ] IP: equal cost multipath,用于路由的基于目的地址的均衡。不清楚可以不选。

[ ] IP: verbose route monitoring,显示冗余的路由监控信息,可以不选

[ ] IP: kernel level autoconfiguration,内核启动时自动配置IP地址、路由表等,需要从网络启动的无盘工作站需要这个,普通用户不需要。

< > IP: tunneling,IP隧道,将一个IP报文装在另一个IP报文的技术。不清楚不用选。

< > IP: GRE tunnels over IP,基于IP的GRE(通用路由封装)隧道,不清楚可以不选。

[] IP: multicast routing,多重传播路由,没有特殊需求可以不选。

[ ] IP: multicast policy routing,子项,不清楚可以不选

[ ] IP: PIM-SM version 1 support,子项,不清楚可以不选

[ ] IP: PIM-SM version 2 support,子项,不清楚可以不选

[ ] IP: ARP daemon support,废弃功能,不选。

[ ] IP: TCP syncookie support,抵抗SYN flood攻击的好东西,要启用它必须同时启用/proc文件系统和"Sysctlsupport", 然后在系统启动并挂载了/proc 之后执行"echo 1>/proc/sys/net/ipv4/tcp_syncookies"命令,不清楚可以不选。

< > IP: AH transformation,IPsec验证头(AH),实现了数据发送方的验证处理,可确保数据既对于未经验证的站点不可用也不能在路由过程中更改,不清楚可以不选。

< > IP: ESP transformation,IPsec封闭安全负载(ESP),实现了发送方的验证处理和数据加密处理,用以确保数据不会被拦截/查看或复制。不清楚可以不选。

< > IP: IPComp transformation,IPComp(IP静荷载压缩协议),用于支持IPsec,不清楚可以不选。

< > IP: IPsec transport mode,IPsec传输模式,常用于对等通信,用以提供内网安全.数据包经过了加密但IP头没有加密,因此任何标准设备或软件都可查看和使用IP头,不清楚可以不选。

< > IP: IPsec tunnel mode,IPsec隧道模式,用于提供外网安全(包括虚拟专用网络).整个数据包(数据头和负载)都已经过加密处理且分配有新的ESP 头/IP 头和验证尾,从而能够隐藏受保护站点的拓扑结构,不清楚可以不选。

< > IP: IPsec BEET mode,IPsec BEET模式,不清楚可以不选。

[*] Large Receive Offload (ipv4/tcp),针对 TCP 流量的 LRO (Large Receive Offload) 支持,选上。

<*> INET: socket monitoring interface,socket监视接口,一些Linux 本地工具(如:包含ss的iproute2)需要使用它,选上

[] TCP: advanced congestion control —>,高级拥塞控制,如果没有特殊需求(比如无线网络)就别选了,内核会自动将默认的拥塞控制设为"Cubic"并将"Reno"作为候补,可以不选。如果网络用处较多,还是选上为好(如网络视频服务器)。 关于拥塞控制,见tcp拥塞控制.doc文档。

[ ] TCP: MD5 Signature Option support (RFC2385) (EXPERIMENTAL),不清楚可以不选。

<*> The IPv6 protocol —>,IPV6支持的话,就选上,

[*] Only allow certain groups to create sockets,只允许特定的群体创建socket,选上,没什么坏处。

[*] Network activity statistics tracking,最好选上。

…….网络选项中,后面的不清楚的话 可以不选,选上基本几项,网络就可以工作了,有时间进一步深入研究。

-*- Wireless —>(无线,没有无线网卡的话可以不选)

<*> cfg80211 - wireless configuration API,暂时未会,使用默认配置

\13. Device Drivers(设备驱动)

Generic Driver Options —>,通用选项

(/sbin/mdev) path to uevent helper,不理解,用的默认值

[ ] Maintain a devtmpfs filesystem to mount at /dev,让devtmpfs文件系统安装在/dev,不清楚可以不选。

[*] Select only drivers that don’t need compile-time external firmware,只显示那些不需要内核对外部设备的固件作map支持的驱动程序,除非你有某些怪异硬件,否则请选上。

[ ] Prevent firmware from being built,不编译固件(固化的软件,如bios).固件一般是随硬件的驱动程序提供的,仅在更新固件的时候才需要重新编译。可以不选,但想要更新固件的话就要重新编译内核了。

{*} Userspace firmware loading support,提供某些内核之外的模块需要的用户空间固件加载支持,在内核树之外编译的模块可能需要它,选上。

[*] Include in-kernel firmware blobs in kernel binary

() External firmware blobs to build into the kernel binary

< > Connector - unified userspace <-> kernelspace linker —>,用户空间和内核空间连接器,工作在netlink socket协议的顶层,不清楚可以不选。

<*> Memory Technology Device (MTD) support —>,特殊的存储技术,如常用语数码相机或嵌入式系统的闪存卡,一般是NOR flash和Nand的支持,arm linux必选,PC不用选。

[ ] Debugging,调试模式,不选。

< > MTD tests support,MTD测试支持,不清楚可以不选。

< > MTD concatenating support,连接多个MTD设备,例如使用JFFS2文件系统管理多片Flash的情形。只有一片Flash时不选。

[*] MTD partitioning support,分区支持,选上。

< > RedBoot partition table parsing,使用RedBoot解析Flash分区表,如果需要读取这个分区表的信息选择此项

[*] Command line partition table parsing,允许通过内核命令行传递MTD分区表信息,

< > ARM Firmware Suite partition parsing,使用AFS分区信息

< > TI AR7 partitioning support,AR7分区支持

<*> Direct char device access to MTD devices,将系统中的MTD设备看做字符设备进行读写,需要与驱动同步的。

-*- Common interface to block layer for MTD ‘translation layers’

<*> Caching block device access to MTD devices,文件系统挂载后,模拟块设备进行访问。常用于只读文件系统。如果是DiskOnChip使用NFTL方式。

< > FTL (Flash Translation Layer) support,提供对Flash翻译层支持,可以不选

< > NFTL (NAND Flash Translation Layer) support,NAND Flash翻译层支持,可以不选

< > INFTL (Inverse NAND Flash Translation Layer) support,提供INFTL支持,DiskOnChip使用

< > Resident Flash Disk (Flash Translation Layer) support,提供RFD支持,为嵌入式系统提供类似BIOS功能,不清楚可以不选,使用Uboot驱动的话也不用选。

< > NAND SSFDC (SmartMedia) read only translation layer,NAND SSFDC只读翻译层,不清楚可以不选。

< > SmartMedia/xD new translation layer,不清楚可以不选。

< > Log panic/oops to an MTD buffer,MTD缓冲日志,不清楚可以不选。

RAM/ROM/Flash chip drivers —>,RAM/ROM/Flash芯片驱动,不清楚可以不选。

Mapping drivers for chip access —>,为芯片的访问方式选择Mapping驱动,不清楚可以不选。

Self-contained MTD device drivers —>,自身包含MTD设备驱动,一般不选。

< > Include chip ids for known NAND devices.,NAND flash信息,不用选。

< > NAND Device Support —>,Nand设备支持,有nand的话选上,子项默认配置即可,如果支持Nand,加选这一项就够了。

< > OneNAND Device Support —>,One nand支持,不清楚可以不选。

LPDDR flash memory drivers —>,LPDDR Flash内存驱动,未用,不用选。

UBI - Unsorted block images —>未分类block影响,不清楚不选。

附:配置支持jffs2两步

  1. 在“memory technology devices(mtd)”选项中选择:

<*>memory technology device(mtd)support

<*>mtd partitioning support

<*>cashing block device access to mtd devices

ram/rom/flash chip drivers—>

<*> detect flash chips by common flash interface(cfi) probe

<*> support for intel/sharp flash chips

mapping drivers for chip access—>

<*> cfi flash device in physical memory map

(0) physical start address of flash mapping

(1000000)physical length of flash mapping

(2)buswidthin octets

<*> intel strataflash device mapped on at91rm9200

这里设置了flash芯片的起始地址、大小以及宽度,比如:起始地址为“0”,大小为“1000000”,即16mb,宽度为“2”,即16字节。然后选中自己加入的“intel strataflash device mapped on at91rm9200”这一项

  1. 在“file systems”选项中选择:

<*>joumalling flash file system v2(jffs2)support

对于其他功能,可根据自己的实际情况,进行裁减,然后保存退出,接下来编译出操作系统内核映像。(详细见 linux支持nor flash.txt 文档)

< > Parallel port support —>,配置并口,如打印机,arm linux可以不用配置

< > PC-style hardware (NEW),

< > AX88796 Parallel Port (NEW),

[ ] IEEE 1284 transfer modes (NEW),

[*] Block devices —>,块设备,一般都不用选,除非有特殊需要

< > Loopback device support,拿文件来模拟块设备,想要mount ios文件的话必须选上,一般不选。

< > Network block device support,网络块设备支持,让PC成为网络块设备的客户端。一般不选

< > Low Performance USB Block driver,低性能USB块设备驱动程序,一般不选。

<*> RAM block device support,RAM块设备支持,子选项保持默认就好了。

< > Packet writing on CD/DVD media,不清楚可以不选。

< > ATA over Ethernet support,不清楚可以不选。

[*] Misc devices —>,混杂设备驱动,一般不选。

< > ATA/ATAPI/MFM/RLL support (DEPRECATED) —>,不清楚可以不选。

SCSI device support —>,支持u盘的话,需要选上。

< > RAID Transport Class,不清楚可以不选。

<*> SCSI device support,支持u盘选上,子选项默认配置即可。

< > Serial ATA and Parallel ATA drivers —>,SATA和PATA支持,没有硬盘的话可以不选。

[ ] Multiple devices driver support (RAID and LVM) —>,特殊服务器管理用到,如LVM,一般用户不会用到,不用选,

[*] Network device support —>,网络设备支持,必选。包括前兆网卡,PPPOE等的支持。

[*] HID Devices —>,HID支持,选上

[*] USB support —>,USB支持,选上

<*> MMC/SD/SDIO card support —>,SD卡支持,选上。

……

其他选项根据需求来。在嵌入式linux中一般IIC SPI等device都自己写驱动,不用选。

\14. File systems(文件系统)

<*> Second extended fs support,EXT2文件系统支持。

[*] Ext2 extended attribute,EXT2文件系统支持。

<*> Ext3 journalling file system support,EXT3文件系统支持,子项默认就行。

<*> The Extended 4 (ext4) filesystem ,EXT4文件系统支持,子项默认就行。

……

有JFS(IBM所用)文件系统等,省略,用的不多。

……

[*] Enable POSIX file locking API,使能POSIX文件锁的API,最好选上。

[*] Dnotify support,基于目录的文件变化的通知机制,不选nfsd起不来,比选的。

[ ] Inotify file change notification support,新式的文件体统的变化通知机制,用以替代老旧的Dnotify,选了Dnotify就不要选它了。

[*] Inotify support for userspace,用户空间的Inotify支持,最好选上。(notify 是一个 Linux特性,它监控文件系统操作,比如读取、写入和创建)。

<*> FUSE (Filesystem in Userspace) support,允许在用户空间实现一个文件系统,如果打算开发一个自己的文件系统或使用一个机遇FUSE的文件系统,最好打开。

<*> Character device in Userpace support,允许在用户空间实现一个字符设备,

-*- Miscellaneous filesystems —>,杂项文件系统,子项很复杂,主要配置jffs2 和 yaffs2文件系统,一般用于嵌入式设备。

[*] Network File Systems —>,网络文件系统,NFS等。

……

其他没有特殊需求可以不选。

\15. Kernel hacking(内核hack选项,基本上选Enable __must_check logic和Stacktrace就可以了,有需要再深入研究)

[ ] Show timing information on printks,在printk的输出中包含时间信息,可以用来分析内核启动过程各步骤所用时间,需要时选上。

[ ] Enable __deprecated logic,不清楚不要选。

[*] Enable __must_check logic,在编译内核的过程中使用"必须检查"的逻辑,禁用它将不会显示某些警告信息,选上。

[ ] Magic SysRq key,不懂,千万别选。

[ ] Strip assembler-generated symbols during link,,不清楚不要选。

[ ] Enable unused/obsolete exported symbols,没用的信息符号,会使内核增大,不选.

[ ] Debug Filesystem,不是内核开发者的别选。

[ ]Run ‘make headers_check’ when building vmlinux,在编译内核时运行’make headers_check’命令检查内核头文件,当你修改了与用户空间相关的内核头文件后建议启用该选项。

[ ] Kernel debugging,不是内核开发者的别选。

[ ] SLUB debugging on by default,不清楚不要选。

[ ] Enable SLUB performance statistics,不清楚不要选。

[*] Stacktrace,支持调用栈,用于出错排查问题。

[ ] Debug memory initialization,调试内存初始化,不选,

[ ] Check for stalled CPUs delaying RCU grace periods ,检查停止CPU延缓RCU的宽限期,

[ ] Latency measuring infrastructure,不清楚不要选。

[ ] Sysctl checks,不清楚不要选。

[ ] Tracers —>,不清楚不要选。

[ ] Perform an atomic64_t self-test at boot,不清楚不要选。

[ ] Sample kernel code —> ,不清楚不要选。

[*] Enable stack unwinding support,可以不选(31没选)。

[*] Verbose user fault messages,可以不选(31没选)。

[ ] On-chip ETM and ETB,片上ETM、ETB,不清楚可以不选。

\16. Security options(安全选项,一般不需要配置,)

[ ] Enable the /proc/keys file by which keys may be viewed,允许有权限的进程通过/proc/keys读取所有的key,最好不要选。

[ ] Restrict unprivileged access to the kernel syslog,限制未经授权访问内核日志。

[ ] Enable different security models,允许内核选择不同的安全模式,如果未选择按默认处理。

[*] Enable the securityfs filesystem,不清楚可以不选(16没选)。

Default security module (Unix Discretionary Access Controls) —>,默认安全模式。

\17. Cryptographic API(支持的加密算法)

\18. Library routines(库子程序)

E. 编译内核:

​ make zImage

​ make bzImage

在x86平台,zImage只能用于小于512K的内核

如需获取详细的编译信息,使用:

​ make zImage V=1

​ make bzImage v=1

编译好的内核位于 arch//boot/目录下

有时候我们需要添加参数:ARCH=arm CROSS_COMPILE=arm-linux-

F. 编译内核模块

​ make modules

G.安装内核模块

​ make modules_install

H. 制作init ramdisk

​ mkinitrd initrd-$verision $verision

例子:

​ mkinitrd initrd-2.6.29 2.6.29

​ *$version 可通过查询/lib/modules下的目录得到。

i. 内核安装

  1. cp arch/x86/boot/bzImage /boot/vmlinuz-$version

  2. cp $initrd /boot/

  3. 修改/etc/grub.conf 或者/etc/lilo.conf

    $version 为所编译的内核版本号

linux 内核模块开发

  1. 模块功能:linux内核的整体结构非常庞大,其包含的组件也非常多

    • 方法一:

      把所有的组件都编译进内核文件,即zImage或bzImage,但这样会导致两个问题:

      1. 生成的内核文件过大
      2. 如果是要添加或者删除某个组件,需要重新编译整个内核
    • 方法二:

      内核模块机制能让内核文件(zImage或者bzImage)本身并不包含某组件,而是在该组件需要被使用的时候,动态的添加到正在运行的内核中。。

      1. 模块本身不会被编译进内核文件(zImage或者bzImage)
      2. 可以根据需求,在内核运行期间动态的安装或者卸载。

    范例:(hello.c)

     #include 
     #include 
     
     static int hello_init(void)
     {
         printf(KERN_WARNING"Hello, world !!!\n");
         return 0;
     }
     
     static void hello_exit(void)
     {
         printf(KERN_INFO "Goodbye, world!!! \n");
     }
     
     module_init(hello_init);
     module_exit(hello_exit);
    
     MODULE_LICENSE("GPL");//声明遵循的协议
     MODULE_AUTHOR("ZHANGHAO");//声明作者
     MODULE_DESCRIPTION("Hello World Module");//模块进行描述
     MODULE_ALIAS("a simplest module");//
     MODULE_VERSION("V1.0");//模块版本声明
    
  2. 程序结构

    • 模块加载函数

      ​ 安装模块时,被系统自动调用的函数,通过module_init宏来指定,在上面的范例中,由module_init(hello_init),知hello_init为模块加载函数。

    • 模块卸载函数

      ​ 卸载模块时,被系统自动调用的函数,通过module_exit宏来指定,在上面的范例中,由module_exit(hello_exit),知hello_exit为模块卸载函数。

  3. 模块编译

    • makefile 编译解决(单文件)

      ifneq ($(KERNELRELEASE),)
      obj-m	:=hello.o
      else
      KDIR	:=	/lib/modules/2.6.32-53.e15/build
      all:	
      	make -C $(KDIR) M=$(PWD) modules
      clean:
      	rm -f *.ko *.o *.mod.o *.mod.c *.symvers
      endif
      

      makefile编译解决(多文件)

      ifneq ($(KERNELRELEASE),)
      obj-m	:=hello.o
      hello-objs	:=main.o add.o
      else
      KDIR	:=	/lib/modules/2.6.32-53.e15/build
      all:	
      	make -C $(KDIR) M=$(PWD) modules
      clean:
      	rm -f *.ko *.o *.mod.o *.mod.c *.symvers
      endif
      
  4. 安装&卸载

    • 加载 insmod
    • 卸载 rmmod
    • 查看 lsmod
    • 加载 modprobe(加载一个模块到内核,能够自动去启动依赖模块)
    MODULE_LICENSE("GPL");//声明遵循的协议
    MODULE_AUTHOR("ZHANGHAO");//声明作者
    MODULE_DESCRIPTION("Hello World Module");//模块进行描述
    MODULE_ALIAS("a simplest module");//
    MODULE_VERSION("V1.0");//模块版本声明
    
  5. 模块参数

    通过宏module_param指定模块参数,模块参数用于在加载模块时传递参数给模块。

    module_param(name, type, perm)

    • name是模块参数的名称,type是这个参数的类型,perm是模块参数的访问权限
    • type常见值:bool-布尔型;int-整型;charp-字符串型;

    实例:param.c

     #include 
     #include 
     
     MODULE_LICENSE("GPL");//声明遵循的协议
     static char *name = "David Xie";
     static int age = 30;
     
    module_param(age, int, S_IRUGO);
    module_param(name, charp, S_IRUGO);
     
     static int hello_init(void)
     {
         printf(KERN_EMERG"Name: %s\n",name);
         printf(KERN_EMERG"Age: %d\n",age);
         return 0;
     }
     
     static void hello_exit(void)
     {
         printf(KERN_INFO "module exit \n");
     }
     
     module_init(hello_init);
     module_exit(hello_exit);
    
    
    • 参数模块的使用

      linux内核构建与编译_第13张图片

      [语法] insmod param.ko age=12

  6. 内核符号导出

    /proc/kallsyms/ 记录了内核中所有导出的符号的名字和地址。

    为了使得一个模块中的函数能够被其他模块使用,必须要将函数符号导出,使得系统能够索引到该函数并有权限使用。

    • 内核符号的导出使用:

      ​ EXPORT_SYMBOL(符号名)

      ​ EXPORT_SYMBOL_GPL(符号名) {只能用于包含GPL许可证的模块}

    实例:

    #include 
    #include 
    MODULE_LICENSE("GPL");
    
    int add_integar(int a, int b)
    {
        return a+b;
    }
    
    int sub_integar(int a, int b)
    {
        return a-b;
    }
    
    static int __init sym_init()
    {
        return 0;
    }
    
    static void __exit sym_exit()
    {
        
    }
    
    module_init(sym_init);
    module_exit(sym_exit);
    
    EXPORT_SYMBOL(add_integar);
    EXPORT_SYMBOL(sub_integar);
    
     #include 
     #include 
     
    MODULE_LICENSE("GPL");//声明遵循的协议
    MODULE_AUTHOR("ZHANGHAO");//声明作者
    MODULE_DESCRIPTION("Hello World Module");//模块进行描述
    MODULE_ALIAS("a simplest module");//
    MODULE_VERSION("V1.0");//模块版本声明
    
    extern int add_integar(int a, int b);
    extern int sub_integar(int a, int b);
    
    static int __init hello_init()
    {
        int res = add_integar(1,2);
        return 0;
    }
    
    static void __exit hello_exit()
    {
        int res = sub_integar(2,1);
    }
    
    module_init(hello_init);
    module_exit(hello_exit);
    

根文件系统


根文件系统是Linux启动时使用的第一个文件系统,内核和根文件系统缺一不可,根文件系统由一系列目录组成,目录中包含应用程序、C库、以及相关的配置文件。

基本的根文件系统文件结构:

linux内核构建与编译_第14张图片

利用busybox生成的目录:

linux内核构建与编译_第15张图片

  1. 根据结构构建目录

  2. 创建设备文件(有两个设备文件需要我们创建)

    cd dev/
    mknod -m 666 console c 5 1
    mknod -m 666 null c 1 3
    
  3. 安装etc

    
    
  4. 进入内核源代码,编译内核模块

    make modules ARCH=arm CROSS_COMPILE=arm-linux-
    
  5. 制定内核模块安装(将ko文件复制)到指定的文件夹中

    make modules_install ARCH=arm INSTALL_MOD_PATH=/xxx/rootfs
    
  6. 介绍busybox制作文件系统

    1. 进入Busybox Settings -->

      ​ build Options -->

      • 选中“Build busybox as a static binary”,静态链接
      • Cross Compiler prefix( arm-linux- )

      进入Installation Option —>

      • 选中“Don’t use /usr”,选中该项可以避免busybox被安装到宿主机/usr目录下,破坏系统。

      Busybox Installation Prefix(/xxx/rootfs),用于表明编译好的busybox安装的位置。

  7. 进入编译 & Install 过程

    make ARCH=arm CROSS_COMPILE=arm-linux-
    make install
    

你可能感兴趣的:(ARM嵌入式)