1.Linux设备类型:字符设备,块设备,网络设备。
(1)字符设备
作为字节流来处理。至少实现open,close,read,write系统调用。在文件系统的/dev目录下。
(2)块设备
整块IO操作。与字符设备接口不同。在文件系统的/dev目录下。
(3)网络接口
网络接口一般是硬件,也可以是软件,如loopback。并不在文件系统/dev目录下,没有路径,通过名字如eth0来访问。
USB设备可以是字符设备(USB串口),块设备(U盘),网络设备(USB网卡)。
2.内核视图
3. 内核模块注册之后是为了接收接下来的请求,其初始化程序会马上结束。换言之,模块的初始化函数的作用是为后续调用模块函数功能做准备。模块的exit函数告诉内核,不能再调用模块的函数。
这种方法类似于事件驱动的编程,每个内核模块都是事件驱动的。模块的资源在调用exit的时候一定要释放,否则只能在系统重启后才会释放。
内核模块只能调用内核导出的函数,不能调用C的标准库函数,因为不会和libc链接。
内核的函数可以作为两种方式执行:系统调用、中断处理
4.Unix在调用系统调用或发生硬件中断的时候将执行从用户空间转到内核空间。
内核代码在一个进程的上下文中执行系统调用,这个进程代表调用进程,可以访问调用进程的地址空间。
5.打印日志不要太多,可用printk_ratelimit限制
if (printk_ratelimit( ))
printk(KERN_NOTICE "The printer is still on fire\n");
7. 进程突然退出后内核会为每个open的设备调用close函数释放资源。
8. 使用gdb调试内核时有许多限制,例如,不能修改内核数据,不能设置断点和观察点,也不能单步执行。为使gdb调试内核时获取到符号信息,需要编译内核时打开CONFIG_DEBUG_INFO,这样编译的内核会比一般的大许多。
9. kdb(或kgdb)可以可以加断点和修改数据。
10.字符设备指那些必须以串行顺序依次进行访问的设备,如触摸屏、磁带驱动器、鼠标等。块设备可以用任意顺序进行访问,以块为单位进行操作,如硬盘、软驱等。字符设备不经过系统的快速缓冲,而块设备经过系统的快速缓冲。但是,字符设备和块设备并没有明显的界限,如 Flash 设备符合块设备的特点,但是我们仍然可以把它作为一个字符设备来访问。
11. input事件类型
#define EV_SYN 0x00
#define EV_KEY 0x01
#define EV_REL 0x02
#define EV_ABS 0x03
#define EV_MSC 0x04
#define EV_SW 0x05
#define EV_LED 0x11
#define EV_SND 0x12
#define EV_REP 0x14
#define EV_FF 0x15
#define EV_PWR 0x16
#define EV_FF_STATUS 0x17
#define EV_MAX 0x1f
#define EV_CNT (EV_MAX+1)
12.GNU C对标准C进行一系列扩展,以增强标准C的功能。
1)GNU C 允许使用零长度数组,在定义变长对象的头结构时,这个特性非常有用
3)GNU C支持case x…y这样的语法,区间[x,y]中的数都会满足这个case的条件
4)GNU C把包含在括号中的复合语句看成是一个表达式,称为语句表达式,它可以出现在
任何允许表达式的地方。我们可以在语句表达式中使用原本只能在复合语句中使用的循环、
局部变量等
6)在GNU C中,宏也可以接受可变数目的参数
<span style="font-size:18px;">#define pr_debug(fmt,arg...) \
printk(fmt,##arg)</span>
使用“##”是为了处理arg不代表任何参数的情况,这时候,前面的逗号就变得多余了。使用“ ##”之后,GNU C预处理器会丢弃前面的逗号
7)标准C要求数组或结构体的初始化值必须以固定的顺序出现,在GNU C 中,通过指定
索引或结构体成员名,允许初始化值以任意顺序出现。指定数组索引的方法是在初始化
方法。要指定一个声明的属性,只需要在声明后添加 _ _attribute_ _ (( ATTRIBUTE ))。其
中 ATTRIBUTE 为属性说明,如果存在多个属性,则以逗号分隔。
译器产生警告信息。
aligned属性用于变量、结构体或联合体,指定变量、结构体或联合体的对齐方式,以字
节为单位
packed属性作用于变量和类型,用于变量或结构体成员时表示使用最小可能的对齐,用
于枚举、结构体或联合体类型时表示该类型使用最小的内存。
9)内建函数_ _builtin_expect(EXP, C)用于为编译器提供分支预测信息,其返回值是整数
表达式 EXP 的值, C 的值必须是编译时常数。
10)do{} while(0)的使用完全是为了保证宏定义的使用者能无编译错误
地使用宏,它不对其使用者做任何假设。
<span style="font-size:18px;">EXPORT_SYMBOL(符号名);
EXPORT_SYMBOL_GPL(符号名);</span>
17、lseek返回文件指针相对于文件头的位置,下列调用返回文件长度
<span style="font-size:18px;">lseek(fd, 0, SEEK_END);</span>
18、DOS、Windows中区分二进制文件和文本文件,Linux中不区分。