musl, pronounced like the word “mussel” or “muscle”, is a “libc”, an implementation of the standard library functionality described in the ISO C and POSIX standards, plus common extensions, built on top of the Linux system calls API. While the kernel governs access to hardware, memory, filesystems, and the privileges for accessing these resources, libc is responsible for:
providing C bindings for the OS interfaces
constructing higher-level buffered stdio, memory allocation management, thread creation and synchronization operations, shared library loading, and so on using the lower-level interfaces the kernel provides
implementing the pure library routines of the C language like
strstr
, snprintf
, strtol
, exp
, sqrt
, etc.
musl has history and development roots going back to 2005, but was named and first released as musl in 2011, as an alternative to glibc and uClibc with an ambitious goal to meet the needs of both tiny embedded systems and typical desktops and servers.
Since 2012, musl has been licensed under the permissive MIT license.
The simpler code is, the less room it has for bugs, and the less costly it is to make major changes when they're required. Simplicity tends to lead naturally to optimal code size and reasonably-good performance. musl favors simple algorithms over more complex ones unless there's a compelling reason to do otherwise. musl also favors minimizing abstractions, keeping code as self-contained/uncoupled as possible. This tends to make it readable (although sometimes dense) and size-efficient when static-linked.
Scaling well "as n goes to 0" can matter as much if not more than scaling "as n goes to ∞". Design around this principle started out with embedded and low-end desktops in mind, but ended up carrying musl (and like-minded distributions) to prominence in the container deployment wave.
Due to lack of heavy internal coupling between libc components, static linking with musl pulls in very little code that the application isn't actually using. Minimal static-linked binaries can be under 10 kB of code, even with threads, and even useful programs can be under 50 kB.
The principle of low constant overhead applies to runtime resource
consumption as well. libc's own global data size is kept as small as
possible - under 8k, and potentially much less when static linking.
For dynamic linking, all functionality is in a single shared library
file (rather than being split across libm
, libpthread
, librt
,
etc.) so that there's no per-component memory and startup time
overhead.
Part of musl's scaling "as n goes to 0" is the ability to run on small stacks, making designs involving large numbers of threads practical even in resource-constrained environments.
musl was the first Linux libc to have mutexes safe to use inside reference-counted objects, the first to have condvars where newly-arrived waiters can't steal wake events from previous waiters, and the first to have working thread cancellation without race conditions producing resource-leak or double-close. All of these are requirements of the specification that were ignored by other implementations, and getting them right was a consequence of careful reading of those specifications.
musl's entire development history has been a process of reading specifications, seeking clarifications when corner cases aren't adequately covered, and proceeding with extreme caution when implementing functionality that's underspecified.
Part of correctness is not getting yourself into a bad situation with no way out. musl always reserves resources for an operation before committing to it, backing out if resources are not available. Low-memory or other resource exhaustion conditions are never fatal; they're always caught (assuming a no-overcommit system configuration) at a point where they can be reported, allowing the application to handle them as it deems fit.
In general, musl avoids unnecessary dynamic allocation, and has no dynamic allocation at all in code paths where reporting failure to the caller is not a possibility.
musl's MIT license is compatible with all FOSS licenses, static-linking-friendly, and makes commercial use painless. Binaries statically linked with musl have no external dependencies, even for features like DNS lookups or character set conversions that are implemented with dynamic loading on glibc. An application can really be deployed as a single binary file and run on any machine with the appropriate instruction set architecture and Linux kernel or Linux syscall ABI emulation layer.
From even before musl was musl, treatment of all text as UTF-8, and
treatment of non-ASCII characters as first-class, was a core
requirement. No external locale files or conversion modules are needed
to process UTF-8 or query properties of arbitrary Unicode characters.
Even musl's getopt
allows arbitrary Unicode characters to be used as
options.
DNS support for non-ASCII domains (IDN) is not complete yet but will be supported in the future.
Localization functionality, a related but different matter, is also presently limited but slated for major improvements.
With the musl-gcc
(or musl-clang
) wrapper shipped with musl
source, it's possible on x86 Linux and other mainstream archs to
evaluate musl and build simple C programs by repurposing your system's
existing glibc-based toolchain. For more advanced usage involving
libraries or C++, though, a dedicated cross toolchain or building in a
musl-based distribution is recommended. Details can be found on the
community wiki's Getting
Started page.