stdlib: document the libc/kernel layering rationale in Net.Sockets
Explain why the unit binds libc (the kernel boundary, the syscall doorway), the common three-layer pattern shared with Indy/Synapse/the JDK, how Java is itself not libc-free, and what a pure-Pascal syscall-stub version would and would not buy.
This commit is contained in:
parent
3c6fbc3184
commit
dd635d5140
|
|
@ -21,7 +21,41 @@
|
||||||
MakeNonBlocking, and IgnoreSigPipe.
|
MakeNonBlocking, and IgnoreSigPipe.
|
||||||
|
|
||||||
IPv4 only, no TLS — suitable for a localhost service or a plain TCP server.
|
IPv4 only, no TLS — suitable for a localhost service or a plain TCP server.
|
||||||
Strings are treated as raw bytes for I/O. }
|
Strings are treated as raw bytes for I/O.
|
||||||
|
|
||||||
|
--- Why this binds libc (and why that is the normal choice) ---
|
||||||
|
|
||||||
|
Opening a socket is not a computation; it is a request to the OS kernel. A
|
||||||
|
userspace process cannot touch the network card, allocate a port, or run TCP
|
||||||
|
state itself — only the kernel can. The single doorway from a process into
|
||||||
|
the kernel is the CPU's `syscall` instruction, and libc (glibc on Linux) is
|
||||||
|
the canonical wrapper around those syscalls: it knows the syscall numbers and
|
||||||
|
the register ABI per architecture, handles errno and EINTR restarts, and
|
||||||
|
gives each call a stable C name (socket/bind/recv/...). `external name
|
||||||
|
'socket'` simply links to that libc symbol. This is why nearly everything on
|
||||||
|
Linux — the FPC RTL, Python, Node, even the JVM — goes through libc.
|
||||||
|
|
||||||
|
Every networking stack is the same three layers; only the middle "shim"
|
||||||
|
differs by who wrote it:
|
||||||
|
|
||||||
|
protocol logic (HTTP/WS/crypto) - pure Pascal here, pure Java in the JDK,
|
||||||
|
pure Pascal in Indy/Synapse
|
||||||
|
socket abstraction - this unit; Indy's TIdStack; the JDK's
|
||||||
|
sun.nio.ch native methods
|
||||||
|
OS doorway - libc bindings (us, Indy, FPC, Synapse)
|
||||||
|
OR hand-written C in a VM (Java JNI ->
|
||||||
|
still libc/Winsock underneath)
|
||||||
|
kernel - syscalls (fixed; nobody reimplements it)
|
||||||
|
|
||||||
|
Java is NOT libc-free: java.net.Socket calls `native` methods implemented in
|
||||||
|
C inside the JVM, which call socket()/bind()/recv() in libc exactly as we do.
|
||||||
|
Its portability comes from writing that C glue once per OS, not from avoiding
|
||||||
|
libc. A truly "pure Pascal" version would replace libc's job with our own
|
||||||
|
per-arch `syscall` assembly stubs (the route Go takes) — that removes the
|
||||||
|
libc dependency but not the kernel boundary, and trades a stable cross-OS C
|
||||||
|
ABI for per-arch/per-OS assembly we would then maintain. For a single Linux
|
||||||
|
target it is a day or two of work; as a portability strategy it is MORE work
|
||||||
|
than the per-platform binding layer noted at the PORTING BOUNDARY below. }
|
||||||
|
|
||||||
unit Net.Sockets;
|
unit Net.Sockets;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue