“阻塞和非阻塞的定义”阻塞操作是指当设备运行时,如果不能获得资源,进程将被暂停,直到满足运行条件。挂起的进程进入睡眠状态,并从调度程序的运行队列中移除,直到满足等待条件。
当不能执行设备操作时,不暂停非阻塞操作的过程。
"阻塞实例"
多个进程驱动全局变量,有些是读的,有些是写的,并使用阻塞机制来确保只有在一个进程写了之后,其他进程才能读这个变量。
# include # include # include # include # include #包含
MODULE _ LICENSE(“GPL”);
#定义专业编号254
静态ssize_t global var _ read(struct file *,char *,size _ t,loff _ t *);静态ssize_t global var _ write(struct file *、const char *、size _ t、loff _ t *);
struct file _ operations global var _ fops={ read:global var _ read,write: globalvar_write,};
静态int global _ var=0;静态结构信号量sem静态wait _ queue _ head _ t outq//定义等待队列头静态int flag=0;//阻塞条件static int _ _ initglobalvar _ init(void)
{ int retret=register_chrdev(MAJOR_NUM,' globalvar 'global var _ fops);如果(返回)
{ printk('globalvar注册失败');} else { printk('globalvar注册成功');初始化互斥体(SEM);init _ wait queue _ head(outq);ret返回;}静态void __exit globalvar_exit(void)
{ int retret=unregister _ chrdev(MAJOR _ NUM,' global var ');如果(返回)
{ printk('globalvar unregister失败');} else { printk(' global var unregister成功');}
静态ssize _ t global var _ read(struct file * filp,char *buf,size_t len,loff_t *off)
{//等待数据获取if(wait _ event _ interruptible(outq,flag!=0))//这里让调用自己的进程进入挂起状态,直到full//foot { return-ERESTARTSYS;后面的条件出现才离开挂起状态;} if (down_interruptible(sem))
{ return-ERESTARTSYS;} flag=0;//阻塞条件在这里发生了变化,也就是说这个变量一次只能读取一次,除非再给这个//变量赋一个新值。
if (copy_to_user(buf,global_var,sizeof(int)))
{ up(SEM);返回-默认;} up(SEM);返回sizeof(int);}
静态ssize _ t global var _ write(struct file * filp,const char *buf,size_t len,loff_t *off)
{ if (down_interruptible(sem))
{ return-ERESTARTSYS;} if (copy_from_user(global_var,buf,sizeof(int)))
{ up(SEM);返回-默认;} up(SEM);flag=1;//这里改变了阻塞条件,意味着可以挂起的进程可以解除。/*通知数据可用。之前调用drive read函数的进程被调整为挂起状态,只有满足条件才会摆脱挂起状态。请注意,没有自动检测条件的机制,也没有在条件改变时自动通知内核改变进程状态的机制。相反,我们需要调用函数来手动唤醒等待队列。队列将检测条件。如果条件满足,该进程将被解除。如果不满足条件,进程仍将被密封。
*/wake _ up _ interruptible(outq);返回sizeof(int);}模块_初始化(global var _ init);模块_出口(全局变量_出口);
这里有个问题。等待队列中应该有多个密封的进程。在这种情况下:1。后面的过程可以被前面的过程提前解除吗?
2.每次通过函数尝试唤醒队列时,队列对条件的检测机制是什么?你一个一个检查条件吗?
用于测试该驱动程序的参考应用程序是“Reader”
# include # include # include # include main()
{ int fd,numfd=open('/dev/globalvar 'O_RDWR,S _ I rusr | S _ IWUSR);如果(fd!=- 1)
{ while (1)
{ read(fd,num,sizeof(int));//除非有全局变量的输入printf ('the globalvar is% d \ n 'num),否则程序将在此语句中阻塞;//如果输入为0,则退出if (num==0)
{ close(FD);打破;} else { printf('设备打开失败\ n ');}
“编写程序”
# include # include # include # include main()
{ int fd,numfd=open('/dev/globalvar 'O_RDWR,S _ I rusr | S _ IWUSR);如果(fd!=- 1)
{ while (1)
{ printf('请输入全局变量:\ n’);scanf('%d '编号);write(fd,num,sizeof(int));//如果输入0,退出如果(数量==0)
{ close(FD);打破;} else { printf('设备打开失败\ n’);}