Live data from Hacker News

I summarized my understanding of Linux systems

github.com

11–20 of 88 posts

Re: I summarized my understanding of Linux systems

#11
post #7
post #6

Earlier quoted context omitted.

> The everything is a file philosophy becomes much more clear then. To be honest, everything is a file is kind of a lie in unix. /proc and /sys are pretty much plan9 inspiration.

Also, a lot of devices require very specific ioctl() commands to work with and don't provide everything as a file. For example, you can't set the baudrate of a serial port by writing it to some /proc node.

nit: The ioctl syscall targets files just the same as the write syscall.

Everything being a file, and everything being read/write calls are different things. There's pros and cons.

Re: I summarized my understanding of Linux systems

#12
post #9
post #6

Earlier quoted context omitted.

> The everything is a file philosophy becomes much more clear then. To be honest, everything is a file is kind of a lie in unix. /proc and /sys are pretty much plan9 inspiration.

A more accurate term is that everything is a file descriptor . The main difference is that plan9 uses read and write for everything, whereas Linux and BSD uses ioctls on file descriptors for everything.

Everything is a descriptor. When I'm opening a TCP connection, there's no file, so calling it a file descriptor feels wrong.

And at that point, the whole "everything is" turns into nonsense, because yes, everything is a pointer to something, so what.

Re: I summarized my understanding of Linux systems

#13
post #8

My mental model of Linux does not have the CPU/Memory in user space. What am I missing?

Userspace program directly uses CPU and memory (unless you're using VM). In contrast to that, your userspace program does not directly access your network device or SSD, but uses kernel routines to access those indirectly.

If you're using a hypervisor, then the userspace program inside the VM is also using the CPU and memory directly. You'd have to do full emulation to avoid that.

Even with full emulation, I'd say memory is being accessed directly, unless you really go out of your way to make it weird.

Re: I summarized my understanding of Linux systems

#14
post #8

My mental model of Linux does not have the CPU/Memory in user space. What am I missing?

Nor does mine.

Userspace assembly runs directly on the CPU* executing in the unprivileged ring. When the userspace program makes a system call by calling a kernel entry function which is mapped into the process's address space by the dynamic loader, then part of that entry into kernelspace is to put the CPU into the privileged ring and kernel assembly then runs on the CPU.

The process scheduler can stop execution to kick a task off the CPU and switch to another one, depending on OS and kernel some things can be kicked off the CPU and some cannot.

Userspace memory allocations are serviced by virtual memory where the page tables track the translation of virtual memory pages into physical memory pages using the MMU.

The kernel is involved during allocation and page fault, but iiuc a regular successful virtual memory access is a hardware operation only.

I don't have a diagram of how this works. Neither processes nor memory are my usual area of kernel.

You'd be better to read the x86 version of the XV6 book to learn how this stuff really works. It's really well written and implements enough to be tangibly useful. Reading the code is optional when just learning concepts. Reading the XV6 code will hopefully help you understand the O'Reilly Linux books better, which will hopefully help you understand the actual Linux kernel better.

(*yes I'm aware CPUs don't directly execute assembly anymore, but the microcode guarantees the observable CPU state at any Instruction Pointer matches the expectation as if you were running assembly on a PDP or C64, or close enough for 99.999% purposes and definitely enough for debugging your program in gdb)

Re: I summarized my understanding of Linux systems

#15
post #9

Earlier quoted context omitted.

A more accurate term is that everything is a file descriptor . The main difference is that plan9 uses read and write for everything, whereas Linux and BSD uses ioctls on file descriptors for everything.

Everything is a descriptor. When I'm opening a TCP connection, there's no file, so calling it a file descriptor feels wrong. And at that point, the whole "everything is" turns into nonsense, because yes, everything is a pointer to something, so what.

There are named files (which have a file path) and anonymous files (which do not). You can see these in /proc/$PID/fd/$FD if you're curious - when the link doesn't start with '/', it's anonymous. Even process memory is just an anonymous file on Linux, and arguably a cleaner one as it operates on proper fds, instead of plan9 where a string "class name" (not a path) is used to access the magical '#g' filesystem.

The difference to plan9 is not the files, but the way plan9 uses text protocols with read/write to ctl files. To open a TCP connection - if memory serves me right - you first have to write to a ctl file, which creates a new file for the connection. Then, you write the dial command to the ctl file of that connection, and after which you can open the connection file. On Linux, a syscall creates an anonymous file, and then everything after is operations on this anonymous file.

There's some ideological benefits, but plan9 creates a mess of implicit text protocols, ugly string handling, syscall storms and memory inefficiencies. Their design is pretty much solely a limitation caused by the idea that all filesystems should exist through the 9p protocol, which as a networked protocol cannot share data (fds, structs), only copy (payloads to/from read, write). With the idea that all functionality had to be replaceable and mountable from remote machines, the only possible API became read/write for everything.

I'd argue that fd-using syscalls and ioctls - basically per-file syscalls - is a superior approach to implement everything-as-a-file.

Re: I summarized my understanding of Linux systems

#16

Earlier quoted context omitted.

Everything is a descriptor. When I'm opening a TCP connection, there's no file, so calling it a file descriptor feels wrong. And at that point, the whole "everything is" turns into nonsense, because yes, everything is a pointer to something, so what.

There are named files (which have a file path) and anonymous files (which do not). You can see these in /proc/$PID/fd/$FD if you're curious - when the link doesn't start with '/', it's anonymous. Even process memory is just an anonymous file on Linux, and arguably a cleaner one as it operates on proper fds, instead of plan9 where a string "class name" (not a path) is used to access the magical '#g' filesystem. The di…

Whichever superior depends on your use case and needs. Plan9's approach is very powerful whenever you need anything distributed, and makes lots of boilerplate to achieve that basically unnecessary. Linux nowadays is flexible for both approaches (in theory, the ecosystem might not be there), and I'm glad user namespaces are a thing.

Re: I summarized my understanding of Linux systems

#17
post #16

Earlier quoted context omitted.

There are named files (which have a file path) and anonymous files (which do not). You can see these in /proc/$PID/fd/$FD if you're curious - when the link doesn't start with '/', it's anonymous. Even process memory is just an anonymous file on Linux, and arguably a cleaner one as it operates on proper fds, instead of plan9 where a string "class name" (not a path) is used to access the magical '#g' filesystem. The di…

Whichever superior depends on your use case and needs. Plan9's approach is very powerful whenever you need anything distributed, and makes lots of boilerplate to achieve that basically unnecessary. Linux nowadays is flexible for both approaches (in theory, the ecosystem might not be there), and I'm glad user namespaces are a thing.

Now, proper plan9-style namespaces, that I miss. :)

