linux设备学习学习(一)
linux设备学习学习(一)
2010年08月23日
地球人都知道LDD这书经典,但一直没时间看(貌似是借口)现在开始啃,希望自己能坚持下去。God bless me!
要看到内核的打印信息,可以先执行下面的语句:echo 8 >/proc/sys/kernel/printk
这里,有blog不错,可以学习下http://blog.chinaunix.net/u1/34474/showart_404278. html
由于驱动程序可能同时被不同的程序并发访问,解决并发的一些方法:1.可以在设备上实现独立于硬件功能的内存映射。
2. 为用户提供独立的函数库,运用同步原语。
3.设备文件和普通文件之间的唯一区别在于:对普通文件的访问可以前后移动访问访问位置,但对大多数字符设备文件的访问只能顺序访问。
4.许多网络连接是面向流的,但网络设备却围绕数据包的传输和接受而设计。网络驱动程序不需要知道各个连接的相关信息,他只要处理数据包即可。由于不是面向流的设备,因此将网络接口映射到文件系统中的节点比较困难,linux访问网络接口的方法仍然是给他们一个唯一的名字(eth0),但这个名字在文件系统中不存在对应的节点。内核和网络设备的通信,不同于字符和块设备,内核调用一套和数据包传输相关的函数,而不是read,write.
5.关于hello模块Makefile的写法:
obj-m += hello.o
KDIR = /lib/modules/$(shell uname -r)/build
PWD = $(shell pwd)
all:
make -C $(KDIR) M=$(PWD) modules
clean:
make -C $(KDIR) M=$(PWD) clean
如果是多个原文件编译出一个模块,则不能出现.c 文件。
obj-m += test.o
test.o := file1.o file2.o file3.o
KDIR = /lib/modules/$(shell uname -r)/build
PWD = $(shell pwd)
all:
make -C $(KDIR) M=$(PWD) modules
clean:
make -C $(KDIR) m=$(PWD) clean
其中KDIR为内核存放的路径,PWD当前路径,uname -r为取得当前使用的内核配置。
6.现代的unix系统基本提供两种保护方式:一种是特权级划分,0到6个级别,ROOT的特权级最高。另一种是分页保护机制,系统除了在启动完成设备初始化时运行在实模式下外,启动起来会开启MMU然后运行在保护模式下。
7.执行系统调用的内核代码运行在进程上下文中,它代表调用进行执行操作,因此可以访问进程地址空间里的所有数据,而处理硬件中断的内核代码和进程是异步的,与任何一个特定进程无关。
8.modprobe和insmod的区别,它会考虑要装载的模块是否引用了一些当前内核不存在的符号。如果有这类引用modprobe会在当前模块的收索路径中查找定义了这些符号的其他模块,如果找到这些依赖模块会同时将这些模块加载到内核中。如果这种情况下用insmod,则会失败。
9.大多数模块都必须包括的头文件:
#include
#include
#include
10.如果在发生某个特定类型的错误以后无法继续装载模块,则要将出错之前的任何注册工作撤销掉。
模块注册代码示例:
#include
#include
#include
struct something *item1;
struct somethingelse *item2;
int stuff_ok;
void my_cleanup()
{
if(item1)
release_thing(item1);
if(item2){
release_thing(item2);
if(stuff_ok)
unregister_stuff;
}
static int __init my_init(void)
{
int err;
item1 = allocate_thing(arguments);
item2 = allocate_thing(arguments2);
if(!item1 || !item2)
goto fail;
err = register_stuff(item1,item2);
if(!err){
stuff_ok = 1;
}else{
goto fail; } return 0; fail: my_cleanup(); return err; } 11.include 该文件包含驱动驱动程序中使用的大部分内核API的定义,包括睡眠函数以及各种变量的声明。
struct task_struct *current;
current->pid
current->comm
获得当前进程的id和命令名
MAJOR(dev_t dev);
MINOR(dev_t dev);
MKDEV(int major,int minor);