Linux驱动程序开发实例的目录

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux驱动程序开发实例的目录相关的知识,希望对你有一定的参考价值。

参考技术A

前言
第1章 Linux设备驱动程序模型 1
1.1 设备驱动程序基础 1
1.1.1 驱动程序的概念 1
1.1.2 驱动程序的加载方式 2
1.1.3 编写可加载模块 3
1.1.4 带参数的可加载模块 5
1.1.5 设备驱动程序的分类 6
1.2 字符设备驱动程序原理 7
1.2.1 file_operations结构 7
1.2.2 使用register_chrdev注册字符
设备 9
1.2.3 使用cdev_add注册字符设备 11
1.2.4 字符设备的读写 13
1.2.5 ioctl接口 14
1.2.6 seek接口 16
1.2.7 poll接口 18
1.2.8 异步通知 22
1.3 proc文件系统 24
1.3.1 proc文件系统概述 24
1.3.2 seq_file机制 25
1.3.3 使用proc文件系统 27
1.4 块设备驱动程序 32
1.4.1 Linux块设备驱动程序原理 32
1.4.2 简单的块设备驱动程序实例 35
1.5 网络设备驱动程序 39
1.5.1 网络设备的特殊性 39
1.5.2 sk_buff结构 40
1.5.3 Linux网络设备驱动程序架构 42
1.5.4 虚拟网络设备驱动程序实例 46
1.6 Linux 2.6设备管理机制 50
1.6.1 kobject和kset 50
1.6.2 sysfs文件系统 51
1.6.3 设备模型层次 52
1.6.4 platform的概念 54
第2章 Linux内核同步机制 58
2.1 锁机制 58
2.1.1 自旋锁 58
2.1.2 读写锁 60
2.1.3 RCU 61
2.2 互斥 64
2.2.1 原子操作 64
2.2.2 信号量 65
2.2.3 读写信号量 67
2.3 等待队列 68
2.3.1 等待队列原理 68
2.3.2 阻塞式I/O实例 68
2.3.3 完成事件 70
2.4 关闭中断 71
第3章 内存管理与链表 72
3.1 物理地址和虚拟地址 72
3.2 内存分配与释放 72
3.3 IO端口到虚拟地址的映射 73
3.3.1 静态映射 73
3.3.2 动态映射 75
3.4 内核空间到用户空间的映射 76
3.4.1 内核空间到用户空间的地址
映射原理 76
3.4.2 mmap地址映射实例 78
3.5 内核链表 80
3.5.1 Linux内核中的链表 80
3.5.2 内核链表实例 81
第4章 延迟处理 83
4.1 内核线程 83
4.2 软中断机制 85
4.2.1 软中断原理 85
4.2.2 tasklet 87
4.3 工作队列 89
4.3.1 工作队列原理 89
4.3.2 工作队列实例 91
4.4 内核时间 92
4.4.1 Linux中的时间概念 92
4.4.2 Linux中的延迟 93
4.4.3 内核定时器 93
第5章 简单设备驱动程序 96
5.1 寄存器访问 96
5.1.1 S3C6410地址映射 96
5.1.2 S3C6410看门狗驱动程序实例 98
5.1.3 S3C6410蜂鸣器驱动程序实例 102
5.2 电平控制 107
5.2.1 S3C6410 LED驱动程序实例 107
5.2.2 扫描型S3C6410按键驱动
程序实例 109
5.3 时序产生 112
5.3.1 时序图原理 112
5.3.2 AT24C02芯片原理 112
5.3.3 AT24C02驱动程序开发实例 115
5.4 硬中断处理 123
5.4.1 硬中断处理原理 123
5.4.2 中断型S3C6410按键驱动
程序实例 127
5.5 Linux I/O端口控制 132
5.5.1 Linux I/O端口读写 132
5.5.2 在应用层访问Linux I/O
端口 133
5.5.3 /dev/port设备 134
第6章 深入Linux内核 135
6.1 嵌入式Linux系统构成 135
6.2 Linux内核导读 136
6.2.1 Linux内核组成 136
6.2.2 Linux的代码结构 137
6.2.3 内核Makefile 138
6.2.4 S3C6410硬件初始化 139
6.3 Linux文件系统 141
6.3.1 虚拟文件系统 141
6.3.2 根文件系统 143
6.3.3 文件系统加载 143
6.3.4 ext3文件系统 145
6.4 Flash文件系统 145
6.4.1 MTD设备 145
6.4.2 MTD字符设备 148
6.4.3 MTD块设备 150
6.4.4 cramfs文件系统 153
6.4.5 JFFS2文件系统 153
6.4.6 YAFFS文件系统 155
6.4.7 文件系统总结 156
6.5 Linux内核移植 156
6.5.1 体系配置 156
6.5.2 添加yaffs2 157
6.5.3 Nand flash驱动程序移植 157
6.5.4 配置启动参数 159
6.5.5 移植RTC驱动程序 160
6.6 根文件系统制作 162
6.6.1 Busybox 162
6.6.2 shell基础 165
6.6.3 根文件系统构建实例 166
6.7 udev模型 167
6.7.1 udev模型原理 167
6.7.2 mdev的使用 167
第7章 I2C总线驱动程序 169
7.1 Linux的I2C驱动程序架构 169
7.1.1 I2C适配器 169
7.1.2 I2C算法 170
7.1.3 I2C驱动程序结构 170
7.1.4 I2C从设备 171
7.1.5 i2c-dev设备层 171
7.2 Linux I2C驱动程序开发 174
7.2.1 S3C2410X的I2C控制器 174
7.2.2 S3C2410X的I2C驱动程序
分析 175
7.3 S3C2410的I2C访问实例 182
7.4 I2C客户端驱动程序 185
第8章 TTY与串口驱动程序 190
8.1 TTY概念 190
8.2 Linux TTY驱动程序体系 190
8.2.1 TTY驱动程序调用关系 190
8.2.2 TTY驱动程序原理 191
8.3 线路规程 194
8.4 串口驱动程序与TTY 196
8.4.1 串口设备驱动程序原理 196
8.4.2 S3C6410的串口驱动程序
实例 199
8.5 TTY应用层 202
第9章 网络设备驱动程序 205
9.1 DM9000网卡驱动程序
开发 205
9.1.1 DM9000原理 205
9.1.2 DM9000X驱动程序分析 207
9.1.3 DM9000网口驱动程序移植 215
9.2 NFS根文件系统搭建 219
9.2.1 主机配置 219
9.2.2 NFS根文件系统搭建实例 220
9.3 netlink Socket 224
9.3.1 netlink机制 224
9.3.2 netlink应用层编程 228
9.3.3 netlink驱动程序实例 229
第10章 framebuffer驱动程序 232
10.1 Linux framebuffer驱动
程序原理 232
10.1.1 framebuffer核心数据结构 232
10.1.2 framebuffer操作接口 234
10.1.3 framebuffer驱动程序的文件
接口 236
10.1.4 framebuffer驱动程序框架 236
10.2 S3C6410 显示控制器 238
10.3 S3C6410 LCD驱动程序实例 243
10.4 framebuffer应用层 250
10.5 Qt4界面系统移植 251
第11章 输入子系统驱动程序 253
11.1 Linux输入子系统概述 253
11.1.1 input_dev结构 253
11.1.2 输入事件 255
11.2 input_handler 256
11.2.1 Input Handler层 256
11.2.2 常用的Input Handler 259
11.3 输入设备应用层 261
11.4 键盘输入设备驱动程序
实例 262
11.5 event接口 267
11.6 触摸屏驱动程序实例 270
11.6.1 S3C6410触摸屏控制器 270
11.6.2 S3C6410触摸屏驱动程序
设计 273
11.7 触摸屏校准 282
11.7.1 触摸屏校准原理 282
11.7.2 利用TSLIB库校准触摸屏 282
第12章 USB驱动程序 284
12.1 USB体系概述 284
12.1.1 USB系统组成 284
12.1.2 USB主机 284
12.1.3 USB设备逻辑层次 285
12.2 Linux USB驱动程序体系 287
12.2.1 USB总体结构 287
12.2.2 USB设备驱动程序 287
12.2.3 主机控制器驱动程序 288
12.2.4 USB请求块urb 289
12.2.5 USB请求块的填充 291
12.3 S3C6410 USB主机控制器
驱动程序 292
12.3.1 USB主机控制器驱动程序
分析 292
12.3.2 S3C6410 USB驱动程序
加载 294
12.4 USB键盘设备驱动程序
分析 296
12.5 USB Gadget驱动程序 301
12.5.1 Linux USB Gadget驱动程序 301
12.5.2 Linux USB Gadget驱动程序
实例 302
第13章 音频设备驱动程序 303
13.1 ALSA音频体系 303
13.2 ALSA驱动层API 304
13.2.1 声卡和设备管理 304
13.2.2 PCM API 304
13.2.3 控制与混音API 305
13.2.4 AC97 API 306
13.2.5 SOC层驱动 307
13.3 ALSA驱动程序实例 308
13.3.1 S3C6410的AC97控制
单元 308
13.3.2 S3C6410声卡电路原理 309
13.3.3 S3C6410的数字音频接口 310
13.3.4 wm9713的数字音频接口 313
13.4 ALSA音频编程接口 316
13.4.1 ALSA PCM接口实例 316
13.4.2 ALSA MIDI接口实例 320
13.4.3 ALSA mixer接口实例 321
13.4.4 ALSA timer接口实例 322
第14章 video4linux2视频
驱动程序 327
14.1 video4linux2驱动程序
架构 327
14.1.1 video4linux2驱动程序的
注册 327
14.1.2 v4l2_fops接口 331
14.1.3 常用的结构 332
14.1.4 video4linux2的ioctl函数 333
14.2 S3C6410摄像头驱动程序
分析 333
14.2.1 电路原理 333
14.2.2 驱动程序分析 334
14.3 video4linux2应用层实例 339
第15章 SD卡驱动程序 346
15.1 Linux SD卡驱动程序体系 346
15.1.1 SD卡电路原理 346
15.1.2 MMC卡驱动程序架构 347
15.1.3 MMC卡驱动程序相关
结构 347
15.1.4 MMC卡块设备驱动程序 350
15.1.5 SD卡主机控制器接口驱动
程序 356
15.2 S3C6410 SD卡控制器驱动
程序分析 360
15.2.1 电路原理 360
15.2.2 S3C6410 SDHCI驱动
程序原理 360
15.2.3 SD卡的加载实例 364
参考文献 366

