|Issue 50, 14 Dec 2003
Well, I could say what I said back in August about trying to get newsletter editions out more often, but instead I'll just say this: When the OBOS developers are quiet, you know it's because they're working through the tough parts. Now give it up for our newsletter writers, who, despite the busiest of schedules, have cranked out something for you to enjoy!
The system logging capabilities in BeOS are built on top of the syslog
interface as defined by the POSIX standard. In addition to the functionality
provided by that standard, it has some BeOS specific extensions.
The following article will give an overview about how this service works
internally in OpenBeOS, and how it can be used in applications. The implementation
as done in OpenBeOS might differ from the actual implementation in BeOS, but it
is fully binary compatible.
The syslog service is provided by a standard
BApplication that runs as a server in
the background, the syslog_daemon.
After it has been started during the system's boot process, it will just sit
there and wait for messages. Every call to syslog() or log_thread/team() will
pass a message to the server containing information about what should be
written to the log and with what options. The message is not a
a plain data structure that can be created without any knowledge about
That is needed, because the service is used by the kernel as well.
The server then just passes on that message to its internal handlers. It has
two built-in handlers. One of them just processes the message and dumps a formatted
text to the syslog file at /var/log/syslog. The other one creates
BMessage out of the message and broadcasts it to all of its listeners.
However, how you can communicate with the syslog_daemon to get those messages will
be the topic of another newsletter article.
If the syslog file reaches a certain size (512 kB), it will be renamed to syslog.old,
and a new syslog file is created.
Using the system logger
As already mentioned, the system logging capabilities are accessible via the standard
POSIX functions. Therefore, the syslog.h header is placed in the headers/posix
directory, and the functions are implemented in libroot.so. That's already
different from standard BeOS where you need to link against libbe.so to access
that functionality. The syslog.h header can be found in the headers/be/support
directory on a standard BeOS system.
The implementation and header have been moved to simplify porting of POSIX-compliant
applications; however, that neither breaks binary nor source compatibility (as long as you
haven't used "
#include <support/syslog.h>" for your native Be apps.)
The first call of a function that will connect to the syslog service will create a
syslog session. It's important to know that there is one session for each thread
that uses the service, as well as one extra session for all team-wide logging
The original POSIX API as well as part of the additional BeOS API
both use thread specific sessions. When a session is started, it will inherit the options
defined for the team session. That means you can set logging options that every
thread in your application will respect (if you don't overwrite them locally).
But in order to define team wide options, you have to specifically use the BeOS-specific
void openlog_team(const char *ident, int logopt, int facility)
Sets the team logging options for the other team functions and for
- ident is the identification string that prepends every message from your team.
- logopt allows you to set several logging options (see below).
- facility determines from what facility your message has been sent; for your
standard issues, this should just be LOG_USER.
Closes the current session. This has currently no effect for the team logging functions.
void log_team(int priority, const char *message, ...)
Sends a message of the specified priority to the syslog daemon.
int setlogmask_team(int priorityMask)
Use the LOG_MASK() macro to build a mask of priorities to show. All
messages of other priorities will be discarded. Example uses:
||// all messages of priority LOG_WARNING will be shown|
setlogmask_team(LOG_MASK(LOG_ERR + 1) - 1);
||// all messages with a priority level higher than LOG_ERR will be shown|
The POSIX API and the thread specific Be API behave exactly in the same way;
*_thread() functions just clobber the global namespace :).
All calls except for the
closelog() calls will start a new session
if there is none yet, and will inherit the current team logging options if they do.
void openlog_thread(const char *ident, int logopt, int facility)
void openlog(const char *ident, int logopt, int facility)
Sets the log options for the current thread.
Closes the thread session, and frees all associated data. The next
call to the syslog service will start a new session, and will inherit
the team log options at that point again.
void log_thread(int priority, const char *message, ...)
syslog(int priority, const char *message, ...)
Sends a message of the specified priority to the syslog daemon.
int setlogmask_thread(int priorityMask)
Use the LOG_MASK() macro to build a mask of priorities to show. All
messages of other priorities will be discarded.
Logging options for openlog()
These are the options that can be passed to openlog()/openlog_thread()/openlog_team().
Note, its effects might be depending on the syslog listener; for example, for a GUI
syslog viewer, LOG_PID might have no effect at all.
There are some more flags defined, but they have currently no effect (notably,
LOG_ODELAY, LOG_NDELAY, LOG_NOWAIT and LOG_SERIAL).
log the process (thread/team) ID with each message
if the message cannot be delivered to the syslog daemon, it will be
directly dumped to stderr.
the message will not only be sent to the syslog daemon, it will also
be written to the application's stderr, not only if sending fails like
Playing with the OpenBeOS implementation
The server is implemented in current/src/servers/syslog_daemon, naturally,
you have to build and start it, before it'll work - although you can also check
out the syslog functionality without a living server.
To test the syslog functionality, you can use the provided test program. You'll
find it in current/src/tests/kernel/libroot/posix/SyslogTest.cpp. Edit
it as you please, and you'll get a good idea of how it works.
Differences between the OpenBeOS and the BeOS implementations
As already written some paragraphs above, the implemenation has been moved from
libbe.so to libroot.so. But since all applications are linked against
libroot.so anyway, this won't have any impact on binary compatibility.
The header file syslog.h has been moved to the headers/posix directory,
where all other POSIX headers reside. If you've previously used the full path of
the old header ("
#include <support/syslog.h>"), you might encounter
errors when trying to compile your old code. The issue has not been finally decided on,
but it probably won't change in the release version of our headers.
It has not been tested if the thread logging functions inherit their settings from
the team session on R5 or not, and if this mechanism works similarly if it's in place.
The only other known difference is that our syslog_daemon implements a way to broadcast
the messages to a listener application. But as I already said earlier, this will be the
topic of another newsletter article. Also note that the actual implementation of that
protocol has not been finalized yet and is probably subject to change; your shiny system
logger viewer might need to be updated before we reach R1.
There is a brief introduction to the BeOS system logger at
You can also find a description of the standard POSIX syslog functions at
When developing an operating system, there is a big amount of secondary
tools and test applications involved. Sometimes, you will find surprisingly
useful things in this "cruft".
I want to introduce you to one of these gems today, the virtualdrive driver.
You can find it in current/src/tests/kits/storage/virtualdrive in our
repository. It has been developed mainly by Marcus Overhagen and Ingo Weinhold.
I only made some minor changes to make it more useful and dangerous for developing
the boot loader code.
It's probably only useful for some of you, and therefore we haven't yet put the
work into it and published it separately from our project. Also, it won't be
needed in OpenBeOS anymore, anyway.
So, what does it good for me?
The driver only does one little thing: it allows device-like access to a file.
The main reason it has been developed was to test our partition scanner. You
can use complete hard drive images with that driver.
If you are using Bochs (there are several entries in BeBits, the most recent one
of them is (currently) http://www.bebits.com/app/3324)
to run other operating systems (or OpenBeOS), you will notice that it is not able
to access your devices directly, but needs every hard disk as a file.
With this driver and its accompanied mkvirtualdrive application, you can
make the partitions on these files directly accessible to BeOS, and just mount
To install the driver to your local hard drive, you have to build it like this:
$ jam install_virtualdrive
$ rescan virtualdrive
To build the mkvirtualdrive tool, just type
jam and then
move the executable (somewhere below the distro-tree; jam will print
out its exact location) to a place where you find it again, most probably you
want to put it somewhere in your path, too, so /boot/home/config/bin is
most appropriate for it.
For your convenience, I built a package that contains the driver and its controlling
from our server.
How can I use it?
To avoid unwanted interactions with Tracker and other BeOS applications, the
driver publishes its devices under /dev/misc/virtualdrive/. That makes
its usage a bit more complicated than you'd want for the general end-user application.
Anyway, here is a step-by-step description of how to get it to work:
$ mkvirtualdrive --install myHD.image
This will print out the device under which you can now access the file. Note, the
file is no longer accessible directly. If you are issuing the above command for
the first time, you will probably get "/dev/misc/virtualdrive/0" back.
The file is now accessible through the device, but the BeOS disk system still
doesn't take notice. If you want to mount the partitions on that image, or even
want to create new partitions on that image, format it with another file system
or whatever, you need to "connect" it to the system; you need to make a new "raw"
entry somewhere below /dev/disk/. I choose the /dev/disk/virtual/files
directory for that.
$ mkdir -p /dev/disk/virtual/files/0
$ ln -s /dev/misc/virtualdrive/0 /dev/disk/virtual/files/0/raw
Now, DriveSetup will suddenly notice the new "disk," and the shell command
mountvolume will work on it as well. Unfortunately, Tracker will ignore the
new disk in its mount menu, but it will show the partition's contents once you've
mounted them; partitions on that disk will have a blue cabinet icon in Tracker (if
they don't have their own icon).
If you have a volume called "BeOS" on a partition on that disk, you can mount it
$ mountvolume BeOS
You can use the "-l" option to print out all mountable partitions; the partitions
on the new disk are visible there as well.
That's nice, right? But as mentioned already, the file cannot be accessed anymore--the
driver locks the file for exclusive access. If you want to use the file in Bochs
again (or have a look at its contents with DiskProbe when you are developing a new
partitioning system add-on), you need to unregister the file with the driver again.
Normally, you would just use
$ mkvirtualvolume --uninstall /dev/misc/virtualdrive/0
to achieve that. But unfortunately, once you've introduced the device to the BeOS
disk system (by making the symlink and using mountvolume or DriveSetup on it),
it won't close the device anymore, and therefore, the driver won't let other people
access the file.
Note that you must unmount all mounted partitions from that file before you are
doing the next step! You can tell the virtualdrive driver to close the file for
some time and reestablish the connection later on. All accesses through the device
will fail, so you should not use DriveSetup or mountvolume during that
$ mkvirtualvolume --halt /dev/misc/virtualdrive/0
The driver will close the file internally and allows others to access the file again.
If you want to activate the device again (i.e. to mount it again), you just need to
install it again like you did before:
$ mkvirtualdrive --install myHD.image
If nobody has closed the device in between and you haven't used the driver for other
files in between, the file will be accessible through the device again. In order to
let it work, you have to provide the exact same image with the exact same path to
the "--install" call.
If you have forgotten which device points to what file, and which ones have been
disabled and which haven't, you can use the following option of mkvirtualdrive
to get that info:
$ mkvirtualdrive --info /dev/misc/virtualdrive/0
Before you are using this driver in the way explained here, especially when you are
using the features described under "Advanced features", you should make sure that you
won't lose any important data on a sudden death.
We take no responsibility or liability on the effects of this software to your system.
However, if you are careful and respect the warnings and directions given in this
document, no case of failure or data loss is known to us. In any case, you've been
My first conception of BeOS was probably a little different than that of most
of you. When I first learned about BeOS, the BeBox had just premiered. I
learned about BeOS from the BeBook on-line. This harkens back to the Old Days
of computer science, when you wrote your program on paper, tested it by hand
(desk checking) until you were sure that it was right, then submitted it to
the computer for a batch job. Because I was not in a rush to find the
object/method that I needed, I could instead focus on just enjoying the
beauty of the design. It was a very pleasant experience.
While I still like the API very much, it is not what most people see when
they use an operating system. Most people's perspectives on an operating
system come from a very few components--installation, booting, the
"desktop", and the applications. I believe that the philosophy that Be had
for each piece of the operating system was something that they called "the
Right Way." I call it TUE--Total User Experience. Why the change in
nomenclature? I believe that it is very easy for engineers, sometimes, to
forget who our "real" customers are.
I suppose, then, that I should define who our "customers" are. There are many
people who would like a piece of our efforts. I have heard from people who
want to make OBOS the next server OS. Other people have said that it should
be a great embedded OS. Yet others think that a platform for massive
scientific computing makes sense. My consistent answer is that we should be
the "Desktop OS." Some argue that we should stick with one of the last
focuses of Be, Inc. and be the "Media OS." I am not opposed to being the
"Media OS"; in fact, I believe that the two go hand in hand. Media, meaning
video and sound, is inherent in the desktop. Ever since the multimedia hype of
the mid-1990's when x86 users found themselves capable of handling CD-quality sound
and TV-quality graphics. Who would run a desktop OS that doesn't play movies?
Or one where they couldn't play MP3's (like I am right now)? No one. Media is a
subset of desktop. Desktop is, of course, different from server, embedded (to
some degree), and other platforms.
With our "customers" thus defined let's take a "TUE", then look at each of
the most visible parts of BeOS and talk a bit about what was done right and
Jean-Louis Gassee once said that Be looked at the price/performance curve and
chose the "sweet spot". This was in regard, if I remember correctly, to
choosing dual PPC 603s for the BeBox. What does it mean? There is frequently
a trade off between two aspects of an engineering decision; usually if you
plot them on a graph, it is exponential--the graph transitions from
incremental increases in price providing massive performance to massive
increases in price providing incremental performance. Processors still do this
today. I believe that this particular philosophy is very much the embodiment
of TUE. With nearly every place you can point out something bad about an operating
system, it will be because a poor point on the graph is chosen. Windows takes
forever to install and boot? Look and see how many devices are supported. If
we support 1/10 of the devices, we can boot 25X faster, or something on that
order. Choosing the right devices is the tricky part. That is the mastery of
TUE--that it works exceptionally well for 90% of users and can be made to
work with little effort for the other 10%. It is possible to build a system
that works faster/better (think custom kernel builds with all hardware
support compiled in) or one the supports more users (think Windows), but the
sweet spot is somewhere in between.
TUE is about making the user's experience so great that they beg for more,
not mercy. TUE is about building something that you are proud of and proud to
be associated with, not something that has to hide behind press releases and
excuses. TUE is about choosing what to do, then doing it the way that is the
best trade off you can make. TUE is about cautious experimentation. Never just
dump radical changes on the consumer without massive in-house and beta
testing. Look at the trouble that Apple has had with users adopting OS X
(and, for that matter, Microsoft with WinXP). On the contrary, Microsoft is
not making a peep over the "leaked" screenshots from Longhorn. They have
hundreds of real life criticisms years before it ships.
The BeOS install is nearly optimal, as far as I can see. You can choose which
partition you want and click Begin. That is the some total of the information
that it needs to decide to install. No time zones, nothing else. The "More
Options", which allows you to set up disk partitions is likewise very well
done. There are a few changes that could be made in the partition tool,
though. Specifically, it doesn't tell you the hard disk name. You only find
out the BeOS /dev path (marginally useful) and the total disk size. I know
that the BIOS, at the very least, knows more than that. If the BIOS can know
the disk manufacturer, we should be able to find it. Secondly, a minor nit,
the grid control doesn't have resizable columns. Finally, obviously unusable
choices (floppy and CD-ROM) are listed. Still, all in all, this is the best
installer that I have ever seen.
Booting is another excellent experience within BeOS. The speed is still
legendary and unmatched. Speed, while a component of TUE, is not the most
important part. The boot loader is graphically helpful, showing what hardware
that it has finished initializing, where in the boot process it is and giving
you useful feedback instead of just a progress bar. Additionally, you can hit
space bar and get all sorts of options for booting. Finally, and probably
best of all, the system matches all of your hardware every time at runtime.
That means that if you pull a HD out to boot somewhere else, it will *just
work* assuming that you have drivers.
Tracker, in many ways, is not much different than other desktop environments.
The power of attributes and their flexible use is well-documented elsewhere.
Replicants are different than the system tray that Windows offers. But,
really, Tracker is very much like "everyone else"--there are icons on the
desktop, folders can open, etc. Deskbar is not drastically better than the Start
Menu from Windows. The desktop is an area where I have seen many complaints
about the paradigm but few realistic choices.
Finally, we have applications. BeOS offers many standard controls and a
standard look. This is somewhat different from the *NIXes. Windows and MacOS
have a definite edge here in terms of numbers and types of controls. I would
like to address this in the future (R2 or beyond), as I believe that some of
these would be very useful to OBOS application designers.
BeOS, while not perfect, works very hard to do the things that it does "the
Right Way". That is the tradition that we hope to carry on.