背景: 当内核空间的驱动收发数据需要通知用户空间时,有以下几种方法:
1.异步通知机制:
a. 在驱动层注册fasync函数
//fops
static struct file_operations global_logic_fops={
.owner = THIS_MODULE,
.unlocked_ioctl = logic_api_ioctl,
.open = logic_open_func,
.release = logic_release,
.write = logic_write,
.read = logic_read,
.fasync = logic_fasync_func,
};
b.驱动实现fasync函数static int logic_fasync_func(int fd, struct file *flip, int on)
{
int err;
/* 注意APP调用前,需要先通过ioctl接口,设置 g_logic_device_index */
err = fasync_helper(fd,flip,on,&pcm_fasync[g_logic_device_index]);
printk(KERN_ALERT "%s :%s index [%d]!\n", __FILE__, __func__, g_logic_device_index);
return err;
}
c.在需要发送消息的地方如下调用
static int pcm_Async(int channel)
{
/* 通知有数据 */
if(channel < MAX_LOGIC_DEVCIE_NUM)
{
kill_fasync(&(pcm_fasync[channel]), SIGIO, POLLIN);
}
return 0;
}
d.在用户态绑定信号服务函数
/* 异步信号处理函数 */
signal(SIGIO, logic_PCMHandler);
/* 设置驱动绑定对应的异步通知发生器,一个设备文件可以给多个进程发送信号,需要知道目前是绑定哪个 */
encoder_index = m31_GetEncodeIndex();
logic_SetDeviceIndex(encoder_index);
/* 将驱动发出的异步信号绑定到本进程 */
fcntl(g_LogicDevice, F_SETOWN, getpid());
flags = fcntl(g_LogicDevice, F_GETFL);
flags |= FASYNC;
fcntl(g_LogicDevice, F_SETFL, flags);