Lot of fun reading that, I looked around briefly but couldn't find my email archive from Sun, but I was in the kernel group when folks got the idea that "Gee if you shared the text segment of libraries, that would give you more memory for your buffer cache or user pages!" One of the guys in my group re-wrote the linker to scan through and realign text segments so that the maximum number of read-only pages (and thus shareable) could be allocated. And of course code that had static buffers and what not (go look at the 4.1BSD code, they were everywhere). It made my Sun 3/75 which had, wait for it 32 Megabytes of RAM (yes, less than the L2 cache in some machines these days) run quite a bit faster. Took a long time to get right too.
Shared libraries gave you three distinct advantages, one you cut down on the working set size, two you cut down on file load time, and three it became possible to "interpose" on the library and run two versions of the library at the same time for backwards compatibility.
Building a static system might be fun but for a 64 bit system, building one where libraries were fixed in the address space in flash or something might actually be even better.
An issue both back then and today is potentially that dynamic linkage often ends up using an indirection table, unlike static linkage with simple fixups, which then adds at least the cost of an indirection to each function call.
Sometimes that overhead is swamped by other factors, sometimes it's not, but that would be one reason why static linkage can be faster at times.
Dlopen() is certainly a lifesaver sometimes.
your claim of running two library versions at the same time is downright hilarious! this is far harder with dynamic linking, where you need to be sure of loading the right library on every launch of the affected programs than it is with static, where the libraries are just built in to the executables.
This part I don't get "no sensible system loads the entire executable when it's statically linked." If you're a statically linked executable, by definition the entire file is headed into memory, if there was something in the library you didn't use it got edited out in the link step. Now you may mmap the file and fault it in as you go along, but you are going to have the whole thing read.
Surely you must be joking eekee.
I know SSDs have made us all forget, but Disks (you know, those spinning piles of rust that most of us still have in computers to permanently store our bits on) are incredibly, painfully slow. Average times for any action on a disk are in milliseconds. That's millions of computational cycles.
I'm sure someone could invent a system where the dynamic linking process is slower than loading a static executable from a disk, but I've yet to find it. I'm also certain that our assumption that dynamic linking is always the way to go will be more and more challenged by the speed of SSDs, which are becoming much closer to RAM in speeds every day. But for today... no way.
I'm no kernel hacker, but doesn't that make the GP argument better?
It would be almost like static linking?
If code is compiled against a shared lib which always will be at the same address in virtual memory, a linking setup could be cached. (And redone if there is a new version of the library, of course.)
(I realize that caching this symbol table won't be a totally trivial change.)
Programs using shared libraries allow a degree of avoiding blame. It's difficult to judge the real impact of things, it rests upon assumptions about how much the library is shared, while putting pressure on the library to be serve more masters and to become more generalized increasing overall size.
It's not a simple equation. It would be at least interesting to get data on all-static systems as well as compare static linked memory usage vs shared library on an individual basis.
If the OS has rigid dependency tracking (maybe source distros like Gentoo, or a cryptographically tracked binary distribution like freebsd-update), maybe you can live with that.
So there's some trade off of "dll hell" for binary hell, and perhaps some other security advantages to dynamic libs. IMHO shared libraries are pretty well understood now days and static linking should be avoided unless you have a very good reason.
Even in the unlikely case where binaries are statically linked against different versions of a library. You'd still have to check against which version each binary is compiled.
Of course, you also gain in security, since all kind of library preloading attacks are not possible anymore.
"Also a security issue with dynamically linked libraries are executables with the suid flag. A user can easily run dynamic library code using LD_PRELOAD in conjunction with some trivial program like ping. Using a static executable with the suid flag eliminates this problem completely."
Have the authors actually tried this? Using LD_PRELOAD with suid programs won't work.
Was it worth the effort? Eh. But it was instructive and I'd like to attempt (when I get some time) to try a larger project.
This is a very big assumption.
Dynamic linkers are also clever enough to only mmap the required parts of dynamic library.
This is why I like to re-make my shell and associated tools static binaries — shell scripts run 10-20% faster. (lots of small programs running repeatedly)
True, but I'd expect that to be dwarfed by the I/O time required to load even a single 4k page from disk, vs. keeping one copy of a big dynamic library like glibc loaded for the whole system, with fixups done per-process.
Good points about ASLR and static-linking frequently-exec'd-and-exited processes like the shell; and certainly for embedded and HPC it makes sense. I guess the moral, as always, is to measure.
On one hand, you eliminate one attack vector since you take ldd out of the equation. On the other hand, you depend on packagers who distribute their programs to rebuild and relink them every time a security issue creeps up a library they link with. I'm not sure I like that, and I don't have the free time I had in high school when compiling everything by hand seemed really fucking cool.
as for static linking being leaner, i have been told an entire shared library needs to be loaded if so much as 1 program needs a part of it, but i doubt it. i don't see why shared libraries can't be demand loaded just like executables are. then again, demand loading a shared library would be a more complex task, and i have reservations about complexity just like the suckless community does.
> Linking a stripped hello world program with glibc results in 600kb. Linking it with uclibc in about 7kb.
That's nice for uclibc, but we're typically linking dynamically. The comparison should be between dynamically and statically linked binaries. A stripped and dynamically linked hello world results in a 6kb program on my machine (glibc).
There's also a lot of handwaving on memory usage in the FAQ.
I can build busybox (a multi-call all-in-one executable, use symlinks to refer to the binary with the name of a tool and it acts like that tool), with init and bourne shell and the minimal set of command-line tools (coreutils remakes and util-linux remakes) into a 600KiB executable statically linked with uclibc. Combined with a linux kernel, I can boot with it. Meanwhile, my glibc is 2MiB.
Modern computers are really amazing. And it's also amazing that the understandable trend of letting software get bigger and slower as long as it doesn't really cause problems on current hardware has resulted in such astounding (though mostly harmless) waste.
All that said, these stali project pages have existed for years, and there's nothing interesting to show for it. Not that many people really buy into this thing (including me).
As it stands, the FAQ entry is comparing apples and oranges. Comparing full-featured and dynamically linked programs to statically linked, but feature-limited ones is only interesting if you can get by with the feature-limited version. I suspect we're in agreement.
Is that the proportional size (binary size + glibc size / number of things using glibc), or just the size of the binary?
If we add more functionality to the hello world program, the dynamically linked version should increase in size slower than the statically linked.
Totally. Reading the FAQ reminded me of https://xkcd.com/386/
Not sure about "changing code during runtime", but one of the great benefits of dynamic-link libraries are for writing plugins. And I don't think it would take much time for an app to look up its own plugin folder.
As I see it suckless.org community prefers 'linking' in form of shell scripts or communication via pipes, ideally via system's VFS.
You will get lean and minimalistic base system. If something will not share same ideals it will not be in the base system (like glib[c]?, bash, Firefox). It is possible that dynamic linking will be allowed in /emul chroot as stated in 'Filesystem' page.
I see sta.li as rock solid minimalistic base system, which you can use on it's own (how I belive many suckless.org folks will use it) or as a base system, that you can build upon. Even more than that, you will be able to use sta.li components in generic distributions with ease, because of static linking.
Go-lang is in my opinion next step for Bell Labs folks in lean development for the masses. Don't take this too literally ;) Plan 9 [1] was first step, but people did not want whole new system. Inferno [2] was next one, but VM system was too much also. Go allows to use some of Plan 9 features in edible form for the masses. Without requirement to install specific system or VM to run your programs. That to some extent is what makes sta.li's ideals similar to go-lang's.
Development of sta.li is at slow pace, but many experiments are under development [3]. Probably some of them will be included in sta.li. Most probably sta.li will include X11, but we are seeing some developments with Wayland [4].
[1] - http://en.wikipedia.org/wiki/Plan_9_from_Bell_Labs [2] - http://en.wikipedia.org/wiki/Inferno_%28operating_system%29 [3] - https://github.com/henrysher/sinit - http://galos.no-ip.org/sdhcp - http://git.suckless.org/dmc/ [4] - https://github.com/michaelforney/swc
http://www.youtube.com/watch?v=Zu9Qm9bNMUU
I'm not qualified to comment on Stali itself but, more generally, I can't recommend Suckless software highly enough.
Since I switched to Linux a few years back I've found myself using more and more of their programs--DWM, Dmenu, ST, Tabbed, Slock and Surf.
Before, I'd hop from one window manager, terminal or browser to another but, for me, Suckless programs just tend to stick because of the minimal philosophy.
This causes gcc to put each function in a separate section in the resulting object file, and the -gc-sections option makes ld strip the sections that are not reachable by calls from main (basically a tree-shaker).
"Because dwm is customized through editing its source code, it’s pointless to make binary packages of it. This keeps its userbase small and elitist. No novices asking stupid questions. There are some distributions that provide binary packages though."
Over the past 17 or so years I've been using linux full-time, I've experienced 3 or 4 of the "sweet spots", or times where using linux was superior to everything else on the market. GNOME 1.x with Enlightenment 0.15 (vs Win98) was the second one (the first, I'm told, was E DR0.13 with CmdrTaco's task managing app and Hand of God theme vs Win95). I believe we are currently at the end of another sweet spot with KDE 4.x being put out to pasture, as it completely destroys the UX of Windows 7/8 and Mountain Lion.
But don't knock the state of linux circa 1999. Sure, you had to ensure your sound cards had OSS drivers, and Winmodems sucked, but it was a superior experience to Win9x even back then.
Furthermore I suspect the scope of stali will be so narrow that I will never be able to run say a CL implementation on it. Pretty much the same as Plan9, I love the design but it's practically useless for me. :(