In this article I will cover the steps necessary to enable and configure Linux binary compatibility on FreeBSD 6. I'll also share a couple of my own experiences with getting some well-known desktop Linux applications to run on FreeBSD 6.
How does it work?
Although it is by no means essential to understand how Linux compatibility actually works, it sometimes helps to have an idea when it comes to problem solving.
Linux compatibility isn't instruction-level emulation or some kind of virtual machine. The Linux ABI is implemented in the FreeBSD kernel, so in most senses the Linux binaries could be considered to be running natively. Through what appears to be some sleight-of-hand the system selects at run time the Right Thing to do to run an executable. This is partly figured out based on branding information encoded in an ELF binary header. A command-line tool called brandelf can be used to report the brand:
# brandelf /usr/X11R6/lib/firefox/firefox-bin File '/usr/X11R6/lib/firefox/firefox-bin' is of brand 'FreeBSD' (9). # brandelf /usr/X11R6/lib/linux-firefox/firefox-bin File '/usr/X11R6/lib/linux-firefox/firefox-bin' is of brand 'SVR4' (0).
This tool will also brand a binary if you use the -t option. Normally this isn't needed -- the brand is always set correctly for any recently built binaries.
After looking at the brand, the FreeBSD ELF loader will arrange to use the correct set of system calls -- Linux as opposed to FreeBSD. It will also link the correct shared libraries at run time. Shell scripts can be forced to run similarly by setting the first line to
#!/compat/linux/bin/sh and, although it isn't often needed, you can alter the environment by setting the UNAME_s environment variable (reported using uname -s) to Linux rather than FreeBSD.
For those who want to understand the real nuts and bolts, the FreeBSD Handbook has a more complete and accurate explanation.
Linux binary support is said to be less than 100% but I have rarely experienced any problems I could not trace to unresolved shared library dependencies. With this feature, FreeBSD users can run many Linux binaries easily and at performance levels that rival that of the native platform.
PreliminariesIf you are running the GENERIC FreeBSD 6 kernel you're already set -- kernel Linux compatibility is compiled in by default. If you are not running the GENERIC kernel, or you are not sure what options are turned on in your kernel, you can perform a quick check by attempting to load the Linux kernel loadable object by hand. Use the kernel load utility as root:
# kldload linux
If it reports kldload: can't load Linux: File exists, you know you already have Linux compatibility loaded or compiled in. If it reports nothing at all, you have just succeeded in loading the Linux kernel loadable object. You can verify this by using the companion kernel status utility:
# kldstat
It returns a list of the currently loaded dynamically loadable kernel objects. If you don't have Linux compatibility compiled in, kldstat should now report that the object linux.ko has been loaded. (You can unload it manually by using the kernel unload utility, kldunload .) If you want to load the Linux object automatically every time you boot, add the following line to /boot/loader.conf:
linux_load="YES"
If you want to build Linux compatibility into the kernel so that there is no need to load the object every time, follow the instructions for building a new kernel and make sure that the following options are uncommented in your kernel configuration file (use COMPAT_LINUX32 instead of COMPAT_LINUX if you're building for amd64):
option COMPAT_43
option COMPAT_LINUX
option PSEUDOFS
option LINPROCFS
The last of those kernel configuration options enables support for the Linux Process File System procfs which some Linux applications may require. The procfs normally allows applications to query process or device information from the kernel. You can add the following to /etc/fstab to ensure that the Linux procfs is mounted:
none /compat/linux/proc linprocfs rw 0
0
Note that it is mounted at /compat/linux/proc, not /proc as is usual on Linux. This is to distinguish it from the FreeBSD procfs which, if it is mounted at all, will be mounted at /proc.
Once you have updated /etc/fstab, type mount -a to mount the Linux procfs. It will happen automatically next time you boot.
Now that you have linux.ko loaded, or verified that it is compiled in,
you are ready to run Linux binaries. In fact, you will be able to run 100% Linux binaries without any more ado. The only problem is that the Linux binaries you want to run are unlikely to be statically linked. They may have anything from a handful to dozens of shared library dependencies (for example, the native Firefox on my system has 29 shared library dependencies, and a version built for Linux will have at least as many). You can see these dependencies for yourself by running ldd on any native application.
# ldd /usr/X11R6/lib/firefox/firefox-bin
For a Linux binary, these dependencies must be met by shared libraries compiled for Linux (the ones already installed on your FreeBSD system won't do) and they must be the same versions of the libraries that were used when the binary was compiled.
You should resist the temptation to copy Linux libraries off your nearest Linux system into /usr/lib or /usr/local/lib -- it's a recipe for disaster to mingle foreign libraries with native FreeBSD libraries. On FreeBSD, foreign binaries are cordoned off under /compat/linux, a directory that's created and populated when you install a base Linux compatibility environment.
There are two main approaches to putting together a Linux base under /compat/linux: install it from ports or build it by hand using Linux packages from a Linux distribution of your choosing. The first approach is usually the way to go -- it's generally simpler and is consistent with the FreeBSD practice of using ports and packages for installation. The alternative method may be harder work but gives you more control and allows you to select a package-based Linux distribution of your own liking. I'll describe only the ports approach; if you want to follow the second approach, you should should check out the consise instructions by FreeBSD's Tim Robbins. (I'll vouch that it works, as I initially followed that route using Slackware 10.2 packages, with good success.)
Installing from portsYes, there are Linux ports that download Linux binary packages onto your FreeBSD system! To get a rough idea how many such ports there are, go to /usr/ports and type:
# make search name=linux | grep Path
Most of ports on this list are individual Linux libraries, some are Linux applications, and those under /usr/ports/emulators are the base Linux library sets. This is only a rough list though -- not all such ports include 'linux' in the name. For example, the Adobe Acrobat Reader 7 for Linux port is 'print/acroread7.'
The base port upon which many of the Linux ports ultimately depend is linux_base-8. This is a foundational set of packages using Red Hat 8 i386 binary RPM packages. It isn't the only base Linux port though. There are others -- most more recent than Red Hat 8 -- but they conflict with each other, so you'll only be able to install one. As linux_base-8 is the port upon which all the other Linux ports depend, it's the one to go for if you want things simple and want to take advantage of the hard work the port maintainers put into figuring out all the binary dependencies for each application. If, on the other hand, you want a more recent Linux base or one that you're already familiar with, and you don't mind getting your hands dirty figuring out and downloading dependencies yourself, then you have a choice. More about that approach later.
For now, let's deal with linux_base-8. To install it:
# cd /usr/port/emulators/linux_base-8
# make install && make clean
If you prefer not to install right away, just type make. This downloads the RPMs from Fedora Legacy to /usr/ports/distfiles/rpm/i386/8.0. Once they're downloaded, make install will unpack them so that they end up rooted at /compat/linux. Under this directory you'll then find usr, lib, etc, and var, under which you'll find all the Linux binary shared libraries and configuration files. It's usually not necessary but you can explicitly chroot to the environment by typing chroot /compat/linux /bin/bash. At this point you'll only be able to run the Linux binaries under FreeBSD compatibility, in the chrooted environment. Press Ctrl-D or type exit to leave it.
Now, if you wish to install, say, Linux Opera (native Opera is only available for i386 FreeBSD) go to /usr/ports/www/linux-opera and type make install && make clean. This will download more RH8 RPMs that meet additional dependencies not met by linux_base-8, as well as the Linux Opera RPM. Again, library dependencies will end up under /compat/linux, but a startup script for the Linux Opera (version 8.51) will be installed under /usr/bin, and Opera itself under /usr/X11R6/share/linux.opera. If you want Flash installed for the Linux browser binary, go to /usr/ports/www/linux-flashplugin7 and type make install && make clean again. Now if you run linux-opera, you should find it has the Flash plugin already configured.
Using this Red Hat 8 install you should be able to install a load of applications, including Skype, Firefox 1.5 (which will also use the Flash plugin), and Adobe Acrobat Reader 5 or 7. In general you will meet with success, but sometimes binary dependencies will fail to download, and some dependencies may not be met even if the install appears to succeed.
If this happens, you may be able to fix up the runtime dependencies by hand. If you run the Linux application from the command line and it complains about missing shared libraries, you may be able to make an educated guess as to what RH8 RPM a missing library lives in and download it from the Red Hat 8 RPM archives at Fedora Legacy. (And herein lies the black art of setting up compatibility -- RPMs often contain multiple libraries and may have additional RPM dependencies. Finding the right ones may not be as difficult as it sounds, though; RPMs usually have meaningful names, so you can often put two and two together, given the full list of RPMs at Fedora Legacy. You can also use rpm2cpio rpm-name.rpm | cpio -itv (both tools found under /usr/ports/archivers) to list the RPM table of contents.) Once you've located and downloaded it, install the RPM to /compat/linux as root as follows:
# /compat/linux/bin/rpm -ihv --root=/compat/linux
rpm-name.rpm
If this command itself complains about missing RPM package dependencies, first check whether the library files are already present under /compat/linux (they may be, even if rpm is complaining). If they're not, as before, find, download, and install the RPM that supplies the missing library as identified by the rpm error message. Once you've installed the dependencies, go back and install the original RPM. You can force the RPM installion to go ahead even with missing RPM package dependencies by adding the --nodeps flag to the rpm command options. Do this if you figure the missing libraries are in place even if it is complaining that the RPM packages have not been installed.
If you decide you need to remove an RPM package, use the command:
/compat/linux/bin/rpm -e --root=/compat/linux
package-name
Note that in all these cases you are using the Linux rpm tool -- not the native FreeBSD rpm tool that you may have on your system. Any attempt to use the FreeBSD rpm command on a Linux RPM file will have it complaining about the RPM being for the wrong architecture. Conceivably, you could use FreeBSD's rpm2cpio and cpio commands (under /usr/ports/archivers), as follows:
# cd /compat/linux
# rpm2cpio rpm-name.rpm | cpio -ih
This unceremoniously unpacks an RPM and dumps it under /compat/linux. Using the Linux rpm is a better method, however.
At this point you may feel happy that you are able to run the Linux binaries you are interested in and that they complement your native FreeBSD applications nicely. You can run linux-opera or linux-firefox or Skype without any bother. But this may not be enough. You may not have the version of the Linux application that you want, or you may have trouble getting recently compiled binaries, for which you have no source and which don't appear in ports, to run on this older Red Hat environment. This may be the reason why there are a variety of other base Linux ports under /ports/emulators.
Note that you will not be able to install any of these other ports at the same time as linux_base-8, and if you install an alternative to linux_base-8 you will not be able to install any other Linux application from ports -- they all depend on linux_base-8. So, if you use any of these, you will have to install Linux binaries by hand using the techniques described above for resolving unmet dependencies -- using packages appropriate to your chosen Linux base rather than RH8 RPMs, of course. You will also have to deinstall linux_base-8 and any other Linux applications and libraries before you can install an alternative.
Of the alternative Linux bases, two -- linux_base-debian and linux_base-gentoo-stage1 -- are marked suitable for the Alpha architecture (in addition to i386 and amd64) and, in the case of Gentoo, ia64. However, both were marked as broken at the time of my writing. I was able to install the SUSE 9.3 base, linux_base-suse-9.3, and run applications I had trouble running under Red Hat 8. (On the other hand, I was unable to get Adobe Acrobat Reader 7 running under linux_base-suse-9.3 even though it ran fine when installed from ports using linux_base-8.)
I could not get RealPlayer10 to install and work under linux_base-8. With SUSE 9.3 I downloaded and unpacked the binary by hand and got it running after I applied a couple of fix-ups to the SUSE base environment. The base SUSE 9.3 is missing a couple of auto-generated configuration files, namely pango.modules and gdk-pixbuf.loaders. The first prevented RealPlayer from running and, once I'd fixed it, the second caused the buttons to have no pixmaps. I created these configuration files by hand using the following commands:
# cd /compat/linux/opt/gnome/bin
# ./pango-querymodules | sed 's/opt\//compat\/linux\/opt\//g' > /compat/linux/etc/opt/gnome/pango/pango.modules
# ./gdk-pixbuf-query-loaders | sed 's/opt\//compat\/linux\/opt\//g' > /compat/linux/etc/opt/gnome/gtk-2.0/gdk-pixbuf.loaders
Now I'm running SUSE 9.3 as my preferred base Linux environment, in preference to my earlier Slackware 10.2 hand-rolled effort (fonts looked bad with Slackware, although I'm sure I could have solved the problem) and Red Hat 8, despite the availability of associated ports for many Linux applications.
Why not just run Linux?After all this, you may wonder why anyone would bother jumping through these hoops rather than simply wipe the box clean and install Linux. Maybe for the same reason Linux users run essential Windows applications under Wine -- I run FreeBSD because I like it. It has a huge number of applications available for it. Being able to run a few applications that are available only for Linux is a bonus. Hopefully the trend will continue and a shrinking number of applications will fall into this category. (It is always worth double-checking that an application is not already in ports before selecting the Linux version.) Perhaps soon we'll see an amd64 Opera (or substitute your closed-source app of choice) and the availability of good alternative open source browser plugins built for the common *BSD architectures and versions.
Note: Comments are owned by the poster. We are not responsible for their content.
I can remember a day when Linux had no binary support from NVidia, ATI, or Matrox. But apparently Linux users still saw some reason to continue on despite this obvious flaw.
Also, I can tell you've never heard of DRI, the Direct Rendering Infrastructure, which is a standard interface for acceleration for XFree86 and Xorg that ATI, Matrox, and other vendors have been contributing to for a while now. The development DRI can drive quite a bit of the r300 chipset, and all of the r250 and previous chipsets. The infrastructure is a real extension to X, and it's all open sourced and available on sourceforge! It's very ironic that Linux users, the self-acclaimed champions of open source software, would prefer to rely on a binary released libGL hack to drive their hardware rather than champion an open source infrastructure.
You can use the BSD kernel as the kernel for a GNU system. Isn't that all this is about?
The resulting system would be indistinguishable, for most users (including most "Linux" fans), from a GNU/Linux system.
The main difference that could be noticed is that the Linux kernel has support for a wider range of hardware devices than any BSD. So most people would be better off with GNU/Linux. Which presumably is one of the reasons it's more popular.
Gordon McEwen
Gordon - sorry, but this is nonesense
Posted by: Anonymous Coward on April 01, 2006 10:47 AMOk. That's a matter of taste, but your example does not apply. A "Windows application" is just that, an application, not an OS. Running a good Windows application under Wine is not at all comparible to running FreeBSD which is an OS. But ok - liking anything is a matter of taste.
It has a huge number of applications available for it.
WTF?!?! Debian Sarge has 18000+ applications, does FreeBSD come even close? No. In terms of stability and security Debian has been a match for *BSD for a quite a while now, so there is really no rational reason to stick with *BSD, in particular for a *desktop* which is what you say you are using it for.
I tried various flavors of *BSD and none come even close to the power of Debian which is a superior product to any *BSD (or any other Linux distro for that matter) in pretty much any use. Ok - between, say Lindows or OSX and FreeBSD I would definitely choose FreeBSD. But with Debian out there? Never.
I do not intend to troll by starting a "my OS/distro is better than yours" flamewar (although some will probably accuse me of just that) - but since your article concludes with exactly this issue, let me ask you this: can you name me one reason - besides issues of taste which are inherently subjective but still very legitimate - to use FreeBSD with some GNU/Linux application when Debian is out there?
And since you seem to like having a choice of many applcation - does *BSD have anything as good as apt-get?!
Cheers!
#