Here is an interesting question. Suppose you wrote the same program but one in user space and another in kernel space. And lets say all the program did was like a toggling of some gpios. Which version would achieve the higher toggle speed and why and what would be the limit?
Well it depends on how you do it.
There are a number of method of toggling gpios:
1 - In kernel space - you can directly manipulate the gpio registers
2 - In kernel space - you can use gpiolib
3 - In user space - you can directly manipulate the gpio registers (via mapped memory)
4 - In user space - you can use the sysfs interface
5 - In user space - you can use some other gpio driver (I wrote one before gpiolib had a sysfs interface: https://github.com/dhylands/projects/tree/master/linux/gpio)
1 & 3 are the fastest - and will most likely be limited by the hardware. kernel space can be faster because it can play games like disabling interrupts, so I could say toggle a gpio 20 times in kernel space with interrupts disabled and know that the 20 toggles took a very exact amount of time. In userspace, your best case might match the kernel space time, but the worst case will be worst. If you didn’t disable interrupts, then both should be similar.
4 & 5 will be slower than 2
I’m not sure whether 4 would be faster or slower than 5, I’ve never benchmarked them.
Directly accessing registers from userspace can be problematic if something else (like another kernel driver) is trying to access the same registers at the same time, and personally, I don’t recommend it. You can get away with it in certain very specialized circumstances.
Part of the problem is that certain operations need mulual exclusion or need to be performed atomically, and you can’t do some of that stuff from userspace. The classic example with gpios, is that gpios are often arranged so that there are 32 of them in a register. If you’re interested in gpio 27 and some other driver is interested in gpio 3, you can wind up colliding since both gpios are in the same register. Some hardware is more forgiving (i.e. HW that has separate set and clear registers for a gpio), but there are other registers (like the configuration registers) that need to be set with mutual exclusion.
In general, if you want to be manipulating registers you should be doing it from kernel space.
If you’re trying to do high-performance stuff that involves hardware, you probably need to be in kernel space.