Linux设备驱动学习笔记

来源:互联网 发布:淘宝网刀具图片和价格 编辑:程序博客网 时间:2024/05/06 17:28

编译内核

$ tar xvf linux-3.0.tar.bz2
$ cd linux-3.0
$ cp -vi /boot/config-`uname -r` .config
$ make localmodconfig (参见:Easy local kernel configuration)
$ make -j4 (增加编译速度)
$ sudo make modules_install$ sudo make install
$ sudo update-initramfs -u -k 3.0.0 (如果在/boot下没有生成initrd.img-3.0.0文件)

编译内核的外部模块(自己写的模块)

在$HOME的module目录下创建Makefile和test.c
# Makefile for single source fileobj-m := test.o
# Makefile for two source filesobj-m := test.otest-objs := file1.o file2.o
# Makefile from the Linux Device Drivers# If KERNELRELEASE is defined, we've been invoked from the# kernel build system and can use its language.ifneq ($(KERNELRELEASE),)obj-m := simple.o# Otherwise we were called directly from the command# line; invoke the kernel build system.elseKERNELDIR ?= /lib/modules/$(shell uname -r)/buildPWD := $(shell pwd)all:$(MAKE) -C $(KERNELDIR) M=$(PWD) modulesclean:$(MAKE) -C $(KERNELDIR) M=$(PWD) cleanendif
/* test.c */#include <linux/init.h>#include <linux/module.h>MODULE_LICENSE("Dual BSD/GPL");static int test_init(void){        printk(KERN_ALERT "Hello, world\n");        return 0;}static void test_exit(void){        printk(KERN_ALERT "Goodbye, cruel world\n");}module_init(test_init);module_exit(test_exit);
编译模块
$ make -C /lib/modules/`uname -r`/build M=`pwd` modules

内核编程时的注意点

  1. Applications are laid out in virtual memory with a very large stack area. The stack, of course, is used to hold the function call history and all automatic variables created by currently active functions. The kernel, instead, has a very small stack; it can be as small as a single, 4096-byte page. Your functions must share that stack with the entire kernel-space call chain. Thus, it is never a good idea to declare large auto-matic variables; if you need larger structures, you should allocate them dynamically at call time.
  2. <linux/config.h>已经过时了,可以删除源代码中的相关引用。
  3. container_of的作用: cast a member of a structure out to the containing structure。我的理解是,根据结构体中的一个成员(的地址),获取这个结构体(的地址)。参考信息
  4. 通过/proc和ioctl获取(调试)信息的优缺点对比
    a. /proc相对简单
    b. ioctl更高效。In addition, ioctl doesn’t require splitting data into fragments smaller than a page.
    c. ioctl命令常駐于驱动中,如果没有文档说明,用户几乎不会知道它们的存在。相对地,通过/proc来获取调试信息的话,通常是在DEBUG版本下进行的,而且所有的用户都可以访问这些调式信息。
  5. 避免Race Condition的经验法则
    a. 如果可能,尽量避免共享的资源,比如避免使用全局变量。
    b. 全局变量远不是共享资源的唯一形式。比如,任何时候你的代码向内核的其它部分传递了一个指针,就创建了一个潜在的共享资源。共享是不可争辩的事实。
    c. Here is the hard rule of resource sharing: any time that a hardware or software resource is shared beyond a single thread of execution, and the possibility exists that one thread could encounter an inconsistent view of that resource, you must explicitly manage access to that resource.
  6. Note the check on the return value of down_interruptible
    If it returns nonzero, the operation was interrupted. The usual thing to do in this situation is to return -ERESTARTSYS. Upon seeing this return code, the higher layers of the kernel will either restart the call from the beginning or return the error to the user. If you return -ERESTARTSYS, you must first undo any user-visible changes that might have been made, so that the right thing happens when the system call is retried. If you cannot undo things in this manner, you should return -EINTR instead.
  7. Sleeping
    Never sleep when you are running in an atomic context.
  8. Exclusive waits
    Employing exclusive waits within a driver is worth considering if two conditions are met: you expect significant contention for a resource, and waking a single process is sufficient to completely consume the resource when it becomes available.

内核代码理解


braced-group within expression
/* so, i = 100 */int i = ({ int k = 1; k += 99; });

原创粉丝点击