The FreeBSD-linuxulator explained (for users)

After anoth­er mail where I explained a lit­tle bit of the lin­ux­u­la­tor behav­ior, it is time to try to make an easy text which I can ref­er­ence in future answers. If some­one wants to add parts of this expla­na­tion to the FreeB­SD hand­book, go ahead.

Lin­ux emu­la­tion? No, “native” exe­cu­tion (sort of)!

First, the lin­ux­u­la­tor is not an emu­la­tion. It is “just” a bina­ry inter­face which is a lit­tle bit dif­fer­ent from the FreeBSD-“native”-one. This means that the bina­ry files in FreeB­SD and Lin­ux are both files which com­ply to the ELF spec­i­fi­ca­tion.

When the FreeB­SD ker­nel loads an ELF file, it looks if it is a FreeB­SD ELF file or a Lin­ux ELF file (or some oth­er fla­vor it knows about). Based upon this it looks up appro­pri­ate actions in a table for this bina­ry (it can also dif­fer­en­ti­ate between 64-bit and 32-bit, and prob­a­bly oth­er things too).

The FreeBSD-table is always com­piled in (for a bet­ter big pic­ture: at least on an AMD/Intel 64-bit plat­form there is also the pos­si­bil­i­ty to include a 32-bit ver­sion of this table addi­tion­al­ly, to be able to exe­cute 32-bit pro­grams on 64-bit sys­tems), and oth­er ones like the Lin­ux one can be loaded addi­tion­al­ly into the ker­nel (or build sta­t­i­cal­ly in the ker­nel, if desired).

Those tables con­tain some para­me­ters and point­ers which allow to exe­cute the bina­ry. If a pro­gram is mak­ing a sys­tem call, the ker­nel will look up the cor­rect func­tion inside this table. It will do this for FreeB­SD bina­ries, and for Lin­ux bina­ries. This means that there is no emulation/simulation (over­head) going on… at least ide­al­ly. Some behav­ior is a lit­tle bit dif­fer­ent­ly between Lin­ux and FreeB­SD, so that a lit­tle bit of translation/house-keeping has to go on for some Lin­ux sys­tem calls for the under­ly­ing FreeB­SD ker­nel functions.

This means that a lot of Lin­ux stuff in FreeB­SD is han­dled at the same speed as if this Lin­ux pro­gram would be a FreeB­SD program.

Lin­ux file/directory tricks

When the ker­nel detects a Lin­ux pro­gram, it is also play­ing some tricks with files and direc­to­ries (also a prop­er­ty of the above men­tioned table in the ker­nel, so the­o­ret­i­cal­ly the ker­nel could play tricks for FreeB­SD pro­grams too).

If you look up for a file or direc­to­ry /A, the ker­nel will first look for /compat/linux/A, and if it does not find it, it will look for /A. This is impor­tant! For exam­ple if you have an emp­ty /compat/linux/home, any appli­ca­tion which wants to dis­play the con­tents of /home will show /compat/linux/home. As it is emp­ty, you see noth­ing. If this appli­ca­tion does not allow you to enter a direc­to­ry man­u­al­ly via the key­board, you have lost (ok, you can remove /compat/linux/home or fill it with what you want to have). If you can enter a direc­to­ry via the key­board, you could enter /home/yourlogin, this would first let the ker­nel look for /compat/linux/home/yourlogin, and as it can not find it then have a look for /home/yourlogin (which we assume is there), and as such would dis­play the con­tents of your home directory.

This implies sev­er­al things:

  • you can hide FreeB­SD direc­to­ry con­tents from Lin­ux pro­grams while still being able to access the content
  • bad­ly” pro­grammed Lin­ux appli­ca­tions (more cor­rect­ly: Lin­ux pro­grams which make assump­tions which do not hold in FreeB­SD) can pre­vent you from access­ing FreeB­SD files, or files which are the same in Lin­ux and FreeB­SD (like /etc/group which is not avail­able in /compat/linux in the linux_base ports, so that the FreeB­SD one is read)
  • you can have dif­fer­ent files for Lin­ux than for FreeBSD

The Lin­ux userland

