The Kernel Kit Table of Contents | The Kernel Kit Index |
An area is a chunk of virtual memory. As such, it has all the expected properties of virtual memory: It has a starting address, a size, the addresses it comprises are contiguous, and it maps to (possibly non-contiguous) physical memory. The features that an area provides that you don't get with "standard" memory are these:
Because areas are large—one page, minimum—you don't create them arbitrarily. The two most compelling reasons to create an area are the two first points listed above: To share data among different applications, and to lock memory into RAM.
In all particulars (but one) you treat the memory that an area gives you exactly as you would treat any allocated memory: You can read and write it through pointer manipulation, or through standard functions such as memcpy() and strcpy(). The one difference is between areas and malloc'd memory is...
Each area that you create is tagged with an area_id number:
Areas can also be (loosely) identified by name:
For multiple applications to share a common area, one of the applications has to create the area, and the other applications clone the area. You clone an area by calling clone_area(). The function takes, as its last argument, the area_id of the source area and returns a new (unique) area_id number. All further references to the cloned area (in the cloning application) must be based on the area_id that's returned by clone_area().
So how does a cloner find a source area_id in the first place?
Keep in mind that area names are not forced to be unique, so the find_area() method has some amount of uncertainty. But this can be minimized through clever name creation.
The physical memory that lies beneath an area is never implicitly copied—for example, the area mechanism doesn't perform a "copy-on-write." If two areas refer to the same memory because of cloning, a data modification that's affected through one area will be seen by the other area.
When you're working with moderately large amounts of data, it's often the case that you would prefer that the data remain in RAM, even if the rest of your application needs to be swapped out. An argument to create_area() lets you declare, through the use of one of the following constants, the locking scheme that you wish to apply to your area:
Constant | Meaning |
---|---|
B_FULL_LOCK | The area's memory is locked into RAM when the area is created, and won't be swapped out. |
B_CONTIGUOUS | Not only is the area's memory locked into RAM, it's also guaranteed to be contiguous. This is particularly—and perhaps exclusively—useful to designers of certain types of device drivers. |
B_LAZY_LOCK | Allows individual pages of memory to be brought into RAM through the natural order of things and then locks them. |
B_NO_LOCK | Pages are never locked, they're swapped in and out as needed. |
B_LOMEM | This is a special constant that's used for for areas that need to be locked, contiguous, and that fit within the first 16MB of physical memory. The folks that need this constant know who they are. |
Keep in mind that locking an area essentially reduces the amount of RAM that can be used by other applications, and so increases the likelihood of swapping. So you shouldn't lock simply because you're greedy. But if the area that you're locking is going to be shared among some number of other applications, or if you're writing a real-time application that processes large chunks of data, then locking can be a justifiable excess.
The locking scheme is set by the create_area() function and is thereafter immutable. You can't re-declare the lock when you clone an area.
Ultimately, you use an area for the virtual memory that it represents: You create an area because you want some memory to which you can write and from which you can read data. These acts are performed in the usual manner, through references to specific addresses. Setting a pointer to a location within the area, and checking that you haven't exceeded the area's memory bounds as you increment the pointer (while reading or writing) are your own responsibility. To do this properly, you need to know the area's starting address and its extent:
An important point, with regard to area_info, is that the address field is only valid for the application that created or cloned the area (in other words, the application that created the area_id that was passed to get_area_info()). Although the memory that underlies an area is global, the address that you get from an area_info structure refers to a specific address space.
If there's any question about whether a particular area_id is "local" or "foreign," you can compare the area_info.team field to your thread's team.
When your application quits, the areas (the area_id numbers) that it created through create_area() or clone_area() are automatically rendered invalid. The memory underlying these areas, however, isn't necessarily freed. An area's memory is freed only when (and as soon as) there are no more areas that refer to it.
You can force the invalidation of an area_id by passing it to the delete_area() function. Again, the underlying memory is only freed if yours is the last area to refer to the memory.
Deleting an area, whether explicitly through delete_area(), or because your application quit, never affects the status of other areas that were cloned from it.
The Kernel Kit Table of Contents | The Kernel Kit Index |
Copyright © 2000 Be, Inc. All rights reserved..