Linux设备驱动学习笔记

编译内核

$ 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 file
obj-m := test.o
# Makefile for two source files
obj-m := test.o
test-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.
else
	KERNELDIR ?= /lib/modules/$(shell uname -r)/build
	PWD := $(shell pwd)
all:
	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
	$(MAKE) -C $(KERNELDIR) M=$(PWD) clean
endif
/* 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; });

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值