Next: The write callback
Up: Basic Device Creation
Previous: The open and close
The read callback
Returning to our cat /dev/hello-world example, what happens
after the open is successful? Next, cat will try to use
read(2), which will get proxied by FUSD to the function do_read on line 13. This function takes some additional arguments
that we didn't see in the open and close callbacks:
- struct fusd_file_info *file--The first argument to all
callbacks, containing information which describes the file; see
Section 5.
- char *user_buffer--The buffer that the callback should use to
write data that it is returning to the user.
- size_t user_length--The maximum number of bytes
requested by the user. The driver is allowed to return fewer bytes,
but should never write more then user_length bytes into user_buffer.
- loff_t *offset--A pointer to an integer which represents
the caller's offset into the file (i.e., the user's file pointer).
This value can be modified by the callback; any change will be
propagated back to the user's file pointer inside the kernel.
The semantics of the return value are the same as if the
callback were being written inside the kernel itself:
- Positive return values indicate success. If the call is
successful, and the driver has copied data into buffer, the
return value indicates how many bytes were copied. This number should
never be greater than the user_length argument.
- A 0 return value indicates EOF has been reached on the file.
- As in the open and close callbacks, negative values
(such as -EPERM, -EPIPE, or -ENOMEM) indicate errors. Such values will
cause the user's read() to return -1 with errno set
appropriately.
The first time a read is done on a device file, the user's file
pointer (*offset) is 0. In the case of this first read, a
greeting message of Hello, world! is copied back to the user, as
seen on line 24. The user's file pointer is then advanced. The next
read therefore fails the comparison at line 20, falling straight
through to return 0, or EOF.
In this simple program, we also see an example of an error return on
line 22: if the user tries to do a read smaller than the length of the
greeting message, the read will fail with -EINVAL. (In an actual
driver, it would normally not be an error for a user to provide a
smaller read buffer than the size of the available data. The right
way for drivers to handle this situation is to return partial data,
then move *offset forward so that the remainder is returned on
the next read(). We see an example of this in
Program 2.)
Next: The write callback
Up: Basic Device Creation
Previous: The open and close
Jeremy Elson
2003-08-20