5 c语言调用Linux的sleepy函数,Linux设备驱动程序学习

Linux设备驱动程序学习(5)
-高级字符驱动程序操作[(2)阻塞型I/O和休眠]
这一部分主要讨论:如果驱动程序无法立即满足请求,该如何响应?()
一、休眠
进程被置为休眠,意味着它被标识为处于一个特殊的状态并且从调度器的运行队列中移走 。这个进程将不被在任何 CPU 上调度,即将不会运行 。直到发生某些事情改变了那个状态 。安全地进入休眠的两条规则:
(1) 永远不要在原子上下文中进入休眠,即当驱动在持有一个自旋锁、或者 RCU 锁时不能睡眠;关闭中断也不能睡眠 。持有一个信号量时休眠是合法的,但你应当仔细查看代码:如果代码在持有一个信号量时睡眠,任何其他的等待这个信号量的线程也会休眠 。因此发生在持有信号量时的休眠必须短暂,而且决不能阻塞那个将最终唤醒你的进程 。
(2)当进程被唤醒,它并不知道休眠了多长时间以及休眠时发生什么;也不知道是否另有进程也在休眠等待同一事件,且那个进程可能在它之前醒来并获取了所等待的资源 。所以不能对唤醒后的系统状态做任何的假设,并必须重新检查等待条件来确保正确的响应 。
除非确信其他进程会在其他地方唤醒休眠的进程,否则也不能睡眠 。使进程可被找到意味着:需要维护一个称为等待队列的数据结构 。它是一个进程链表,其中饱含了等待某个特定事件的所有进程 。在 Linux 中,一个等待队列由一个 结构体来管理,其定义在中 。类型的数据结构非常简单:
{
lock;
;
};
;
它包含一个自旋锁和一个链表 。这个链表是一个等待队列入口,它被声明做。包含关于睡眠进程的信息和它想怎样被唤醒 。
简单休眠(其实是高级休眠的宏)
Linux 内核中最简单的休眠方式是称为 的宏(及其变种),它实现了休眠和进程等待的条件的检查 。形式如下:
(queue, )/*不可中断休眠,不推荐*/
ible(queue, )/*推荐,返回非零值意味着休眠被中断,且驱动应返回 -*/
(queue, , )
(queue, , )
/*有限的时间的休眠;若超时,则不管条件为何值返回0,*/
唤醒休眠进程的函数称为,形式如下:
void ( *queue);
void e( *queue);
惯例:用 唤醒;用 e 唤醒ible 。
简单休眠实验
模块程序链接:
模块测试程序链接:-test
实验现象:
[@]#cd /lib//
[@]# .ko
[@]#cd /dev/
[@]#cat /proc/
:
1 mem
2 pty
3 ttyp
4 /dev/vc/0
4 tty
4 ttyS
5 /dev/tty
5 /dev/
5 /dev/ptmx
7 vcs
10 misc
13 input
14 sound
81
89 i2c
90 mtd
116 alsa
128 ptm
136 pts
180 usb
189
204
252
253
254 rtc
Block :
1
256 rfd
7 loop
31
93 nftl
96 inftl
179 mmc
[@]#mknod -m 666c 252 0
[@]#cd /tmp/
[@]#./&
[@]#./&
[@]#ps
PID Uid VSZ Stat
1 root 1744 S init
2 root SW< []
3 root SWN [/0]
4 root SW< [/0]
5 root SW< [/0]
6 root SW< []
59 root SW< [/0]
60 root SW< []
63 root SW< [khubd]
65 root SW< []
77 root SW []
78 root SW []
79 root SW< []
80 root SW< [aio/0]
707 root SW< []
708 root SW< [nftld]
709 root SW< []
710 root SW< [rfdd]
742 root SW< []
751 root SW< [kmmcd]
769 root SW< [/0]
778 root 1752 S -sh
779 root 1744 S init
781 root 1744 S init
783 root 1744 S init
787 root 1744 S init
799 root 1336 S ./ root 1336 S ./
802 root 1744 R ps
[@]#./
read code=0
write code=0