The linux_base port in FreeB­SD is com­ing from a plain instal­la­tion of Lin­ux pack­ages. The dif­fer­ence is that some files are delet­ed, either because we can not use them in the lin­ux­u­la­tor, or because they exist already in the FreeB­SD tree at the same place and we want that the Lin­ux pro­grams use the FreeB­SD file (/etc/group and /etc/passwd come to mind). The instal­la­tion also marks bina­ry pro­grams as Lin­ux pro­grams, so that the ker­nel knows which kernel-table to con­sult for sys­tem calls and such (this is not real­ly nec­es­sary for all bina­ry pro­grams, but it is hard­er to script the cor­rect detec­tion log­ic, than to just “brand” all bina­ry programs).

Addi­tion­al­ly some con­fig­u­ra­tions are made to (hope­ful­ly) make it do the right thing out of the box. The com­plete set­up of the linux_base ports is done to let Lin­ux pro­grams inte­grate into FreeB­SD. This means if you start acrore­ad or skype, you do not want to have to have to con­fig­ure some things in /compat/linux/etc/ first to have your fonts look the same and your user IDs resolved to names (this does not work if you use LDAP or ker­beros or oth­er direc­to­ry ser­vices for the user/group ID man­age­ment, you need to con­fig­ure this your­self). All this should just work and the appli­ca­tion win­dows shall just pop up on your screen so that you can do what you want to do. Some linux_base ports also do not work on all FreeB­SD releas­es. This can be because some ker­nel fea­tures which this linux_base ports depends upon is not avail­able (yet) in FreeB­SD. Because of this you should not choice a linux_base port your­self. Just go and install the pro­gram from the Ports Col­lec­tion and let it install the cor­rect linux_base port auto­mat­i­cal­ly (a dif­fer­ent FreeB­SD release may have a dif­fer­ent default linux_base port).

A note of cau­tion, there are instruc­tions out there which tell how to install more recent linux_base ports into FreeB­SD releas­es which do not have them as default. You do this on your own risk, it may or may not work. It depends upon which pro­grams you use and at which ver­sion those pro­grams are (or more tech­ni­cal­ly, which ker­nel fea­tures they depend upon). If it does not work for you, you just have two pos­si­bil­i­ties: revert back and for­get about it, or update your FreeB­SD ver­sion to a more recent one (but it could be the case, that even the most recent devel­op­ment ver­sion of FreeB­SD does not have sup­port for what you need).

Lin­ux libraries and “ELF file OS ABI invalid”-error messages

Due to the above explained fact about file/directory tricks by the ker­nel, you have to be care­ful with (addi­tion­al) Lin­ux libraries. When a Lin­ux pro­gram needs some libraries, sev­er­al direc­to­ries (spec­i­fied in /compat/linux/etc/ld.so.conf) are searched. Let us assume that the /compat/linux/etc/ld.so.conf spec­i­fies to search in /A, /B and /C. This means the FreeB­SD ker­nel first gets a request to open /A/libXYZ. Because of this he first tries /compat/linux/A/libXYZ, and if it does not exist he tries /A/libXYZ. When this fails too, the Lin­ux run­time link­er tries the next direc­to­ry in the con­fig, so that the ker­nel looks now for /compat/linux/B/libXYZ and if it does not exist for /B/libXYZ.

Now assume that libXYZ is in /compat/linux/C/ as a Lin­ux library, and in /B as a FreeB­SD library. This means that the ker­nel will first find the FreeB­SD library /B/libXYZ. The Lin­ux bina­ry which needs it can not do any­thing with this FreeB­SD library (which depends upon the FreeB­SD syscall table and FreeB­SD sym­bols from e.g. libc), and the Lin­ux run­time link­er will bail out because of this (actu­al­ly he sees that the lin is not of the required type by read­ing the ELF head­er of it). Unfor­tu­nate­ly the Lin­ux run­time link­er will not con­tin­ue to search for anoth­er library with the same name in anoth­er direc­to­ry (at least this was the case last time I checked and mod­i­fied the order in which the Lin­ux run­time link­er search­es for libraries… this has been a while, so he may be smarter now) and you will see the above error mes­sage (if you start­ed the lin­ux pro­gram in a terminal).

The bot­tom line of all this is: the error mes­sage about ELF file OS ABI invalid just means that the Lin­ux pro­gram was not able to find the cor­rect Lin­ux library and got a FreeB­SD library instead. Go, install the cor­re­spond­ing Lin­ux library, and make sure the Lin­ux pro­gram can find it instead of the FreeB­SD library (do not for­get to run “/compat/linux/sbin/ldconfig ‑r /compat/linux” if you make changes by hand instead of using a port, else your changes may not be tak­en into account).

