How? I don't think the kernel cares what the directory looks like - userspace will break in funny ways, but you can boot without procfs even mounted (well, I say boot, but more like "you can start a shell and some things will still work")
When your application calls open() or read() or stat() or whatever, it passes through libc and then makes a syscall to ask the kernel "hey, give me a file handle for /proc/foo", "hey, give me the first 500 bytes from this file handle", etc. Then in the kernel, that syscall triggers a function that figures out what filesystem you're talking to and passes the request to that filesystem driver. AFAIK, the procfs driver just reads (and writes) a bunch of data structures in kernel memory and passes the result through as a filesystem. So the actual underlying data structure does always exist and is a hard requirement for the system to work, but procfs is just a userspace view into that underlying data in the kernel. Incidentally sysfs would be the same - the stuff you see in /sys exists in the kernel regardless, but the kernel doesn't really care whether those data structures are exposed to userspace as a virtual filesystem.
Thanks for this extra context! I wonder now how much latency the system experiences with the procfs driver loaded. I'm guessing virtually none, but still, for a driver that is essentially just decoration for userspace to look at, it seems like there would be some noticeable overhead in having the procfs driver loaded
I wouldn't think so, no. If userspace isn't using it, then there's no latency overhead; the kernel access its own internal data structures the same regardless. If userspace is using it, the kernel still uses its own data structures just the same, but now there's a way for programs to read those data structures. Using the procfs driver doesn't change anything inside the kernel (well, anything important; obviously it exercises the procfs driver code (which also will have its own variables) and there's some data structures that describe mounted filesystems), it just provides an interface to what's already there.