|
Approaching BeAn introduction to programming for the BeOSAs the Be Operating System (BeOS ) has emerged onto the computing landscape, thousands of software developers have been attracted to its feature set, simplicity and performance. This interest has been amplified by the introduction of versions of the BeOS that can run on mainstream PowerPC systems, such as PowerMacintosh and its clones. As interest has risen, one of the questions we get most often from programmers is, "Where do I start?" Programming for the BeOS is similar in many ways to programming for other operating systems, at least those that can be considered "modern." But there are fundamental differences in the design and goals which can affect how you might structure your application. Programmers want to understand those fundamental design goals and the philosophy of the OS design before they start to write code. This white paper is designed to answer this set of basic questions. It is written with the programmer in mind, though some non-programmers may find it useful as well. It is also written to be useful from the perspective of the programmer coming to the BeOS from a MacOS or Windows environment. Many of the topics will be discussed in a way that compares the BeOS approach with those used by these other systems. The content is broken into three sections. The first will discuss the underlying fundamental design and philosophy of the BeOS and how they might impact the design of your software. The second section will discuss the general architecture of the BeOS and identify the key components a programmer deals with. In the third section, we'll walk through the creation of a basic, simple application. There are a number of other white papers and primers available that build on this document. These can be found in the Developer section of the Be web site at http://www.be.com. [Note: Source code for this tutorial can be found at ftp://ftp.be.com/pub/samples/preview/intro/HelloWorld.zip]
Fundamental ConceptsIn creating the BeOS, the Be engineering team has used a set of fundamental assumptions and concepts as guides. These concepts are so ingrained in the OS that they can have important impacts on how you might architect your own applications. If you are approaching the BeOS from the MacOS space, or even the Windows space, it's also important to understand where the BeOS differs; many of the differences lie in these fundamental concepts. One common joke around the Be offices is that "BeOS" actually stands for "buzzword enabled operating system." Without a doubt, the BeOS meets and exceeds the market expectations of what a "modern" operating system should look like. Five of these buzzword concepts are important to understand because they impact the design of software written for the BeOS; object-orientation, preemptive multitasking, protected memory, symmetric multiprocessing and extensive multithreading.
Object-OrientationProbably the most significant difference between the BeOS and current mainstream operating systems is that the BeOS is an object-oriented operating system. This means that its application programming interface (API) is composed of objects, rather than the procedure calls you might find in the MacOS or Windows. When you create an application for the BeOS, you will create a derivative of the basic BApplication object, and you will use either the standard objects built into the BeOS such as BWindow and BButton, or derivatives of these objects. Object-oriented programming has been around for awhile, but it is only recently that software development has utilized its basic concepts. The BeOS is one of the few operating systems to base itself entirely upon the object-oriented concept. When looking at the BeBook, the reference book that describes the entire BeOS API, you won't find a set of procedures. What you will find is an entire application framework, with objects that can be linked together to create an application, create its windows and interface, manage network connections, and manipulate most of the data objects you'll create within your application. These objects contain a large amount of functionality built-in; you won't need to start from scratch nor connect separate procedures into complex chains. A lot of the basic work is already done for you. And further, you'll be able to use objects created by other BeOS programmers from within your application as well. But what this means is that within in the BeOS, you'll need to program in an object-oriented language. The BeOS API is based on C++. Java, a close cousin of C++, will also be supported in the future. Be chose these languages because they are based on industry standards and have the support of a wide range of vendors. If you understand object-oriented concepts, and have used C++, you'll have no problems jumping into the BeOS. If you have programmed on the MacOS, and have used an application framework such as Metrowerk's PowerPlant or Apple's MacApp, you are even in a better position because the BeOS API will look very familiar to you. Likewise, if you have used Microsoft Foundation Classes for Windows, you will recognize many of the concepts found in the BeOS. If you don't know C++ or Java, but would like to learn about object-oriented programming, the BeOS is a great place to start because it is a new, relatively uncluttered operating system that is built on object-oriented concepts. So you won't have to deal with a lot of exceptions and work-arounds in the API that you might find in other systems.
Preemptive Multitasking
Most programmers are familiar with multitasking - the ability to run more than one
application at a time and have the operating system worry about splitting CPU time
between them. Preemptive
multitasking goes a step further, and it's important to understand the difference,
especially if you are coming from the MacOS. Several operating systems, including
the MacOS, use a system known as cooperative multitasking, which means that each
application must voluntarily give up time so that other applications can continue running.
In the MacOS, this system is represented by the
Preemptive multitasking eliminates the need for something like Of course, what this also means is that you, as a programmer, must always remember that your application can be interrupted at any time. Usually, you don't need to do anything differently under this system. But if you are accessing a shared resource, it's possible that other processes sharing that resource will jump in (or out) during your "suspended" state, and that may affect you. Remember, unlike cooperative multitasking, you won't necessarily be guaranteed to finish a sequence of instructions before the OS switches your code out. There are ways of telling the OS how important certain tasks are (such as real-time audio or video, etc.) and there are ways of locking resources if needed. We'll talk more about that in a bit.
Protected MemoryOne of the key complaints users have about personal computer systems is how often applications crash, and in doing so lock up their entire machine. The reason for this is that the failed application has usually attempted to alter physical memory owned by another application, or by the operating system itself. These changes quickly ripple through the system and cause both the application and entire machine to crash. To prevent this, the BeOS uses a scheme known as protected memory. What this means is that the memory owned by one process cannot be accessed by any other process. When an application starts up under the BeOS, it is told that it has the entire logical address space (currently 32-bits or 4 gb of memory) all to itself. Applications under the BeOS use pointers or other direct references to memory. If you are coming from Windows, this is pretty much old hat, but the MacOS often uses indirect memory "handles" to allow for memory management. Of course, most real computers don't have 4 gb of memory installed. The BeOS therefore keeps a close watch on each application's real memory use. It breaks down the entire 4 gb memory space into "pages" and then keeps track of how many pages are used, and how often each page is accessed. If more physical memory is needed by another process, the BeOS will temporarily unload several least-used pages onto disk to make room, and will reload those pages when needed again. This is the real meaning behind "virtual memory." Within the BeOS (as well as within Unix, Windows NT and other modern operating systems) virtual memory is always on. Protected memory goes a long way towards keeping a system stable. If you are writing applications, servers or many other pieces of code, you'll have difficulty bringing the system down. Another one of the reasons for this is that the BeOS is built upon a "client-server" architecture where system resources such as the screen or networking hardware are controlled by a "server" which multiple "clients" talk to in order to gain access. All applications lie on the client side of this architecture. This provides a further level of protection by minimizing resource collisions. If you are one of the developers creating code that lies on the server side of the architecture, such as hardware drivers, you'll need to make sure your code is simple, fast and bullet-proof. The BeBook provides further advice for building this type of software.
Symmetric MultiprocessingAnother key limitation of most mainstream operating systems today is an assumption that there is only one microprocessor per system. Although some systems, like the MacOS, can make limited use of a second processor, most OSes were not designed with multiprocessing in mind. The BeOS was designed as a multiprocessor OS from the beginning. The initial systems it was created on all used two microprocessors, and the BeOS now runs on systems containing one to four processors. The BeOS itself is not limited -- it can support "n" processors in theory -- although realistically there are significant limitations today in mainstream hardware implementations once you pass about eight processors. Further, the implementation of multiprocessing in the BeOS is "symmetric." As a programmer, you do not have to worry about which processor your application uses at any particular point in time. In designing a BeOS application, you do nothing differently in order to run on single processor systems and eight processor systems (although you may want to take the number of processors into account in a few calculation-intensive cases for optimization purposes) Your application may start on one processor, move to another processor, and move back many times during execution. All of this is transparent to your code. But one thing that symmetric multiprocessing implies is that you can create applications that do many (many, many) things in parallel. And in order to do this, there is one last BeOS concept that you need to keep in mind...
Extensive MultithreadingIn traditional operating systems, each application can be thought of as a single "thread" of execution, from the top of the code to the eventual end. If you have multiple applications open, there are multiple threads of execution happening at once, and they share the processor(s) time. In the BeOS, threading goes much further. In order to take maximum advantage of multiple processors, each application should be broken down into multiple threads of execution. If an application has a single thread, then it must execute on only one processor at a time (although that processor may change during execution.) But if an application has multiple threads, then that application can make use of multiple processors in parallel. This can vastly improve the execution time of code. In testing various execution models, we've found out that breaking an application into multiple threads can make overall execution and task switching faster and smoother, even on single processor systems. It turns out that extensive threading aids and amplifies the affect of preemptive multitasking.
Knowing this, the BeOS itself is heavily threaded. Even at a complete standstill,
the BeOS makes use of dozens of threads. Every server in the system spawns threads
constantly. Further, it is virtually impossible to write an application that is
not threaded. In creating a Other than the object-oriented nature of the BeOS, multithreading has perhaps the most significant impact on software design. Luckily, object-orientation and threading go hand-in-hand. If you are coming to the BeOS from either the MacOS or Windows, there are two things involving threading to keep in mind;
System ArchitectureNow that we've described the basic concepts underlying the BeOS, we can outline the architecture of the system in a more concrete fashion. The block diagram below provides an overview of the components of the BeOS; The BeOS can be divided into three main groups of components; the Kernel, the BeOS Servers, and the BeOS Kits.
The Kernel A sampling of the core BeOS software kits found in the BeBook include;
Application Kit The servers and kits work closely together, and in most cases the kits are simply the interface through which applications make requests of the servers. For example, if during a draw method you draw a line into a window;
In this case, you've created a Thus the objects in the BeOS kits correspond to a BeOS server. Here are some of the kits and the corresponding servers they communicate with;
Now that we've built a foundation of BeOS concepts, the best way to understand how they fit together is to write an application. To do this, we'll look at a BeOS implementation of a simple application, HelloWorld. The discussion in the next session assumes that you understand the basics of C++.
HelloWorld ApplicationHelloWorld will do a few simple things. At startup, it will create a window. Within that window it will write the words "Hello, World!". Closing the window will cause the application to quit. What we'll find in creating this application is that most of the work is already done for us in the basic BeOS objects. We're going to define each object with a header file and an implementation file. With such a simple application, we could take shortcuts and place the code in fewer files, even one, but the purpose here is to write HelloWorld in a way similar to how you'd write a full-blown application. First off, we need to create the application object. The interface to this object is simple and straightforward;
// ----------------------------------------------------------------------- // HelloWorldApp.h // ----------------------------------------------------------------------- #pragma once #include <Application.h> class HelloWorldApp : public BApplication { public: HelloWorldApp(); };
The
The next line includes the BeOS
The
There is only one new method defined in this simple example, a constructor for the
class,
// ----------------------------------------------------------------------- // HelloWorldApp.cpp // ----------------------------------------------------------------------- #include "HelloWorldApp.h" // other includes go here main() { HelloWorldApp myApplication; myApplication.Run(); return (0); } HelloWorldApp::HelloWorldApp() : BApplication(application/x-vnd.Be-HelloWorldSample") { // Set up windows and stuff }
For clarity, we've left out the window creation code. We'll get to that in a
minute. As with any C and C++ application, a
The only other routine in the implementation is the The window we need to create is actually made up of two objects. There is the window itself, and within the window there will be a view that draws the "Hello, World!" text. We'll start at the bottom of this ladder, and define the view first.
// ----------------------------------------------------------------------- // HelloView.h // ----------------------------------------------------------------------- #pragma once #include <StringView.h> class HelloView : public BStringView { public: HelloView(BRect frame, const char* name, const char* text); }; // ----------------------------------------------------------------------- // HelloView.cpp // ----------------------------------------------------------------------- #include "HelloView.h" HelloView::HelloView(BRect frame, const char* name, const char *text) : BView(frame, name, text, B_FOLLOW_ALL, B_WILL_DRAW) { SetFont(be_bold_font); SetFontSize(24); }
In the header,
In the implementation, we provide an empty constructor whose purpose is to pass along
arguments to the Now that we have the view defined, we can define the window. // ----------------------------------------------------------------------- // HelloWindow.h // ----------------------------------------------------------------------- #pragma once #include <Window.h> class HelloWindow : public BWindow { public: HelloWindow(BRect frame); virtual bool QuitRequested(); //Override }; // ----------------------------------------------------------------------- // HelloWindow.cpp // ----------------------------------------------------------------------- #include "HelloWindow.h" #include "HelloView.h" HelloWindow::HelloWindow(BRect frame) :BWindow(frame, "Hello", B_TITLED_WINDOW, B_NOT_RESIZABLE | B_NOT_ZOOMABLE) { BRect viewRect = Bounds(); HelloView* theView = new HelloView(viewRect, "HelloView", "HelloWorld!"); AddChild(theView); Show(); } HelloWindow::QuitRequested() { be_app->PostMessage(B_QUIT_REQUESTED); return true; }
The
In the constructor, we pass the arguments to the inherited
Within the constructor itself, we create a
Within the BeOS, each
In our case, we want to do one more thing. If the user closes the window, we also want the HelloWorld application to quit.
So, we override Now that we have defined the window and view, we can complete the application implementation;
// ----------------------------------------------------------------------- // HelloWorldApp.cpp // ----------------------------------------------------------------------- #include "HelloWorldApp.h" #include "HelloWindow.h" main() { HelloWorldApp myApplication; myApplication.Run(); return (0); } HelloWorldApp::HelloWorldApp() : BApplication("application/x-vnd.Be-HelloWorldSample") { BRect frameRect; frameRect.Set(100,100,280,140); HelloWindow* theWindow = new HelloWindow(frameRect); }
We've added an Once complete, our CodeWarrior project should look something like the window below.
We can then make the project (Project menu/make.) Make sure that within CodeWarrior
you've set the project preferences to name the application "HelloWorld", otherwise
the name of the application will be "Application". Another exercise that might be
useful is to take HelloWorld and modify it so that a "Quit" button appears in the window
as well, which would close the window and quit the application. This would simply
take the This paper has provided an introductory overview of programming in the BeOS. For further information and sample code, take a look at the tutorials section of the Developer area on the Be web site (http://www.be.com) You may also want to take a look at the BeBook, the API of the BeOS, to get a more thorough overview of the BeOS Kits and other objects. [Webmaster's Note: This tutorial was written by Mark Gonzales, our former VP of Marketing. No kidding.]
|