Con­straints regard­ing chroot into /compat/linux

The linux_base ports are designed to have a nice install-and-start expe­ri­ence. The draw­back of this is, that there is not a full Lin­ux sys­tem in /compat/linux, so doing a chroot into /compat/linux will cause trou­ble (depend­ing on what you want to do). If you want to chroot into the lin­ux sys­tem on your FreeB­SD machine, you bet­ter install a linux_dist port. A linux_dist port can be installed in par­al­lel to a linux_base port. Both of them are inde­pen­dent and as such you need to redo/copy con­fig­u­ra­tion changes you want to have in both environments.

Weath­er sta­tion read­out with FreeBSD

A while ago a wind tur­bine was installed not far away from my place. It is far enough to not dis­turb us, and it is near enough to notice that it turns a lot (IIRC I have seen it only once not turning).

This trig­gered a ques­tion. How much ener­gy would such a device (small­er of course) pro­duce at my place?

The answer depends upon sev­er­al fac­tors. The wind speed, the wind direc­tion and the wind-speed-to-power-output curve of the device. If you do not take a device which rotates around the hor­i­zon­tal axis but the ver­ti­cal axis, the wind direc­tion can be tak­en out of the ques­tion (prob­a­bly not com­plete­ly, but to answer my ques­tion this sim­pli­fi­ca­tion should be ok). The output-power curve depends upon the device, and I hope it is easy to get it from the ven­dors. The remain­ing open ques­tion it the wind speed at my place. Is there enough wind with enough speed?

To answer this ques­tion I bought a weath­er sta­tion with an anemome­ter (wind speed sen­sor). I searched a lit­tle bit until I decid­ed to buy a spe­cif­ic one (actu­al­ly I bought three of them, some cowork­ers got inter­est­ed too but they found only much more expen­sive ones, so soon there will be three more weath­er sta­tions in use in Bel­gium, France and Ger­many). The main point is, I can con­nect it to an USB port of a PC and there is some soft­ware for Lin­ux to read out the data. It also comes with some oth­er outdoor-sensors (tem­per­a­ture, rain, wind direc­tion, humid­i­ty, …) and an indoor-control-unit with some inter­nal sen­sors (tem­per­a­ture, humid­i­ty). The user inter­face is main­ly the touch­screen of the control-unit. There is also some Win­dows soft­ware, which is need­ed to pro­gram the inter­val in which the mea­sure­ments are tak­en and saved in the control-unit.

It seems the weath­er sta­tion is pro­duced by Fine Off­set Elec­tron­ics Co.,Ltd and sold with­in dif­fer­ent brands in dif­fer­ent loca­tions. The Lin­ux soft­ware can read all of them, as the ven­dor and prod­uct IDs are not changed.

Port­ing the soft­ware was easy, it uses libusb and I just had to cor­rect a lit­tle prob­lem for the non-portable func­tions which are used (I asked about them on usb@ and the response was that they just got imple­ment­ed upon my request and will be com­mit­ted to HEAD soon). I made a lit­tle patch for the soft­ware to only use them when avail­able (if you have not loaded the USB HID dri­ver, you do not need to care about them) and com­mit­ted it to the Ports Col­lec­tion as astro/fowsr.

Now I just need to attach the out­side sen­sors at the place where I would put the ver­ti­cal axis wind tur­bine, install some toolk­it which takes a series of mea­sure­ments and dis­plays them as a nice graph (while keep­ing all data val­ues) and write some glue code to feed the out­put of fowsr to it. After a year I can then cal­cu­late how much pow­er a giv­en wind tur­bine would have pro­duced dur­ing the year and cal­cu­late the return of invest­ment for it.

The Lin­ux soft­ware also ref­er­ences sev­er­al weath­er sites, for some of them you can get even an iGoogle wid­get so that you can view the data from wher­ev­er you want (as long as you have a suit­able inter­net con­nec­tion). I think this is also some­thing I will have a look at later.

Note to users in Europe, the device also comes with a DCF77 receiv­er. As the time is dis­trib­uted in UTC+1 (or +2, depend­ing on the day­light sav­ing time), you should adjust the time­zone set­ting accord­ing­ly to this, not to plain UTC (so for me the time­zone should be ‘0’ for the same timezone).

