views:

389

answers:

3

Is it possible to expand the ioctl interface in Linux so that the user-space application can send a pointer to a function to the kernel space driver?

I'm in particular thinking of ways to handle the stream in user-controllable way but doing it in the kernel. Those operations could be attached to the kernel module but this would make development a lot easier as I wouldn't need to mess with the kernel during development.

More specifically, this would be the process:

  1. Data is read by the driver to a buffer.
  2. Data is handled by these user-defined functions in place.
  3. Some more handling is done, possibly with some HW blocks.
  4. Data is used by a user-space application.
+1  A: 

I think you can achieve what you want by having your driver provide one or more character devices (or block devices) that your user space applications opens.

Then you could use inotify (linux journal article) for kernel->user space event communication. Ioctl or writing to the device for user space->kernel event communication. Data exchange could also be achieved by reading/writing to one or more device files.

Alternatively you can provide /proc or /sys filesystem entries or use netlink.

You might also consider ksocket:

Ksocket is a linux 2.6 kernel module that provides bsd-style socket interfaces (namely socket, bind, listen, connect, accept, ...) for kernel developers to facilitate their network progaramming in linux kernel space. The interfaces ksocket presents are much the same as their equivalent in glibc, so even new developers for kernel space will have no barrier in developing kernel network-related programms.

hlovdal
Well, obviously I could send the data back, but if we talk about high-speed communication (like, audio data) that would facilitate a lot of data being copied all over the place...
Makis
+1  A: 

I think you're asking for a square circle: if the kernel were to just execute your "userland" function directly, it wouldn't be "userland" but rather a homebrew loadable module system. I assume that what you really want is a way to figure out what to do to make it all work without crashing your PC every time you make a mistake. Maybe you could abuse signal handlers as the means of "callback", but I'm too rusty to point out how you'd get back to the kernel as if by a function call return. The problem here is that in any userland->kernel context switch, the kernel starts with a fresh stack, so the return address is long gone. How about if you combine a signal handler with mmap'ing /dev/mem, and let your userland pseudodriver poke the kernel-mode driver's data structures directly? But then you're back to rebooting when you make a mistake, unless you figure out how to mmap only your driver's data structures? Other repurposeable mechanisms might be STREAMS and TTY line disciplines; I think these confer some sort of transmogrifying ability. Of course none of this is a good idea as a permanent solution!

Bernd Jendrissek
I can always run the development system in a virtual machine, so crashing isn't really the issue here.
Makis
+1  A: 

Your use case keeps mentioning data.

Maybe what you want to do is share memory between the kernel and a user process. You could put data and/or commands into the shared memory, and the process/kernel code on the other side could read it and do whatever. The get_user_pages_fast() call can make a process's memory accessible to the kernel, even when the process is not currently running.

Andy Grover