Hacker News new | ask | show | jobs
by SixSigma 4130 days ago
It is interesting that the OP things that static binaries is related to being born in Google. The thing is that Plan9 doesn't have shared libraries, all binaries are statically linked. And the reason for this is that plan9 is a networked operating system, needing to load multiple files at runtime would severely harm startup time for a binary.

Run trace on a Linux binary and see the slew of "file not found" errors from syscalls looking for shared libs at startup and then imagine each one of these is taking place over a 9600 baud connection.

Good design realises benefits that authors never needed to consider.

3 comments

Static binaries used to be common, the normal way of doing stuff. People tend to think that package management killed them, but it was actually glibc which cannot make proper static binaries as it insists on dynamic functionality for some functions, such as name resolution. Now we have Musl libc there may well be a revival in static binaries from C applications, and the C-derived ecosystem.
As a demonstration I traced date(1) on CentOS. Here are the file accesses, if you are running diskless, each of these needs a round trip to the file server. (except the final 3, of course)

access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)

open("/etc/ld.so.cache", O_RDONLY) = 3

fstat(3, {st_mode=S_IFREG|0644, st_size=54185, ...}) = 0

close(3) = 0

open("/lib64/librt.so.1", O_RDONLY) = 3

read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0@!\0\0\0\0\0\0"..., 832) = 832

fstat(3, {st_mode=S_IFREG|0755, st_size=43880, ...}) = 0

close(3) = 0

open("/lib64/libc.so.6", O_RDONLY) = 3

read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0p\356\1\0\0\0\0\0"..., 832) = 832

fstat(3, {st_mode=S_IFREG|0755, st_size=1921176, ...}) = 0

close(3) = 0

open("/lib64/libpthread.so.0", O_RDONLY) = 3

read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\340]\0\0\0\0\0\0"..., 832) = 832

fstat(3, {st_mode=S_IFREG|0755, st_size=142640, ...}) = 0

close(3) = 0

open("/usr/lib/locale/locale-archive", O_RDONLY) = 3

fstat(3, {st_mode=S_IFREG|0644, st_size=99158576, ...}) = 0

close(3) = 0

open("/etc/localtime", O_RDONLY) = 3

fstat(3, {st_mode=S_IFREG|0644, st_size=3661, ...}) = 0

fstat(3, {st_mode=S_IFREG|0644, st_size=3661, ...}) = 0

read(3, "TZif2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\7\0\0\0\7\0\0\0\0"..., 4096) = 3661

lseek(3, -2338, SEEK_CUR) = 1323

read(3, "TZif2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\10\0\0\0\10\0\0\0\0"..., 4096) = 2338

close(3) = 0

fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0

write(1, "Tue Feb 24 08:57:58 GMT 2015\n", 29) = 29

close(1) = 0

Ok, here is strace of date(1), which is dynamically linked, on Alpine Linux which uses Musl libc not glibc.

execve("/bin/date", ["date"], [/* 16 vars */]) = 0

mprotect(0x7777dcd5a000, 4096, PROT_READ) = 0

mprotect(0xdc2d89a3000, 4096, PROT_READ) = 0

arch_prctl(ARCH_SET_FS, 0xdc2d89a4268) = 0

set_tid_address(0xdc2d89a4298) = 2439

clock_gettime(CLOCK_REALTIME, {1424769563, 611556639}) = 0

open("/etc/localtime", O_RDONLY|O_NONBLOCK|O_CLOEXEC) = 3

fstat(3, {st_mode=S_IFREG|0644, st_size=118, ...}) = 0

mmap(NULL, 118, PROT_READ, MAP_SHARED, 3, 0) = 0x7777dcd57000

close(3) = 0

ioctl(1, SNDCTL_TMR_TIMEBASE or SNDRV_TIMER_IOCTL_NEXT_DEVICE or TCGETS, {B38400 opost isig icanon echo ...}) = 0

writev(1, [{"Tue Feb 24 09:19:23 UTC 2015", 28}, {"\n", 1}], 2Tue Feb 24 09:19:23 UTC 2015 ) = 29

close(1) = 0

close(2) = 0

exit_group(0) = ?

+++ exited with 0 +++

That is worlds apart.
OpenBSD's ktrace is similar

31144 date CALL readlink(0x3c001c16,0xcfbe7048,0x3f)

31144 date NAMI "/etc/malloc.conf"

31144 date RET readlink -1 errno 2 No such file or directory

31144 date CALL open(0x3c001967,0<O_RDONLY>)

31144 date NAMI "/etc/localtime"

31144 date RET open 3

31144 date CALL open(0xcfbde9d4,0<O_RDONLY>)

31144 date NAMI "/usr/share/zoneinfo/posixrules

31144 date RET open 3

Yes, in many ways Musl is a BSD style libc for Linux (even down to the license). Add pkgsrc and it is pretty BSD-like.
Static binaries are bad design as soon as a library has a security flaw. Remember when there was a double free in zlib and Apple had to release a 1.3GB patch to update everything that linked it in statically - and even that only fixed the problem for Apple-official programs, not for anything the user had installed?
recompiling all of plan9 takes about 15 minutes
Well yeah, but plan9 has so little code because it doesn't really do anything. Recompiling any consumer-grade system takes much longer.
Actually recompiling Plan 9 takes about 60 seconds on my current Thinkpad.
A 15x speed up in a few short years, how delightful.
So how would one implement Erlang-like functionality in Plan9, where the code of a server can be hotswapped while still keeping all existing sockets to the clients open?
fork, I guess. Plan9 uses files so there is nothing special about sockets.