Beautiful Code [46]
struct vop_vector *vop_default;
int (*vop_open)(struct vop_open_args *);
int (*vop_access)(struct vop_access_args *);
and here is how the ISO-9660 filesystem initializes the structure:
struct vop_vector cd9660_vnodeops = {
.vop_default = &default_vnodeops,
.vop_open = cd9660_open,
.vop_access = cd9660_access,
.vop_bmap = cd9660_bmap,
.vop_cachedlookup = cd9660_lookup,
.vop_getattr = cd9660_getattr,
.vop_inactive = cd9660_inactive,
.vop_ioctl = cd9660_ioctl,]
.vop_lookup = vfs_cache_lookup,
.vop_pathconf = cd9660_pathconf,
.vop_read = cd9660_read,
.vop_readdir = cd9660_readdir,
.vop_readlink = cd9660_readlink,
.vop_reclaim = cd9660_reclaim,
.vop_setattr = cd9660_setattr,
.vop_strategy = cd9660_strategy,
};
(The .field = value syntax is a nifty C99 feature that allows fields of a structure to be initialized in an arbitrary order and in a readable way.) Note that although the complete vop_vector structure contains 52 fields, only 16 are defined in the preceding code. As an example, the vop_write field is left undefined (getting a value of NULL) because writing to files is not supported on ISO-9660 CD-ROMs. Having initialized one such structure for every filesystem type (see the bottom of Figure 17-1), it is then easy to tie this structure to the administrative data associated with each file handle. Then, in the FreeBSD kernel, the filesystem-independent part of the read system call implementation appears simply as (see Figure 17-1):
struct vop_vector *vop;
rc = vop->vop_read(a);
Figure 17-1. Layers of indirection in the FreeBSD implementation of the read system call
So, when reading from a CD containing an ISO-9660 filesystem, the previous call through a pointer would actually result in a call to the function cd9660_read; in effect:
rc = cd9660_read(a);
Python's Dictionary Implementation: Being All Things to All People > Inside the Dictionary
18. Python's Dictionary Implementation: Being All Things to All People
Andrew Kuchling
Dictionaries are a fundamental data type in the python programming language. Like awk's associative arrays and Perl's hashes, dictionaries store a mapping of unique keys to values. Basic operations on a dictionary include:
Adding a new key/value pair
Retrieving the value corresponding to a particular key
Removing existing pairs
Looping over the keys, values, or key/value pairs
Here's a brief example of using a dictionary at the Python interpreter prompt. (To try out this example, you can just run the python command on Mac OS and most Linux distributions. If Python isn't already installed, you can download it from http://www.python.org.)
In the following interactive session, the >>> signs represent the Python interpreter's prompts, and d is the name of the dictionary I'm playing with:
>>> d = {1: 'January', 2: 'February',
... 'jan': 1, 'feb': 2, 'mar': 3}
{'jan': 1, 1: 'January', 2: 'February', 'mar': 3, 'feb': 2}
>>> d['jan'], d[1]
(1, 'January')
>>> d[12]
Traceback (most recent call last):
File " KeyError: 12 >>> del d[2] >>> for k, v in d.items(): print k,v # Looping over all pairs. jan 1 1 January mar 3 >feb 2 ... Two things to note about Python's dictionary type are: A single dictionary can contain keys and values of several different data types. It's legal to store the keys 1, 3+4j (a complex number), and "abc" (a string) in the same dictionary. Values retain their type; they aren't all converted to strings. Keys are not ordered. Methods such as .values() that return the entire contents of a dictionary will return the data in some arbitrary arrangement, not ordered by value or by insertion time. It's important that retrieval of keys be a very fast operation, so dictionary-like types are usually implemented as hash tables. For the C implementation of Python (henceforth referred to as CPython), dictionaries are even more pivotal because they underpin several other language features. For example, classes and