When the selection of the routine to assign to a function pointer is based on a
particular piece of data, such as the protocol handling the data or the device driver a
given packet is received from, it is easier to derive the routine. For example, if a
given device is managed by the drivers/net/3c59x.c device driver, you can derive the
routine to which a given function pointer of the net_device data structure is
initialized by reading the device initialization routine provided by the device driver.
•
When the selection of the routine is based instead on more complex logic, such as
the state of the resolution of an L3-to-L2 address mapping, the routine used at any
time depends on external events that cannot be predicted.
•
A set of function pointers grouped into a data structure are often referred to as a virtual
function table (VFT). When a VFT is used as the interface between two major subsystems,
such as the L3 and L4 protocol layers, or when the VFT is simply exported as an interface to
a generic kernel component (set of objects), the number of function pointers in it may swell
to include many different pointers that accommodate a wide range of protocols or other
features. Each feature may end up using only a few of the many functions provided. You will
see an example in Part VI. Of course, if this use of a VFT is taken too far, it becomes
cumbersome and a major redesign is needed.
1.2.6. goto Statements
Few C programmers like the goto statement. Without getting into the history of the goto
(one of the longest and most famous controversies in computer programming), I'll
summarize some of the reasons the goto is usually deprecated, but why the Linux kernel
uses it anyway.
Any piece of code that uses goto can be rewritten without it. The use of goto statements
can reduce the readability of the code, and make debugging harder, because at any position
following a goto you can no longer derive unequivocally the conditions that led the
execution to that point.
Let me make this analogy: given any node in a tree, you know what the path from the root to
the node is. But if you add vines that entwine around branches randomly, you do not always
have a unique path between the root and the other nodes anymore.
However, because the C language does not provide explicit exceptions (and they are often
avoided in other languages as well because of the performance hit and coding complexity),
carefully placed goto statements can make it easier to jump to code that handles undesired
or peculiar events. In kernel programming, and particularly in networking, such events are
very common, so goto becomes a convenient tool.
I must defend the kernel's use of goto by pointing out that developers have by no means
gone wild with it. Even though there are more than 30,000 instances, they are mainly used to
handle different return codes within a function, or to jump out of more than one level of
nesting.
1.2.7. Vector Definitions
In some cases, the definition of a data structure includes an optional block at the end. This is
an example:
8 Part I: General Background
8 Part I: General Background