Reputation: 43456
I'm interested in implementing a userspace char device in Linux using CUSE.
In a Linux kernel driver for char devices, the kernel driver .read
function is supposed to implement either blocking or non-blocking operation depending on the file descriptor's O_NONBLOCK
flag state.
But what about a CUSE driver .read
function, if there is no data to read "yet"?
.read
function responsible for implementing both the blocking and non-blocking behaviours, depending on the file descriptor's O_NONBLOCK
flag state?.read
function implement a blocking read?I tried implementing a .read
function with a sleep(1)
in it. I found that it kind of worked, but my CUSE driver became slow to respond to .write
. So I suppose a CUSE .read
function should not simply block for a long time. But I haven't found out how to do properly block so far, in either CUSE docs or CUSE example code or other projects that use CUSE.
Upvotes: 0
Views: 45
Reputation: 43456
- Is the CUSE driver .read function responsible for implementing both the blocking and non-blocking behaviours, depending on the file descriptor's
O_NONBLOCK
flag state?
I've examined the source code for the Linux kernel CUSE driver, and the userspace libfuse
library. I don't see any code to automatically handle blocking/non-blocking behaviour according to the file descriptor's O_NONBLOCK
flag state. So it looks as though it's the responsibility of the userspace driver implementation to check the O_NONBLOCK
flag and explicitly implement the blocking and non-blocking behaviour.
The libfuse
comment in fuse_common.h
for struct fuse_file_info
field flags
says
Open flags. Available in open() and release()
But, the libfuse do_read()
implementation makes the open flags also available in fi->flags
in the .read()
function. Similarly for the .write()
function call. But not .ioctl()
— I guess IOCTL calls are normally expected not to block — except for functions where that is the explicit purpose, such as TIOCMIWAIT
.
- How can the CUSE driver .read function implement a blocking read?
I tried implementing a .read function with a sleep(1) in it. I found that it kind of worked, but my CUSE driver became slow to respond to .write.
I was testing my prototype code using picocom
. It sets O_NONBLOCK
, so it expects .read()
and .write()
not to block. It superficially appeared to work with my blocking .read()
, but didn't really work well, which explains my observation that data was delayed through the .write()
function.
So I reworked my .read()
function to check that flag.
if (fi->flags & O_NONBLOCK) {
fuse_reply_err(req, EAGAIN);
return;
}
I removed the sleep(1)
from my function and implemented data pacing using clock_gettime(CLOCK_MONOTONIC, &ts)
instead.
Upvotes: 0