one thing that i really dislike about Unix is the zealous adherence to semi-accidental design elements that ends up interfering with the utility of the underlying useful principle

for example:

  • early Unix could not run too complex a program due to hardware restrictions, so programs were composed using text streams
  • useful underlying principle: designing your applications for composition
  • zealous interpretation: your OS should have a toolkit of single-purpose programs communicating over text streams
  • design we could have had, but never will: applications that communicate using structured data, simplifying life for both programmers and end users

there is also much to be said about splitting your application into many different pieces, but keeping a unified approach to application design so that the pieces may be understood via a unified mental model

i think some Unices (that i haven't really used enough to comment) do approach userspace design like this, but the GNU-plus-random-tools userspace you're much more likely to encounter definitely doesn't

why the actual fuck does Linux not have a syscall for /proc/self/maps

it is beyond ridiculous that the 2026 solution to "find out what my memory mappings are" is fucking fscanf

@whitequark "well first you're gonna need to allocate a bunch of strings...." might as well be the intro to half of Linux systems programming
@whitequark I wonder what is the use case?
I can imagine only security-related stuff like anti-cheats.
@iurii debuggers, JITs, crash reporters, allocators, and similar low-level users could all benefit from VirtualQuery-like API

@whitequark Interesting. While working with JITs and allocators, I never looked beyond virtual memory, hence the question.

I'm not saying have the mapping is not useful, just pointing out that mileage may vary, so that may be the reason nobody has done it.

@iurii what do you mean "beyond virtual memory"?
@iurii in any case, I've encountered the "parse /proc/$PID/maps" code too many times in the wild to count. there is clearly a very significant need to do the operation. just that Linux doesn't care to give it to you
@whitequark @iurii

dont get me started on the different decisions, by those codebases, on what the actual file path of the mapped objfile should be

is it resolved? symlink only or also hardlink? is it relative? a special prefix to annotate remote targets? your guess is as good as mine!
@whitequark I never cared about virtual vs physical memory relation.
Basically my process' address space is what it is.
@iurii that is not what /proc/self/maps gives you

@whitequark I see now. But again, never had to encounter those.

It’s fascinating to watch Linux evolve.

On one hand, one may expect /proc/self just for coherency. On the other, in corporate development, I’m a proponent of not writing code until it’s actually required. If someone implements a linked list with `insert_before`, I’ll ask them to delete `insert_after` if it’s unused.

Linux seems to handle this naturally, by the absence of certain patches.

@iurii you still fail to understand the core of my complaint. it is not about the specifics of /proc/self/maps. it is rather about how little care and thought was put into the design of the system as a whole.

moreover, the Linux development process actively filters out people with better taste who could improve the design, both by exhaustion of having to deal with assholes (gregkh isn't much better than linus) and by virtue of "if everything around you is a pile of crap, there is little point in building something great"

@whitequark @iurii See also the ` (deleted)` suffix in iirc maps and in symlink targets in /proc/PID/fd/ (what if I actually have a file that a name that ends like that?)
@robryk @iurii you can also put a newline into it to completely fake entries! (they might have fixed that specific one, but it is absurd that it is a problem in first place)
@whitequark @iurii Relatedly, a thing that surprised me a lot once is that symlinks in /proc are fake: if you open through them you can get totally different things than if you resolve the path they expand to (e.g. `root` or `exe` if that process is in a different mount namespace might be accessible, but its target path might be nonsensical).
@robryk @iurii @whitequark for Plan 9, which Linux took procfs from, it was sensible and probably even worked.

@whitequark I understand the complaint, I was just cautious to frame it that way.

if you view Linux not as a coherent system but as a set of related patches, it makes more sense, but yeah... When I was trying to understand how TCP/IP stack is implemented in Linux, I was reading BSD code, because "look we apply this flag just to make socket handler look like a file's one because unrelated code crashes"

I'm still fascinated by the lengths that Linux has made always being like this.

@whitequark to me, it is a mystery why BSD is decaying, and Linux is thriving.

Judging by the readability of code only, it should be vise versa. Knowing a bit about maintaining OSS project makes me think sometimes that being an asshole is a hard requirement, I don't know.

@whitequark

This one of the things that keeps me on FreeBSD. Linux decided to put most of the things that the BSDs put in sysctls in filesystems and make them human readable. The equivalents on the BSDs are usually structured data from a sysctl.

About 20 years ago, I wrote some code for showing machine info in a desktop environment’s about box. On FreeBSD, NetBSD, OpenBSD, and Solaris, the information was exposed as sysctls. They had different names, but it was trivial to write a little wrapper where each platform told you the sysctls to use.

On Linux, the info was in /proc/cpuinfo. The structure of this changed between releases and also between architectures on the same kernel version. The code for Linux was more than all of the other three platforms, combined, and that code was just to interface with a 300 KiB library that included a parser that worked on all of the different versions.

It makes me sad that so many people’s first experience with a F/OSS kernel is with a design that bad.

@david_chisnall am I remembering this correctly please? As far as I remember one of the other nice things about bsd sysctls is that you can use a lot of them from shell scripts and a sh prompt too because the sysctl userland program can convert them all to and from text too?

@0x2ba22e11

Yes, they advertise the type, so the sysctl program can provide the value, the type, and a human-readable description. Some of the structured ones can”t (yet) be exposed nicely as structures (it would be nice if the sysctl tool could emit them as JSON or something).

@david_chisnall @whitequark Linux really should've just made them sysctls and then added a virtual filesystem interface to do the Plan9 thing (for those who care to have it).

@david_chisnall @whitequark right, but it should all be behind a library at this point so i don't have to care about the sysctl details.

also, just as a side note - parsing /proc/cpuinfo vs sysctl dev.cpu is an interesting example of "which scales poorly with increasing number of CPUs", and it . turns out /proc/cpuinfo ends up being pretty good in that respect :(

So, I do prefer the structured data way, but honest to god i wish we had libraries for this stuff and people didn't hand roll it all

@erikarn @whitequark

At least for my use case, the code required to call the library was more than the code required to read the sysctls directly. And the sysctl code was shared across four platforms (only the names of the sysctls differed). I don’t see a value in an abstraction layer if the abstraction layer is more complex than the thing it abstracts over needs to be.

@david_chisnall @whitequark because then the sysctl interface across four operating systems - that isn't defined in any standard - is the thing that you're hoping doesn't change.

in your case, for a simple tool, yeah. I'm porting another tool that implements /proc/cpuinfo parsing and i really wish we just had a library that abstracted this stuff out for all OSes and actually /that/ was standardised.

Note - one of my systems has 160 CPUs. sysctl iteration takes TIME there.

@whitequark I guess the modern solution is using ebpf+io_uring if you actually want to skip the string creation and parsing.
But yes, the whole fact that there is no generic interface to proc that avoids parsing strings is pretty embarrassing.
@whitequark don't say it too loud or we'll get yet-another ioctl! Lol.
@whitequark It does now: https://docs.kernel.org/filesystems/proc.html
"Starting with 6.11 kernel, /proc/PID/maps provides an alternative ioctl()-based API that gives ability to flexibly and efficiently query and filter individual VMAs. This interface is binary and is meant for more efficient and easy programmatic use. struct procmap_query, defined in linux/fs.h UAPI header, serves as an input/output argument to the PROCMAP_QUERY ioctl() command."
The /proc Filesystem — The Linux Kernel documentation

@myrrhperiwinkle @whitequark you still need to actually have a /proc fs mounted for this unfortunately
@uis @myrrhperiwinkle @whitequark That's obviously still a very silly requirement for an API. You need to rely on something other than the kernel for this basic property of your process. Unless you make your own mount, which I'm not sure whether you can in some way without effective root. Even if you make your own mount, it's a hideously complicated sequence compared to just having a syscall for this, especially if you rigorously use O_PATH etc. to avoid TOCTOU. The path is effectively a magic number (a magic string) which is just inelegant.
@anselmschueler @myrrhperiwinkle @whitequark > You need to rely on something other than the kernel for this basic property of your process.
Then I have good news for you: procfs is a pseudo-filesystem implemented in your kernel.
> Unless you make your own mount, which I'm not sure whether you can in some way without effective root.
Namespaces, but in case of procfs requiring root is a good idea(see mount options, that give more isolation).
> Even if you make your own mount, it's a hideously complicated sequence compared to just having a syscall for this, especially if you rigorously use O_PATH etc. to avoid TOCTOU. The path is effectively a magic number (a magic string) which is just inelegant.
System call numbers are also magic numbers in that sense. If syscall numbers could be rebound, we would be in exactly same situation regardless of mapping in VFS.
@whitequark at least you won't get some unexpected ioctl when implementing procfs implementation with fuse.
Also, Linux procfs is not one from Unix, it's one from Plan 9.
@uis go away
@whitequark I will leave, but leave you with thoughts of procfs in userspace. And maybe some sandboxing.