Hi- I'm trying to write a linux kernel (network) device driver, and user space library to go with it.
The kernel driver and user space library communicate via the ioctl() mechanism; the library has to poll the driver (using ioctl()) for driver-initiated (ie. asynchronous from the library's point of view) events*. Most events have fixed size data associated with them, for which the sequence is: (1) driver: event occurs, added to queue : (2) library polls driver: calls ioctl() with a pointer to a user event data area (3) driver ioctl handler: gets event off queue and calls copy_to_user() to copy event data from kernel memory into user memory (4) library: ioctl() call returns with event data in user event data area. But some events have variable sized data, and the structures associated with them contain pointers. So for these the sequence I want is: (1) driver: event occurs, kernel memory allocated, added to queue : (2) library polls driver: calls ioctl() (3) driver ioctl handler: gets event off queue, allocates user memory and sets pointer in ioctl() data pointing to it, copies event data from kernel into user memory, frees kernel memory (4) library: ioctl() call returns with pointers to driver-allocated user memory containing event data. Is this possible? That is, I don't know how to (or whether I can) manage user memory in the kernel. I know there is a GFP_USER kmalloc() flag, but does that return a pointer that can be used as the destination of a copy_to_user()? (Did a Google but didn't find appropriate info, apologies if I missed it.) It would be possible to use fixed size structures between library and driver, but this would mean changing a published interface and hence I'm trying to avoid it. Cheers John [*] I know polling isn't ideal, but haven't come up with anything better. I tried using 2 sockets, one for library to driver traffic and the other for driver to library events. For the latter, the library called ioctl() as for polling, but in the device's ioctl handler, it blocked waiting for an event to be added to the event queue. This blocking worked, but unfortunately it also blocked the library to driver traffic on the other socket. I'm not a linux expert, and would be interested to hear a better way...
