我有一个用于虚拟设备的char设备驱动程序。我想在设备驱动程序中使用FIFO,以便使用设备驱动程序的2个进程可以在它们之间传输字符。我试过kfifo,但我是新手,发现很难使用。任何人都可以建议在Linux驱动程序中实现FIFO的其他方法。
答案 0 :(得分:2)
如果您只允许两个进程使用驱动程序,那么您可以这样做:
在open
处理程序中,确保只有两个进程可以进入驱动程序:
If access mode = READ and not alreadyreading then
alreadyreading = 1
else
return -EBUSY
If access mode = WRITE and not alreadywritting then
alreadywritting = 1
else
return -EBUSY
在同一个处理程序中,初始化FIFO(可能只是一个全局字符变量)和两个等待队列:一个用于读取,一个用于写入。与这些队列相关联的是两个变量:ready_to_read和ready_to_write。在开始时,ready_to_read = 0和ready_to_write = 1。
然后,在release
处理程序中:
If access mode = READ
alreadyreading = 0;
If access mode = WRITE
alreadywritting = 0
允许新进程以读或写模式打开设备。
在write
处理程序中:
If access mode = READ then // we only support writting if the access mode is write
return -EINVAL
Else
res = wait_event_interruptible (write_queue, ready_to_write);
if (res)
return res; // if process received a signal, exit write
Take a single character from user space (copy_from_user() )
Copy it to the FIFO (the global character variable)
ready_to_write = 0; // no more writtings until a read is performed
ready_to_read = 1; // ready to read! wake up the reading process
wake_up_interruptible (&read_queue);
return 1; // 1 byte written
最后,在read
处理程序中:
If access mode = READ then // we only support reading if the access mode is read
return -EINVAL
Else
res = wait_event_interruptible (read_queue, ready_to_read);
if (res)
return res; // if process received a signal, exit write
Take character from global variable (our FIFO) and send it to userspace (copy_to_user() )
ready_to_read = 0; // no more reads until a write is performed
ready_to_write = 1; // ready to write! wake up the writting process
wake_up_interruptible (&write_queue);
return 1; // 1 byte read
您可以扩展此示例以允许FIFO或多个字符:您需要一个字符数组和两个索引:一个用于知道从哪里读取,另一个用于知道写入的位置。
要测试您的驱动程序,您可以打开两个xterms并执行
cat /dev/mydriver
中的一个,并且:
cat > /dev/mydriver
在其中一个。然后,您在第二个xterm中写入的每一行都将显示在第一个xterm中。
您甚至可以修改驱动程序,以便在写入过程关闭文件时,设置一个标志,以便下次读取进程等待读取内容时,它会检测到写入过程结束,然后返回0(向用户发出EOF信号,因此当您在第二个xterm中按Ctrl-D
结束输入时,第一个也自动结束。类似的东西:
(read
handler)
res = wait_event_interruptible (read_queue, ready_to_read || write_process_ended);
if (res)
return res; // -ERSTARTSYS if signal
if (write_process_ended)
{
ready_to_write = 1;
return 0; // if write process ended, send an EOF to the user
}
else
{
...
... get byte from FIFO, send to the user, etc.
...
return number_of_bytes_sent_to_user;
}