Linux程序开发中如何判断目录是否为根目录?

问题引入

判断某个目录字符串是否是根目录,咋一听很简单,只要判断字符串是否是"/"即可,但是,很多情况下使用的路径是相对路径,那么如何判断相对路径是根目录呢?

思路分析

熟悉Linux的同学应该知道,每个目录下都有.和..两个目录,分别指代当前目录和父目录,考虑从这个点下手,根目录的当前目录和父目录指向相同,也就是说这两个文件的描述符是一样的。

大体思路有了之后,来看下Linux中常用的目录操作的函数:

1 DIR *opendir(const char *)
2 struct dirent *readdir(DIR *)
3 int closedir(DIR *)

它们位于dirent.h头文件中。

再来看一下dirent的结构

1 struct dirent {
2     ino_t d_ino;            /* file number of entry */
3     __uint16_t d_reclen;        /* length of this record */
4     __uint8_t  d_type;      /* file type, see below */
5     __uint8_t  d_namlen;        /* length of string in d_name */
6     char d_name[__DARWIN_MAXNAMLEN + 1];    /* name must be no longer than this */
7 };

解决方案

开始动手编码,如下:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <string.h>
 4 #include <dirent.h>
 5 
 6 bool isRoot(const char* path)
 7 {
 8     if (strcmp(path, "/") == 0)
 9         return true;
10 
11     char dp[256] = {0};
12     int l = strlen(path);
13     memcpy(dp, path, l);
14 
15     if (dp[l - 1] != /)
16     {
17         dp[l] = /;
18         l += 1;
19     }
20 
21     DIR* d = opendir(dp);
22     if (!d)
23     {
24         printf("failed to open dir
");
25         return false;         
26     }                         
27                               
28     uint64_t dino = 0, ddino = 0;
29     while (dirent* ent = readdir(d))
30     {                         
31         if (strcmp(ent->d_name, "..") == 0)
32         {                     
33             ddino = ent->d_ino;
34         }
35         if (strcmp(ent->d_name, ".") == 0)
36         {
37             dino = ent->d_ino;
38         }
39 
40         if (dino > 0 && ddino > 0)
41             break;
42     }
43     return dino == ddino && dino != 0;
44 }
45 
46 int main(int argc, char* argv[])
47 {
48     if (argc != 2)
49     {
50         printf("usage : app path
");
51         return 0;
52     }
53 
54     if (isRoot(argv[1]))
55         printf("this path is root
");
56     else
57         printf("this path is not root
");
58     return 0;
59 }

编译

g++ -o root root.cpp

下面来验证一下

# ./root /
this path is root

# ./root ./
this path is not root

# ./root ./../
this path is not root

# ./root ./../../
this path is not root

# ./root ./../../../
this path is not root

# ./root ./../../../.. #注意,我的机器上这里其实已经是根目录了
this path is not root

奇怪的问题发生了,本应该通过的内容竟然不是根目录。进入代码,打印一下isRoot函数中.和..目录的name和ino。

. 2
.. 1

难道是假设错误?如果想要取得inode可以通过stat函数,那么我们该用stat函数试一下

int stat(const char *, struct stat *) 

修改代码后如下:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <string.h>
 4 #include <dirent.h>
 5 #include <sys/stat.h>
 6 
 7 bool isRoot(const char* path)
 8 {
 9     if (strcmp(path, "/") == 0)
10         return true;
11 
12     char dp[256] = {0};
13     int l = strlen(path);
14     memcpy(dp, path, l); 
15     
16     if (dp[l - 1] != /)
17     {   
18         dp[l] = /;
19         l += 1;
20     }   
21 
22     DIR* d = opendir(dp);
23     if (!d)
24     {   
25         printf("failed to open dir
");
26         return false;
27     }   
28     uint64_t dino = 0, ddino = 0;
29     while (dirent* ent = readdir(d))
30     {   
31         if (strcmp(ent->d_name, "..") == 0)
32         {   
33             char pp[256] = {0};
34             memcpy(pp, dp, l); 
35             pp[l] = .;
36             pp[l + 1] = .;
37             struct stat s;
38             stat(pp, &s);
39             //printf("ddot %s %lld
", ent->d_name, s.st_ino);
40             ddino = s.st_ino;
41         }   
42         if (strcmp(ent->d_name, ".") == 0)
43         {   
44             char sp[256] = {0};
45             memcpy(sp, dp, l); 
46             sp[l] = .;
47             struct stat s;
48             stat(sp, &s);
49             //printf("dot %s %lld
", ent->d_name, s.st_ino);
50             dino = s.st_ino;
51         }
52 
53         if (dino > 0 && ddino > 0)
54             break;
55     }
56     return dino == ddino && dino != 0;
57 }
58 
59 int main(int argc, char* argv[])
60 {
61     if (argc != 2)
62     {
63         printf("usage : app path
");
64         return 0;
65     }
66 
67     if (isRoot(argv[1]))
68         printf("this path is root
");
69     else
70         printf("this path is not root
");
71     return 0;
72 }
73                                  

再次编译验证,发现这次的结果是正确的。经过查证后发现,在使用readdir时取得的dirent中的iNode不一定是正确的,还需要从stat中取。

总结

到此就完成了目录是否为根目录的判断,需要对Linux的API慢慢进行熟悉。

以上是关于Linux驱动程序开发实例的目录的主要内容,如果未能解决你的问题,请参考以下文章

Linux程序开发中如何判断目录是否为根目录?

Linux驱动开发系列:整理入门Ubuntu知识

Linux驱动开发常用头文件

Linux驱动开发:字符设备驱动开发

Linux驱动开发:字符设备驱动开发

Linux驱动开发:字符设备驱动开发