《Linux设备设备驱动程序(第三版)》学习笔记之三:sleepy设备的使用

 
By: 吴垠
Date: 2007-07-05
Email: lazy.fox.wu#gmail.com
Homepage: http://blog.csdn.net/wooin
Copyright: 该文章版权由吴垠所有。可在非商业目的下任意传播和复制。
对于商业目的下对本文的任何行为需经作者同意。
联系方式:lazy.fox.wu#gmail.com
1. 写在前面:
a. 在进行下面的工作之前请先阅读我 的文章《在 Linux 2.6内核下编译可以加载的内核模块》,配 置好可加载内核模块的Linux环境
b. 下载《Linux设备设备驱动程序(第三版)》配套的源代 码,在这里可 以下载到,如果无法下载的话可以留言或者给我发邮件索取。
c. 本文的工作环境是Fedora Core 5,用“uname -r”查看内核版本是:2.6.15-1.2054_FC5
d. 本文主要针对的是《Linux设备设备驱动程序(第三 版)》中第六章:高级字符设备驱动程序操作,第151页中举了个例子用来说明简单的休眠,本文记录了我对该例子的实现和运行。
e. 下文的有些操作需要root权限,所以请尽量用root用 户来执行命令。

2. 源代码包解压后进入misc-modules文件夹,其中的文件有:
[wooin@15:05 misc-modules]$ pwd
/home/wooin/ldd.3rd.examples/misc-modules
[wooin@15:06 misc-modules]$ ll
总计 60K
-rw-r--r-- 1 wooin bao 2.1K 2005-02-01 04:31 complete.c
-rw-r--r-- 1 wooin bao 2.0K 2005-02-01 04:31 faulty.c
-rw-r--r-- 1 wooin bao  463 2005-02-01 04:31 hello.c
-rw-r--r-- 1 wooin bao 1.2K 2005-02-01 04:31 hellop.c
-rw-r--r-- 1 wooin bao 6.1K 2005-02-01 04:31 jiq.c
-rw-r--r-- 1 wooin bao 7.4K 2005-02-01 04:31 jit.c
-rw-r--r-- 1 wooin bao 2.3K 2005-02-01 04:31 kdataalign.c
-rw-r--r-- 1 wooin bao 1.5K 2005-02-01 04:31 kdatasize.c
-rw-r--r-- 1 wooin bao  987 2005-02-01 04:31 Makefile
-rw-r--r-- 1 wooin bao 2.0K 2005-02-01 04:31 seq.c
-rw-r--r-- 1 wooin bao 6.1K 2005-02-01 04:31 silly.c
-rw-r--r-- 1 wooin bao 2.2K 2005-02-01 04:31 sleepy.c
其中sleepy.c就是本文要讲的文件,先打开该文件,将printk()函数中的“KERN_DEBUG1”改为
“KERN_ALERT”,保存退出,这是为了可以在/var/log/messages 文件中看到调试信息。
3. 编译:
直接在misc-modules目录下运行make命令就可以编译通过,如果编译有问题请看我的这篇文章
《在 Linux 2.6内核下编译可以加载的内核模块 》
编译成功后会生成很多文件,其中有一个sleepy.ko,就是我们要的内核模块,其部分源码在《Linux设备设备驱动程序(第三 版)》中第六章:高级字符设备驱动程序操作,第151页。
4. 将设备添加到内核中去:
运行命令:
# ismod sleepy.ko
将其添加到内核中去,此时内核已经可以认出sleepy设备了,但是我们用户却无法访问,因为目前在用户空间中还没有sleepy这个设备,也就是说在 /dev/中还没有sleepy设备,需要我们手动添加。首先查看
/proc/devices文件找到sleepy设备,并找到其主设备号,比如:
[root@FOX misc-modules]# cat /proc/devices
Character devices:
  1 mem
  4 /dev/vc/0
  4 tty
  4 ttyS
     :
     :
180 usb
189 usb_device
226 drm
253 sleepy     # 查到sleepy的主设备号是253
254 pcmcia

Block devices:
  1 ramdisk
  1 ramdisk
  3 ide0
  7 loop
  8 sd
     :
     :
再在/dev/目录中创建sleepy设备:
// 其中253是主设备号,你可以根据你的情况自己修改这个值,0是次设备号
# mknod /dev/sleepy c 253 0

// 查看我们新添加的设备
# ls -l /dev/sleepy
crw-r--r-- 1 root root 253, 0 08-03 15:34 /dev/sleepy

5. 试试设备:
根据书中介绍,sleepy设备是用来演示简单休眠的:当读该设备的时候进程会进入休眠状态,直到有其他进程写该设备,读进程才会被唤醒,我们来读 sleepy设备:
# dd if=/dev/sleepy of=~/temp
上面命令的意思是从/dev/sleepy设备中读取数据,并写到 ~/temp文件中,当按下回车键后,命令行就被挂起了,想死掉了一样,查看/var/log/messages文件可以看到类似下面的内 容:
“Aug  3 15:58:20 FOX kernel: process 13534 (dd) going to sleep”
这个是sleepy.c中函数sleepy_read()里的调试信息,告诉你进程已经sleep了

此时我们打开另一个终端运行下面的命令来写sleepy设备:
# ll > /dev/sleepy
该命令会马上返回,并且在/var/log/messages文件中输出调试信 息:
“Aug  3 16:05:22 FOX kernel: process 13583 (ls) awakening the readers...”
这个是sleepy.c中函数sleepy_write()里的调试信息,告诉你当前进程开始唤醒读进程了。

我们再回过头看看刚才挂起的读操作,发现“dd if=/dev/sleepy of=~/temp”命令已经返回了,并且在/var/log/messages文件中输出调试信息:
Aug  3 16:05:22 FOX kernel: awoken 13534 (dd)
这个是sleepy.c中函数sleepy_read()里的调试信息,告诉你进程已经被唤醒了
6. 相关代码:
跟踪一下printk打印出来信息的先后顺序,就可以大致了解整个“休眠”和“唤醒”的过程了。
34 ssize_t sleepy_read (struct            char __user *buf, size_t count, loff_t *pos)
35 {
36 printk(KERN_ALERT "process %i (%s) going to sleep/n",
37 current->pid, current->comm);
38 wait_event_interruptible(wq, flag != 0);
39 flag = 0;
40 printk(KERN_ALERT "awoken %i (%s)/n", current->pid, current->comm);
41  return 0; /* EOF */
42 }
43 
44 ssize_t sleepy_write (struct file *filp, const char __user *buf, size_t count,
45 loff_t *pos)
46 {
47 printk(KERN_ALERT "process %i (%s) awakening the readers.../n",
48 current->pid, current->comm);
49 flag = 1;
50 wake_up_interruptible(&wq);
51  return count; /* succeed, to avoid retrial */
52

7.  
8.  
9.  
   
   

你可能感兴趣的:(linux,工作,Date,struct,user,email)