User namespaces are still a hell of a lot clunkier than "each process inherits its parents' namespace".

Re: I summarized my understanding of Linux systems

#18
post #16

Earlier quoted context omitted.

Whichever superior depends on your use case and needs. Plan9's approach is very powerful whenever you need anything distributed, and makes lots of boilerplate to achieve that basically unnecessary. Linux nowadays is flexible for both approaches (in theory, the ecosystem might not be there), and I'm glad user namespaces are a thing.

Now, proper plan9-style namespaces, that I miss. :) User namespaces are still a hell of a lot clunkier than "each process inherits its parents' namespace".

If you setup user namespace, the child processes will inherit that namespace. The difference is that plan9 is fully built on this idea and isn't multi-user, on linux you have to opt-in to this. It's very useful and underused (mostly used by containers). I wanted to ship my AWS lambdas this way, but sadly AWS lambdas don't allow user namespaces.

https://github.com/aws/aws-lambda-base-images/issues/143

Re: I summarized my understanding of Linux systems

#19
post #16

Earlier quoted context omitted.

There are named files (which have a file path) and anonymous files (which do not). You can see these in /proc/$PID/fd/$FD if you're curious - when the link doesn't start with '/', it's anonymous. Even process memory is just an anonymous file on Linux, and arguably a cleaner one as it operates on proper fds, instead of plan9 where a string "class name" (not a path) is used to access the magical '#g' filesystem. The di…

Whichever superior depends on your use case and needs. Plan9's approach is very powerful whenever you need anything distributed, and makes lots of boilerplate to achieve that basically unnecessary. Linux nowadays is flexible for both approaches (in theory, the ecosystem might not be there), and I'm glad user namespaces are a thing.

> There's some ideological benefits, but plan9 creates a mess of implicit text protocols, ugly string handling, syscall storms and memory inefficiencies.

On the other hand, linux ioctl and syscalls have infinite binary structs you need to know (and cannot let the compiler reorder fields in), which then doesn't make cross-platform development any easier.

Re: I summarized my understanding of Linux systems

#20
post #16

Earlier quoted context omitted.

Whichever superior depends on your use case and needs. Plan9's approach is very powerful whenever you need anything distributed, and makes lots of boilerplate to achieve that basically unnecessary. Linux nowadays is flexible for both approaches (in theory, the ecosystem might not be there), and I'm glad user namespaces are a thing.

> There's some ideological benefits, but plan9 creates a mess of implicit text protocols, ugly string handling, syscall storms and memory inefficiencies. On the other hand, linux ioctl and syscalls have infinite binary structs you need to know (and cannot let the compiler reorder fields in), which then doesn't make cross-platform development any easier.

I was quite disappointed by the ABI differences between different architectures when I was doing network transparent uinput.

https://git.cloudef.pw/uinputd.git/tree/common/packet.h#n34 https://git.cloudef.pw/uinputd.git/tree/server/uinputd.c#n16

(Excuse to write code to use my PS Vita as gamepad :D)

Post reply on HN