Direct, indi­rect and explic­it depen­den­cies in progams/ports

The dis­cus­sion about direct and indi­rect depen­den­cies is com­ing up again on the FreeB­SD mail­inglists. Seems I should make some blog post about it, maybe it makes this top­ic more find­able than my post­ings in the mailinglists.

Some def­i­n­i­tions:

  • A direct depen­den­cy from A to B is when program/port A uses sym­bols from library/port B.
  • An indi­rect depen­den­cy from A to C is when program/port A uses sym­bols from library/port B but no sym­bols from library/port C, and library/port B uses sym­bols from library/port C.
  • An explic­it depen­den­cy from A to C is when it is a direct or indi­rect depen­den­cy A to C, and when the compiler-time-linker added an explic­it ref­er­ence to C to the program/lib of A.

Ide­al­ly we have no indi­rect depen­den­cies in the explic­it depen­den­cies, only direct depen­den­cies. Unfor­tu­nate­ly in real­i­ty we also have indi­rect depen­den­cies there. This has at least two causes:

  1. libtool (at least 1.x) does not (or was not) come with a hint on FreeB­SD, which tells that the run-time-linker is recur­sive­ly resolv­ing dependencies.
  2. Some pkg-config setups list indi­rect depen­den­cies as explic­it depen­den­cies (IIRC it depends if Requires.private and/or Libs.private is used in the .pc file or not; if it is used, there should be no indi­rect depen­den­cy appear from this soft­ware, but I am not 100% sure about this).

Three years ago I wrote /usr/ports/Tools/scripts/explicit_lib_depends.sh, it looks at the files of a giv­en port (it needs to be installed), and prints out explic­it depen­den­cies. Because of the indi­rect depen­den­cies which could be list­ed there, this list is not a list of ports which are real depen­den­cies from a source code point of view, but it reflects the link-time real­i­ty. If a port C shows up there, the port which is checked needs to be rebuild in case the ABI of library/port C changes.

LAME updat­ed in the FreeB­SD ports collection

After all the big-impact com­mits (Gnome/gettext/KDE/X11/…) have set­tled now, I took the time to update audio/lame (I iden­ti­fied more than 100 ports with an (implic­it) depen­den­cy on lame, 45 of them need­ed a portre­vi­sion bump; if I forgot/overlooked some, bump the revi­sion your­self or noti­fy me please). That is the first update of my ports where miwi@ did not beat me in com­mit­ting an update since a year (he has implic­it approval to do any­thing he wants with my ports).

I can be hap­py that he is/was this fast (and that we have such a pro­duc­tive and effi­cient com­mit­ter), or I can be sad that I do not have the time any­more to be faster than I am with such things… or both. Hmmm… I think I will go the hap­py way. 😉

Cheap process mon­i­tor­ing (no addi­tion­al soft­ware required)

I have an old sys­tem (only the hard­ware, it runs ‑cur­rent) which reboots itself from time to time (most­ly dur­ing the dai­ly periodic(8) run, but also dur­ing a lot of com­pil­ing (por­tup­grade)). There is no obvi­ous rea­son (no pan­ic) why it is doing this. It could be that there is some hard­ware defect, or some­thing else. It is not impor­tant enough to get a high enough pri­or­i­ty that I try hard to ana­lyze the prob­lem with this machine. The annoy­ing part is, that some­times after a restart apache does not start. So if this hap­pens, the solu­tion is to login and start the web­serv­er. If the web­serv­er would start each time, near­ly nobody would detect the reboot (root gets an EMail on each reboot via an @reboot crontab entry).

My prag­mat­ic solu­tion (for ser­vices start­ed via a good rc.d script which has a work­ing sta­tus com­mand) is a crontab entry which checks peri­od­i­cal­ly if it is run­ning and which restarts the ser­vice if not. As an exam­ple for apache and an inter­val of 10 minutes:

*/10 * * * *    /usr/local/etc/rc.d/apache22 status >/dev/null 2>&1 || /usr/local/etc/rc.d/apache22 restart

For the use case of this service/machine, this is enough. In case of a prob­lem with the ser­vice, a mail with the restart out­put would arrive each time it runs, else only after a reboot for which the ser­vice did not restart.