当前位置: 技术问答>linux和unix
Linux内核信号量和定时器问题请教:
来源: 互联网 发布时间:2016-07-29
本文导语: 正在学习用户态线程和内核态定时器的使用,有个问题请教大家: 我在用户空间建立了一个线程,内核做一个字符驱动模块,通过ioctl调用来不断读取内核定时器有没有 到期。在设备结构体里面加了一个信号量,在open调用...
正在学习用户态线程和内核态定时器的使用,有个问题请教大家:
我在用户空间建立了一个线程,内核做一个字符驱动模块,通过ioctl调用来不断读取内核定时器有没有
到期。在设备结构体里面加了一个信号量,在open调用的时候把信号量拿到,使用一个内核定时器,在内
核定时器到期的处理函数里面释放信号量,这样用户线程调ioctl的时候就获取不到信号量了,等定时器
超时了,就会释放信号量,这样ioctl就返回到用户空间了,可是下次再调用ioctl的时候就不等待信号量了,不知道为什么??
不知道这样做行不行,看书上好像都是两个内核线程间用信号量来通信,请大家指教,谢谢!
void timer_handle(void)
{
int i = 0;
mod_timer(&KDA_devp->s_timer,jiffies + HZ * 5); /*重新改变定时器的超时时间*/
up(&KDA_devp->sem); /*释放信号量,ioctl调用可以获取到该信号量*/
}
int KDA_open(struct inode *inode, struct file *filp)
{
struct KDA_dev *dev; /* device information */
dev = container_of(inode->i_cdev, struct KDA_dev, cdev);
filp->private_data = dev; /* for other methods */
init_timer(&KDA_devp->s_timer);
KDA_devp->s_timer.function = &timer_handle;
KDA_devp->s_timer.expires = jiffies + HZ * 5;
add_timer(&KDA_devp->s_timer); /*添加(注册)定时器*/
down_interruptible(&dev->sem); /*获取信号量*/
return 0;
}
int KDA_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
int err = 0;
int isr_num = 100;
struct KDA_dev *dev = filp->private_data;
printk("want to get sem n");
down_interruptible(&dev->sem);
switch(cmd)
{
case 1 :
printk("the case 1 n");
break;
case 2 :
printk("the case 2 n");
break;
case 3 :
__put_user(KDA_devp->ISR_flag, (int __user *)arg);
break;
default:
printk("the default case n");
}
}
|
我个人觉得你这样做应该能实现你要的效果,但是逻辑上有点问题,理由如下:
1、信号量适用于进程间通信,而你这里实际上只有一个进程,即用户态创建的进程(你写成了线程)。这个进程和内核之间进行通过驱动接口进行数据交流,这个过程中并没有引入新的进程。其实简单化来看:这个模型的工作就是在进程里面先down()了一下,然后再up()一下,在down和up这段时间间隔内,轮询的查看信号量是否可用。但是信号量的真正作用确是用于进程间的通信,所以说你的效果应该能实现,但是逻辑上有点问题。
2、再分析下你这个模型,轮询的查看,这个很浪费CPU的资源。而根据你的设计,似乎用condition更合适一些。即先down()一下,然后用户态的进程就在那里阻塞着,什么时候定时器超时了,这个时候再产生一个condition,通知用户态的进程:我完事了,到你了。这时候用户态的进程再执行其他的操作。这样似乎效率更高一些。逻辑上也合理一些。
以上只是个人分析,未必全面,欢迎拍砖。
PS:这个确实是个挺不错的问题!
1、信号量适用于进程间通信,而你这里实际上只有一个进程,即用户态创建的进程(你写成了线程)。这个进程和内核之间进行通过驱动接口进行数据交流,这个过程中并没有引入新的进程。其实简单化来看:这个模型的工作就是在进程里面先down()了一下,然后再up()一下,在down和up这段时间间隔内,轮询的查看信号量是否可用。但是信号量的真正作用确是用于进程间的通信,所以说你的效果应该能实现,但是逻辑上有点问题。
2、再分析下你这个模型,轮询的查看,这个很浪费CPU的资源。而根据你的设计,似乎用condition更合适一些。即先down()一下,然后用户态的进程就在那里阻塞着,什么时候定时器超时了,这个时候再产生一个condition,通知用户态的进程:我完事了,到你了。这时候用户态的进程再执行其他的操作。这样似乎效率更高一些。逻辑上也合理一些。
以上只是个人分析,未必全面,欢迎拍砖。
PS:这个确实是个挺不错的问题!
|
一般性思路: 应用程序调用驱动,通常在驱动里加入同步机制,例如用信号量加条件变量。
有数据需要应用程序处理时,驱动就唤醒应用程序,否则使应用程序睡眠(挂起)。这种异步的做法比较节省资源,比应用程序轮询高效得多。
有数据需要应用程序处理时,驱动就唤醒应用程序,否则使应用程序睡眠(挂起)。这种异步的做法比较节省资源,比应用程序轮询高效得多。