1.练习课上代码
2.把设备树信息解析相关函数按照自己的理解发布CSDN
3.复习中断相关内核
IO多路复用---epoll
核心内容:一棵树一个链表三个方法
epoll会将要监听的事件文件描述符添加到内核里一颗红黑树上,当有事件发生,epoll会调用回调函数将发生事件的文件描述符添加到存放的链表中,程序中只需要判断这个表是否为空即可知道是否有事件发生,然后针对表中的文件描述符进行IO操作即可。
一棵电路板上CPU、总线、设备组成的树
dtb文件会在内存中一直存在着,不会被内核或者应用程序占用,我们需要使用的时候可以直接使用dtb文件。dtb文件的内容会被解析生成多个device_node,然后这些device_node构成一棵树, 根节点为: of_root
自动换行
#include <sys/epoll.h>
1. int epoll_create(int size)
功能:创建一个epoll(建立红黑树)
2. int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
功能:epoll的操作函数
3.int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);
功能:阻塞等待事件就绪
stdio.h sys/types.h sys/stat.h sys/wait.h fcntl.h sys/select.h sys/time.h sys/epoll.h unistd.h stdlib.h string.h
#include<stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/epoll.h>
#include <unistd.h>
#include <stdlib.h>
#include<string.h>
stdio.h是stand input & output的缩写,意思是标准输入输出头文件。凡是用到标准输入输出函数,就要调用该头文件。
查看stdio.h目录下包含哪些函数:主要有文件访问、二进制输入/输出、格式化和非格式化输入/输出、文件定位、错误处理、文件操作等。
具体打开自己的VS安装目录,找到include文件夹,打开include夹下面的stdio.h文件即可查看
常用标准输入输出函数:
scanf() 从屏幕格式输入
printf() 格式输出到屏幕
getchar() 从屏幕得到一个字符
putchar() 字符输出到屏幕
gets() 从屏幕得到一个字符串
puts() 字符串输出到屏幕
fscanf() 从磁盘格式输入
fprintf() 格式输出到磁盘
fgetc() 从磁盘得到一个字符
fputc() 字符输出到磁盘
fgets() 从磁盘得到一个字符串
fputs() 字符串输出到磁盘
#号是预处理语句,表明在编译之前预先进行处理。
.h是header file的缩写,表面这是一个头文件。
include是文件包含命令,后面跟着引号""或者尖括号<>,意思是将引号或尖括号内指定的文件包含到本程序中,成为本程序的一部分,而包含的文件通常是由系统提供的。
区分引号""或者尖括号<>:尖括号<>编译程序会先到标准函数库中找文件,引号""编译程序会先从当前目录中找文件。
#include <sys/types.h>
基本系统数据类型
是Unix/Linux系统的基本系统数据类型的头文件,含有size_t,time_t,pid_t等类型。
NAME
sys/types.h - data types
SYNOPSIS (简要说明)
#include <sys/types.h>
DESCRIPTION (描述)
The <sys/types.h> header shall include definitions for at least the following types: (以下类型)
blkcnt_t
Used for file block counts.
blksize_t
Used for block sizes.
clock_t
Used for system times in clock ticks or CLOCKS_PER_SEC; see <time.h> .
clockid_t
Used for clock ID type in the clock and timer functions.
dev_t Used for device IDs.
fsblkcnt_t
Used for file system block counts.
fsfilcnt_t
Used for file system file counts.
gid_t Used for group IDs.
id_t Used as a general identifier; can be used to contain at least a pid_t, uid_t, or gid_t.
ino_t Used for file serial numbers.
key_t Used for XSI interprocess communication.
mode_t Used for some file attributes.
nlink_t
Used for link counts.
off_t Used for file sizes.
pid_t Used for process IDs and process group IDs.
size_t Used for sizes of objects.
ssize_t
Used for a count of bytes or an error indication.
suseconds_t
Used for time in microseconds.
time_t Used for time in seconds.
timer_t
Used for timer ID returned by timer_create().
trace_attr_t
Used to identify a trace stream attributes object.
trace_event_id_t
Used to identify a trace event type.
trace_event_set_t
Used to identify a trace event type set.
trace_id_t
Used to identify a trace stream.
uid_t Used for user IDs.
useconds_t
Used for time in microseconds.
All of the types shall be defined as arithmetic types of an appropriate length, with the following exceptions:
key_t
Additionally:
* mode_t shall be an integer type.
* nlink_t, uid_t, gid_t, and id_t shall be integer types.
* blkcnt_t and off_t shall be signed integer types.
* fsblkcnt_t, fsfilcnt_t, and ino_t shall be defined as unsigned integer types.
* size_t shall be an unsigned integer type.
* blksize_t, pid_t, and ssize_t shall be signed integer types.
* time_t and clock_t shall be integer or real-floating types.
dts 设备树源文件 dtc 设备树编译 dtb 二进制设备树镜像 dtsi 功能类似设备树文件的头文件
流程为 : dts dtb device_node platform_device
什么是设备树
(1)设备树(dt:device tree)是linux内核采用的参数表示和传递技术,在系统引导启动阶段进行设备初始化的时候,将设备树中描述的硬件信息传递给操作系统;
(2)dts(device tree source):设备树源文件,描述设备信息的;
(3)dtc(device tree compiler):设备树编译/反编译/调试工具;
(4)dtb(device tree binary):二进制设备树镜像;
(5)dtsi(device tree source include):功能类似设备树文件的头文件,可以被dts文件通过include引用,dtsi文件一般是描述共性部分;
设备树的加载流程
dts
文件经过dtc
工具编译为dtb
,内核加载并解析dtb
文件,最终获得设备树的信息在dts文件中,在根节点中有一个compatible属性,该属性的值是一系列的字符串,比如compatible = “samsung,smdk2440”“samsung,smdk2410,samsung,smdk24xx”;,该属性就是告诉内核要选择什么样的machine_desc,因为machine_desc结构体中有一个dt_compat成员,该成员表示machine_desc支持哪些单板,所以内核会把compatible中的字符串与dt_compat进行依次比较。
一、dts产生原因
DTS即Device Tree Source 设备树源码, DeviceTree是一种描述硬件的数据结构,它起源于OpenFirmware (OF)。
它替代arch/arm/plat-xxx和arch/arm/mach-xxx中的板级spec代码,便于code管理。
本质上,Device Tree改变了原来用hardcode方式将HW配置信息嵌入到内核代码的方法,改用bootloader传递一些参数。
如果我们认为kernel是一个black box,那么其输入参数应该包括:
a.识别platform的信息 b. runtime的配置参数 c.设备的拓扑结构以及特性
对于嵌入式系统,在系统启动阶段,bootloader会加载内核并将控制权转交给内核,此外,还需要把上述的三个参数信息传递给kernel,以便kernel可以有较大的灵活性。在linux kernel中,Device Tree的设计目标就是如此。
2.1 dts加载过程
如果要使用Device Tree,首先用户要了解自己的硬件配置和系统运行参数,并把这些信息组织成Device Tree source file。通过DTC(Device Tree Compiler),可以将这些适合人类阅读的Device Tree source file变成适合机器处理的Device Tree binary file(有一个更好听的名字,DTB,device tree blob)。在系统启动的时候,boot program(例如:firmware、bootloader)可以将保存在flash中的DTB copy到内存(当然也可以通过其他方式,例如可以通过bootloader的交互式命令加载DTB,或者firmware可以探测到device的信息,组织成DTB保存在内存中),并把DTB的起始地址传递给client program(例如OS kernel,bootloader或者其他特殊功能的程序)。对于计算机系统(computer system),一般是firmware->bootloader->OS,对于嵌入式系统,一般是bootloader->OS。
2.2 dts描述信息
Device Tree由一系列被命名的结点(node)和属性(property)组成,而结点本身可包含子结点。所谓属性,其实就是成对出现的name和value。在Device Tree中,可描述的信息包括(原先这些信息大多被hard code到kernel中):CPU的数量和类别
内存基地址和大小
总线和桥
外设连接
中断控制器和中断使用情况
GPIO控制器和GPIO使用情况
Clock控制器和Clock使用情况
一棵电路板上CPU、总线、设备组成的树
.dts文件是一种ASCII 文本格式的Device Tree描述,此文本格式非常人性化,适合人类的阅读习惯。基本上,在ARM Linux在,一个.dts文件对应一个ARM的machine,一般放置在内核的arch/arm/boot/dts/目录。由于一个SoC可能对应多个machine(一个SoC可以对应多个产品和电路板),势必这些.dts文件需包含许多共同的部分,Linux内核为了简化,把SoC公用的部分或者多个machine共同的部分一般提炼为.dtsi,类似于C语言的头文件。其他的machine对应的.dts就include这个.dtsi。
dtb文件会在内存中一直存在着,不会被内核或者应用程序占用,我们需要使用的时候可以直接使用dtb文件。dtb文件的内容会被解析生成多个device_node,然后这些device_node构成一棵树, 根节点为: of_root
设备树中的每一个节点,都会被转换为
device_node
结构体
那么多的device_node,哪些会被转化为platform_device呢?
根节点下的子节点,且该子节点必须包含compatible属性;
如果一个节点的compatile属性含有这些特殊的值(“simple-bus”,“simple-mfd”,“isa”,“arm,amba-bus”)之一,那么它的子结点(需含compatile属性)也可以转换为platform_device。
内核提供了一些
API
来直接获取设备树中对应的属性。如:
of_property_read_u32_index
:获取设备树中某个属性的值of_property_read_string
:获取设备树中某个属性的字符串的值of_get_address
:获取设备树中的某个节点的地址信息
头文件:
a. 处理DTB
of_fdt.h // dtb文件的相关操作函数, 我们一般用不到, 因为dtb文件在内核中已经被转换为device_node树(它更易于使用)b. 处理device_node
of.h // 提供设备树的一般处理函数, 比如 of_property_read_u32(读取某个属性的u32值), of_get_child_count (获取某个 device_node的子节点数)
of_address.h // 地址相关的函数, 比如 of_get_address(获得reg属性中的addr, size值)of_match_device(从matches数组中取出与 当前设备最匹配的一项)
of_dma.h // 设备树中DMA相关属性的函数
of_gpio.h // GPIO相关的函数
of_graph.h // GPU相关驱动中用到的函数, 从设备树中获得GPU信息
of_iommu.h // 很少用到
of_irq.h // 中断相关的函数
of_mdio.h // MDIO (Ethernet PHY) API
of_net.h // OF helpers for network devices.
of_pci.h // PCI相关函数
of_pdt.h // 很少用到
of_reserved_mem.h // reserved_mem的相关函数c. 处理 platform_device
of_platform.h // 把device_node转换为platform_device时用到的函数,
// 比如of_device_alloc(根据device_node分配设置platform_device),
// of_find_device_by_node (根据device_node查找到platform_device),
// of_platform_bus_probe (处理device_node及它的子节点)
of_device.h // 设备相关的函数, 比如 of_match_device