linux设备驱动程序(第三版)阅读笔记(二)

来源:互联网 发布:ubuntu 安装deb 编辑:程序博客网 时间:2024/05/21 10:48

 

说明:版权所有归作者,只供学习交流,若有其它用途请联系作者,转载请遵守IT人职业规范,请注明转载地址

 

第二章:构造和运行模块

1,(printk函数的说明)函数printklinux内核中定义,功能和标志c库中的函数printf类似。内核需要自己单独的打印输出函数,这是因为它在运行的时候不能依赖于c库。模块能够调用printk是因为在insmod函数装入模块后,模块就连接到了内核,因而可以访问内核的公用符号。

 

2,(事件驱动应用程序和内核代码之间的不同)事件驱动的应用程序和内核代码之间的一个主要不同是:应用程序退出时,可以不管资源的释放或者其他的清除工作,但模块的退出函数却必须仔细撤销初始化函数所做的一切,否则,在系统重新引导之前某些东西就会残留在系统中。

 

3,(应用程序和模块的区别)应用程序可以调用它并未定义的函数,这是因为连接过程能够解析外部引用从而使用适当的函数库。例如,定义在libc中的printf函数就是这种可被调用的函数之一。然而,模块仅仅被链接到内核,因此他能调用的函数仅仅是由内核导出的那些函数,而不存在任何可链接的函数库。

 

4,(printf和printk的区别)(1)printk函数有优先级,printf没有;(2)printfprintk的最大的区别在于printk缺乏对浮点数的支持。

 

5,(内核编程和应用程序编程的不同)内核编程和应用程序编程

的另外一点重要的不同之处在于各坏境下处理错误的方式不同:

应用程序开发过程中的段错误是无害的,并且总是可以使用调试

器跟踪到源代码中的问题所在,而一个内核错误即使不影响整个

系统,也至少会杀死当前进程。

 

6,(内核编程区别于用户空间的编程)应用程序在虚拟内存中布局,

并具有很大的一块栈空间。当然,栈是用来保存函数调用历史以

及当前活动函数的自动变量。而相反的是,内核具有非常小的栈,

它可能只有一个4096个字节大小的页那样少。我们自己的函数必

须和整个内核空间调用链一同共享这个栈。因此声名大的自动变

量并不是一个好主意,如果我们需要大的结构,则应该在调用时

动态分配该结构。

 

7,(关于浮点数的运算)内核代码不能实现浮点数运算。如果打开了浮点支持,在某些架构上,需要在进入和退出内核空间时保存和恢复浮点处理器的状态。这种额外的开销没有任何的价值,内核代码中也不需要浮点运算。

 

8,(insmod和modprobe的区别)insmod类似,modprobe也用来将模块装载到内核中。它和insmod的区别在于,他会考虑要装载的模块是否引用了一些当前内核不存在的符号。如果有这类引用,modprobe会在当前模块搜索路径中查找定义了这些符号的其他模块。如果modprobe找到了这些模块(即要转载的模块所依赖的模块),它会同时将这些模块装载到内核。如果在这种情况下使用insmod,则该命令会失败,并在系统日志文件中记录“unresolved symbols(未解析的符号)”消息。

 

9,(内核符号导出EXPORT_SYMBOL和EXPORT_SYMBOL_GPL)这两个宏均用于将给定的符号导出到模块外部。_GPL版本使得要导出的模块只能被GPL许可证下的模块使用。符号必须在模块文件的全局部分导出,不能再函数中导出,这是因为上面这两个宏将被扩展为一个特殊变量的声明,而该变量必须是全局的。

10,(关于__init和__exit)__init修饰的函数就是告诉内核,该函数仅在初始化期间使用。在模块被装载之后,模块初始化函数就会将初始化函数扔掉,这样可将该函数占用的内存释放出来,以作它用。被__exit修饰的代码仅用于模块卸载(编译器将把该代码放在特殊的ELF段中)。如果模块被直接内嵌到内核中,或者内核的配置不充许卸载模块,则被标志为__exit的函数将被简单的丢弃。所以,被标志位__exit的函数只能在模块被卸载或者系统关闭的时候调用,其他的任何用法都是错误的。

11,(关于Makefile如果我们想不以源文件名命名模块,则

obj-m := module.o

module-objs := file1.o file2.o这样生成的模块的名字为module.ko而不是默认的文件名加点ko。

 

原创粉丝点击