Call a userspace function from within a Linux kernel module
I think the simplest solution would be to create a character device in your kernel driver, with your own file operations for a virtual file. Then userspace can open this device O_RDWR
. You have to implement two main file operations:
read
-- this is how the kernel passes data back up to userspace. This function is run in the context of the userspace thread calling theread()
system call, and in your case it should block until the kernel has another seed value that it needs to know the output for.write
-- this is how userspace passes data into the kernel. In your case, the kernel would just take the response to the previous read and pass it onto the hardware.
Then you end up with a simple loop in userspace:
while (1) {
read(fd, buf, sizeof buf);
calculate_output(buf, output);
write(fd, output, sizeof output);
}
and no loop at all in the kernel -- everything runs in the context of the userspace process that is driving things, and the kernel driver is just responsible for moving the data to/from the hardware.
Depending on what your "do some random stuff here" on the kernel side is, it might not be possible to do it quite so simply. If you really need the kernel loop, then you need to create a kernel thread to run that loop, and then have some variables along the lines of input_data
, input_ready
, output_data
and output_ready
, along with a couple of waitqueues and whatever locking you need.
When the kernel thread reads data, you put the data in input_ready
and set the input_ready
flag and signal the input waitqueue, and then do wait_event(<output_ready is set>)
. The read
file operation would do a wait_event(<input_ready is set>)
and return the data to userspace when it becomes ready. Similarly the write
file operation would put the data it gets from userspace into output_data
and set output_ready
and signal the output waitqueue.
Another (uglier, less portable) way is to use something like ioperm
, iopl
or /dev/port
to do everything completely in userspace, including the low-level hardware access.