This may be regarded as a naive question.
I'm used to bare-metal programming where I changed register values manually in order to write in the GPIO. Conversely, I read those same registers when needing information.
I've recently moved to embedded linux. I've remarked that now dealing with the GPIO cannot be done from code running in the user space.** I can imagine there it might be some security/sanity reason for this but I cannot see it. Why can't code from user space read/write in the GPIO? An example on a problem that could be caused by that would be great.
** I am aware of libraries/APIs that enable you to deal with the GPIO from user-space, and I am learning to use them. My question is pure out of curiosity.
On some platforms it can be, but it's usually avoided.
Typically Linux runs on hardware with an MMU providing both page-level memory protection, and remapping of a virtual address space to physical addresses.
To access a memory-mapped GPIO from userpace, you'd need to configure the MMU to map the register hardware address into the desired process's virtual address space, and you'd need to enable read and/or write access to that page.
The problem though is that the granularity is typically poor - a memory page may be something like 4 kilobytes, while a GPIO pin's behavior is governed by a few distinct bits in several different registers. So it's not possible to expose an individual pin to a given process.
Additionally, doing this from userspace would require knowing the precise hardware details of how GPIO works on a given platform, and that's information which usually better belongs in a driver.
There are a few cases where using the sysfs interface is too slow, for example trying to bit-bang some slower interfaces. But typically in those cases rather than trying to handle the GPIO directly from userspace, a kernel module is written which does the bit-banging from kernel space, and then userspace uses a syscall to pass entire mid- to high- level operation requests to the kernel.