当前位置: 技术问答>linux和unix
还是不懂,驱动到底如何能同步的发送信号给用户程序,请教高人,谢谢了
来源: 互联网 发布时间:2016-03-20
本文导语: 我驱动完成一个操作后要马上发送一个数据或者说是信号给用户程序,通知用户程序完成另一部分操作,这两部分都是我自己写的,现在就是不知道驱动如何通知用户程序,或者直接驱动如果能调用用户程序也可以。...
我驱动完成一个操作后要马上发送一个数据或者说是信号给用户程序,通知用户程序完成另一部分操作,这两部分都是我自己写的,现在就是不知道驱动如何通知用户程序,或者直接驱动如果能调用用户程序也可以。 上次发的帖子里有人说用阻塞的方法? 具体要怎么用? 因为我看了下信号是不行了,信号要进程的PID,但是又找不到其他方法,请有经验的指导下,谢谢了!
|
用file_operations的poll接口去实现,内部会用到一个wait queue。当然也可以不在poll里接口里实现,可以增加一个ioctl来实现,但内部一样可以用wait queue。应用程序通过select接口,或者自定义的ioctl接口来等待(休眠)直到可以读取设备的数据。一般在中断里wake up这个队列,从而唤醒应用程序继续下面的动作。
|
建议看LDD linxu设备驱动程序第五章--高级字符设备驱动程序-阻塞读写
信号不能用于驱动和应用程序同步
但你可以让用户程序在内核态阻塞
这时后驱动就可以和用户程序实现同步了
信号量也可以实现同步,但在内核中其互斥更多
建议用等待队列,ls说得很有道理
下面给个实际例子:
static ssize_t at91_mcp2510_read(struct file *filp, char *buffer, size_t count, loff_t *ppos)
{
CanData candata_ret;
retry:
if (mcp2510dev.nCanReadpos != mcp2510dev.nCanRevpos) {
。。。。
return count;
} else {
if (filp->f_flags & O_NONBLOCK)
interruptible_sleep_on(&(mcp2510dev.wq));
//应用程序read系统调用后在此休眠等待唤醒
if (signal_pending(current))
return -ERESTARTSYS;
goto retry;
}
return sizeof(candata_ret);
}
static void at91_isr_mcp2510(int irq, void * dev_id, struct pt_regs * reg)
{
if ((mcp2510_isr & AT91C_PIO_PC14) ||MCP2510_IRQ_flag) /* this interrupt is shared! Is it ours? */
{
。。。。。。。。。。。
if((AT91_SYS->PIOC_PDSR&AT91C_PIO_PC14?0:1))
{
。。。。。。。。。
if(byte & (RX0INT|RX1INT)){
/////////////////
wake_up_interruptible(&(mcp2510dev.wq);
在中断中此实现同步,唤醒read进程
/////////////////
DPRINTK("Wake up at91_mcp2510_read!n");
}
//else
//MCP2510_WriteBits(CANINTF, 0, 0xff); // Clear other interrupts
}
}
}
信号不能用于驱动和应用程序同步
但你可以让用户程序在内核态阻塞
这时后驱动就可以和用户程序实现同步了
信号量也可以实现同步,但在内核中其互斥更多
建议用等待队列,ls说得很有道理
下面给个实际例子:
static ssize_t at91_mcp2510_read(struct file *filp, char *buffer, size_t count, loff_t *ppos)
{
CanData candata_ret;
retry:
if (mcp2510dev.nCanReadpos != mcp2510dev.nCanRevpos) {
。。。。
return count;
} else {
if (filp->f_flags & O_NONBLOCK)
interruptible_sleep_on(&(mcp2510dev.wq));
//应用程序read系统调用后在此休眠等待唤醒
if (signal_pending(current))
return -ERESTARTSYS;
goto retry;
}
return sizeof(candata_ret);
}
static void at91_isr_mcp2510(int irq, void * dev_id, struct pt_regs * reg)
{
if ((mcp2510_isr & AT91C_PIO_PC14) ||MCP2510_IRQ_flag) /* this interrupt is shared! Is it ours? */
{
。。。。。。。。。。。
if((AT91_SYS->PIOC_PDSR&AT91C_PIO_PC14?0:1))
{
。。。。。。。。。
if(byte & (RX0INT|RX1INT)){
/////////////////
wake_up_interruptible(&(mcp2510dev.wq);
在中断中此实现同步,唤醒read进程
/////////////////
DPRINTK("Wake up at91_mcp2510_read!n");
}
//else
//MCP2510_WriteBits(CANINTF, 0, 0xff); // Clear other interrupts
}
}
}