logo资料库

达内嵌入式 Linux开发 笔记.pdf

第1页 / 共175页
第2页 / 共175页
第3页 / 共175页
第4页 / 共175页
第5页 / 共175页
第6页 / 共175页
第7页 / 共175页
第8页 / 共175页
资料共175页,剩余部分请下载后查看
GCC
编程环境
静态库的创建和使用
动态库的创建和使用
与库有关的命令
运行时调用共享库
C程序错误处理
环境变量获取
环境变量操纵函数
main()函数的参数
内存管理相关函数图
进程和程序
malloc和free函数特征
brk和sbrk
mmap和munmap
文件I/O
标C和UC I/O函数的区别
其它文件操纵函数
fcntl函数
文件锁
fcntl等待式加锁
测试锁
文件状态信息获取/修改
内存映射IO
目录操作函数
进程管理
与进程有关的命令
进程状态
进程启动顺序
进程相关函数
信号
信号操作函数
进程的计时器
管道
XSI IPC
共同特征
IPC命令
共享内存
消息队列
信号量集
网络编程
socket通信
TCP一对多通信
UDP通信
线程相关函数
u-boot.bin写入内存(USB)
u-boot.bin写入内存(SD卡)
u-boot.bin写入Flash
ARM处理器工作模式
寄存器
中断向量
内存数据对齐
ARM体系结构与裸机软件开发Day01
Ubuntu操作系统中的TFTP和NFS服务配置
ARM汇编指令
伪指令和伪操作
ATPCS
异常处理
嵌入式文件系统阶层图
bootloader、kernel、文件系统和用户程序调用关系
u-boot阶段1程序流程框图
u-boot阶段2程序流程框图
构建根文件系统
制作cramfs文件系统
制作ramdisk文件系统
内核移植案例
Linux下串口编程
内核移植简要步骤
内核模块
模块信息声明
模块的编译
模块参数
GPIO操作
字符设备驱动程序
设备文件的创建
设备号
注册、分配设备号
相关结构及函数
内核空间、用户空间数据交换
程序创建设备节点
struct inode和struct file
内核定时器
中断编程
中断申请
中断处理函数
ISR
ISR结构
tasklet
工作队列
中断屏蔽
原子操作
位原子操作
整型原子操作
自旋锁
信号量
内核等待队列
内存分配
内核数据结构——链表
platform总线
平台设备platform_device
平台驱动platform_driver
mmap
IO多路监听select/poll
Input子系统
I2C驱动
I2C驱动框架
i2c_bus_type虚拟总线
i2c_driver
i2c_client
SMBUS协议
混杂设备
1 GCC 1.1 功能:预处理、编译、连接、汇编。 1.2 gcc –E 只预处理; gcc –S 汇编; gcc –c 只编译,不连接; gcc –o 连接,生成目标文件; gcc –std 设置标准规范 C89、C99 等; gcc –Wall 显示尽可能多的警告信息; 1.3 .a 静态库文件; .o 目标文件; .i 不需要预处理的源程序(预处理后的源文件,文本文件); .s 汇编文件(文本文件); .so 共享库文件; 1.4 头文件写什么? 各种声明。其它写源文件中。使用者只需头文件和库文件即可。 1.5 编译过程(从源代码到可执行文件) a 预处理:gcc –E file.c –o file.i //o 应该是 output 的意思,而非 object b 汇编:gcc –S file.i //生成同名的.s 文件,也可输入源文件 c 目标代码生成:gcc –c file.s //生成同名的.o 文件,可输入源文件和.i 文件 d 连接:gcc file.o –o exe_file //生成可执行文件 exe_file,输入源文件可一步到位 实例:
一个源文件就是一个编译单元,编译生成对应的目标文件,多个目标文件可连接成一个可 执行文件。 1.6 gcc 专用预处理指令 产生一个错误,遇到错误停止(预)编译,输出错误信息; #error #warning 产生一个警告,但不停止编译; #pragma 额外指定功能,增强指令; #pragma GCC dependency “file_name” 若 file_name 比当前文件更新(比较最后修改时间),将产生警告; #pragma GCC poison symbol 符号 symbol 不能使用,否则产生错误; #pragm pack(integer) 改变结构体的对齐和补齐方式:integer=1,不对齐和补齐;integer=2,按 2 字节做对 齐和补齐,还可以取其它值; 1.7 a.c 文件中定义了全局变量 g,如何在 b.c 中使用,在 b.c 中作如下声明: extern type g; 如果不想 g 被其它文件访问,在 a.c 中这样定义 g(即使在其它文件中 extern 也不行): static type g; 2 编程环境 2.1 常用环境变量(注意大小写) PATH 系统路径 CPATH, C_INCLUDE_PATH C 语言头文件路径 LD_LIBRARY_PATH 共享库路径 LIBRARY_PATH 库路径 路径分隔符:”:”(Unix), “;”(Windows); 2.2 设置环境变量 PATH(bash): a export PATH=new_dir:$PATH =前后不能有空格 b 将 上 述 命 令 加 入 当 前 用 户 启 动 文 件 : /home/{user_name}/.bashrc; /home/{user_name}/.bash_profile; 重启生效或$source .bashrc 2.3 头文件的查找 a 系统默认路径:/usr/include 等; b 环境变量 CPATH,C_INCLUDE_PATH 指向的路径; c gcc –I header_dir,编译时指定头文件路径; d #include “path”, 目录 path。
2.4 在源文件中实现头文件中声明的函数时,可以不 include 相应的头文件。 2.5 源文件编译打包成库文件,发布头文件和库文件而不发布源文件的方式: a 静态库:归档目标代码,连接时直接复制代码段到目标; 连接时使用 gcc –static 选项生成可执行文件 b 动态库(共享库):归档目标代码,连接时在目标中仅写入调用地址;
1 静态库的创建和使用 创建: a 生成目标文件:$gcc –c {src_file_list} b 生成库:$ar rs|-r {lib_file_name} {obj_file_list} 库文件命名规则:lib{name}.a c 发布库文件和头文件。 使用: a 连接目标文件和库文件: $gcc {obj_file_list} {lib_file_name} 添加库文件路径至 LIBRARY_PATH,执行命令(lib_name 不含前缀 lib 和扩展名.a): $gcc {obj_file_list} –l {name} 不添加 LIBRARY_PATH 执行命令: $gcc {obj_file_list} –l {name} –L {library_path} 即使库文件在当前目录下,也要指定库的路径: -L . 为什么-l 使用库的名字而非文件名?因为 gcc 优先搜索动态库。 b 发布可执行文件即可。 2 动态库的创建和使用 创建: a 生成目标文件:$gcc –c –fpic {src_file_list} b 生成.so 库:$gcc –shared {obj_file_list} –o lib{name}.so c 发布头文件和库文件。 使用: a 连接目标和库文件: $gcc {obj_file_list} –l{name} –L {library_path} b 发布可执行文件和动态库。 c 运行时添加库路径至 LD_LIBRARY_PATH,再执行可执行文件。 3 与库有关的命令 ldd 查询库文件或可执行文件对其它库的依赖; 4 运行时调用共享库 a 打开一个共享库文件(); void *dlopen(const char *filename, int flag) flag 须是 RTLD_LAZY 和 RTLD_NOW 之一; b 在打开库中获取一个函数; void *dlsym(void *handle, const char *symbol) c 调用函数; d 关闭共享库。 int dlclose(void *handle)
连接时使用-ldl(置于命令末:$gcc obj_file_list –o exe_file -ldl)。 出错信息 char *dlerror():在调用上述三个函数后调用此函数,如有错发生返回错误信息, 否则返回 NULL; 5 C 程序错误处理 5.1 通过函数的返回值代表错误: a 如果返回指针类型,一般用 NULL 代表错误; b 如果返回 int 类型,若返回值不可能为负,-1 表示错误;若返回值可为任何值,可使用指 针带出返回数据,return 0 代表成功,return -1 代表失败; c 不需要考虑出错,返回值设为 void; 5.2 C 错误处理方式 全局变量:errno 代表错误编号,#include; perror(const char *) 输出错误信息到终端,参数指定额外信息,#include; char *strerror(int errno) 转换错误代码到字符串,#include 不是所有的函数在出错时都将错误代码写入 errno。 不能用 errno 来判断函数调用是否正确,仅当函数返回值指明其出错时,才应调用 errno 检 查具体错误。errno 的值直到出错才会被修改! 6 环境变量获取 6.1 环境表: 环境变量名值对的字符指针数组 extern char** environ; environ 的最后一个元素存放 NULL! 6.2 单个环境变量操作 char *getenv(const char *name) name 指定环境变量名,返回变量值;
1 环境变量操纵函数 #include char *getenv(const char *name); 获取环境变量; int setenv(const char *name, const char *value, int overwrite); 若 name 不存在设置新的名值对,若 name 已存在,且 overwrite 非零,给 name 设置新的 value; int unsetenv(const char *name); 删除环境变量 name; int putenv(char * name_value_pair); 设置环境变量:name_value_pair 格式:name=value; 2 main()函数的参数 完整格式: int main(int argc, char **argv, char **env); argv:参数列表,包括可执行文件名; argc:argv 的个数; env:环境变量列表,同 extern char **environ 全局变量。 3 内存管理相关函数图 STL -> 自动分配和自动回收 | C++ -> new 和 delete 关键字 | C -> malloc()和 free() | 系统函数 -> sbrk()和 brk() | 底层系统函数 -> mmap()和 munmap() ____________________________________________________用户层 | 内核函数 -> kmalloc(), vmalloc(), get_free_page()等 ____________________________________________________核心层 4 进程和程序 4.1 程序:保存在辅助存储器上的可执行文件;进程:内存中正在执行的程序; 4.2 进程的内存模型 a 代码段:存放指令(包括函数),只读; b 全局段:存放全局变量,static 局部变量,读写;
c bss 段:未初始化的全局变量,在 main()执行之前全部清零; d 栈:存放局部变量,包括函数形参,内存自动分配和回收; e 堆(数据段):程序员管理; f 只读常量段:和代码段接近,有些资料将其和代码段合并一起讲。 排列次序:代码段、只读常量段、全局段、bss 段、堆、栈; 堆从低地址向高地址分配,栈从高地址(接近 3G)向低地址分配。 4.3 虚拟内存地址和物理内存 a Linux 使用虚拟内存地址进行内存管理,每个进程都有 0-4G 的虚拟内存地址(32bit 无符 号整数),0-3G 用户空间,3-4G 内核空间;用户空间不能直接访问内核空间,可通过系统 调用访问; b 虚拟内存必须先映射到一段物理内存或硬盘上的文件才能使用,分配内存就是将虚拟内存 映射到物理内存,未经映射而使用将引发段错误; c 程序中操纵的都是虚拟内存地址; d 内存管理的基本单位:页(4K),内存的分配和回收以页为基本单位; 5 malloc 和 free 函数特征 5.1 malloc 分配内存时,除了分配申请的数量之外,还需要额外分配一定量的空间,以存储 额外的信息(实际分配数量,下一个区域的指针,如何回收等),这些信息存储在一个链表 中; 5.2 malloc 分配物理内存时,按照一次 33 个内存页分配,如果一次性申请超过 33 页,将分 配比指定数稍多的页数; 5.3 free 并不保证立即释放物理内存,释放到了最后一个变量时,系统依然后保留 33 个内存 页不释放; 5.4 什么情况下引发段错误? a 引用没有映射物理内存的虚拟地址时; b 写只读内存页。
1 brk 和 sbrk 都可以调整进程数据段(堆)的 break,brk 是系统调用,sbrk 是库函数,功能一致。 #include int brk(void *addr); void *sbrk(int increase); 1.1 对于 sbrk,参数为 0 返回当前进程的 break,参数非零返回前一次的 break!失败返回 (void*)-1. 实例: 输出: 1.2 brk 将当前的 break 设置为指定值,成功返回 0,失败-1. 实例:
分享到:
收藏