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


[2] + Done ./
[@]#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 ./
804 root 1744 R ps
[@]#./
write code=0
[@]#read code=0
[1] + Done ./
[@]#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
806 root 1744 R ps
阻塞和非阻塞操作
全功能的 read 和 write 方法涉及到进程可以决定是进行非阻塞 I/O还是阻塞 I/O操作 。明确的非阻塞 I/O 由 filp-> 中的标志来指示(定义再,被 自动包含) 。浏览源码,会发现 的另一个名字:,这是为了兼容V 代码 。标志缺省地被清除,因为等待数据的进程的正常行为只是睡眠.
其实不一定只有read 和 write 方法有阻塞操作,open也可以有阻塞操作 。后面会见到 。而我的项目有一个和CPLD的接口的驱动,我决定要在ioctl 中使用阻塞 。
以下是后面的实验的有关阻塞的代码,我觉得写得很好,先结合书上的介绍看看吧:
while (dev->rp == dev->wp){ /*to read */
up(&dev->sem); /*the lock */
if (filp-> & )
-;
【5c语言调用Linux的sleepy函数,Linux设备驱动程序学习】("\"%s\" : going to sleep\n", ->comm);
if (ible(dev->inq, (dev->rp != dev->wp)))
-; /* : tell the fs layer toit */ /*loop, but firstthe lock */
if ((&dev->sem))
-;
}/* ok, data is there,*/
......
高级休眠
步骤:
(1)分配和初始化一个结构,随后将其添加到正确的等待队列 。
(2)设置进程状态,标记为休眠 。在 中定义有几个任务状态: 意思是进程能够运行 。有 2 个状态指示一个进程是在睡眠:和 E 。2.6 内核的驱动代码通常不需要直接操作进程状态 。但如果需要这样做使用的代码是:
void (int );
在老的代码中, 你常常见到如此的东西:->state = ; 但是象这样直接改变是不推荐的,当数据结构改变时这样的代码将会失效 。通过改变状态,只改变了调度器对待进程的方式,但进程还未让出处理器 。
(3) 最后一步是放弃处理器 。但必须先检查进入休眠的条件 。如果不做检查会引入竞态: 如果在忙于上面的这个过程时有其他的线程刚刚试图唤醒你,你可能错过唤醒且长时间休眠 。因此典型的代码下:
if (!)
();
如果代码只是从返回,则进程处于 状态 。如果不需睡眠而跳过对的调用,必须将任务状态重置为,还必要从等待队列中去除这个进程,否则它可能被多次唤醒 。
手工休眠
/* (1)创建和初始化一个等待队列 。常由宏定义完成:*/
();
/*name 是等待队列入口项的名字. 也可以用2步来做:*/