Cover | Table of Contents | Colophon
ftpd provides the file transfer mechanism, while
users can use whatever client they prefer; both command-line and
graphic clients exist, and anyone can write a new user interface to
transfer files.
#define MODULE
#include <linux/module.h>
int init_module(void) { printk("<1>Hello, world\n"); return 0; }
void cleanup_module(void) { printk("<1>Goodbye cruel world\n"); }
<1> is the
priority of the message. I've specified a high priority in this
module because a message with the default priority might not show on the
console if you use version 2.0.x of the kernel and an old klogd
daemon (you can ignore this issue for now; we'll explain it in the section
Section 4.1.1, in Chapter 4).
root# gcc -c hello.c root# insmod hello.o Hello, world root# rmmod hello Goodbye cruel world root#
__KERNEL__ symbol in the
preprocessor before we include any headers. This symbol is used to
select which parts of the headers are actually used. Applications
end up including kernel headers because libc includes
them, but
the applications don't need all the kernel prototypes. Therefore,
__KERNEL__ is used to mask the extra ones out via #ifdef.
Exporting kernel symbols and macros to user-space programs would
greatly contribute to program namespace pollution. If you are compiling
for an SMP (Symmetric Multi-Processor) machine, you also need
to define __SMP__ before including the kernel headers. This
requirement may seem unfriendly, but is going to disappear as
soon as the developers find the right way to be SMP-transparent.MODULE, which must be defined
before including <linux/module.h>. This symbol is always
defined, except when compiling drivers that are directly linked to the
kernel image. Since none of the drivers covered in this book
are directly linked to the kernel, they all define the symbol.inline
in the header files. gcc doesn't expand
inlines unless optimization is enabled, but it can accept both
the -g and -O options, allowing you to debug code that
uses inline functions.
GFP_KERNEL will
do. The GFP acronym stands for ``Get Free Page.''
int skull_ival=0; char *skull_sval;
insmod skull skull_ival=666 skull_sval="the beast"
__KERNEL__
MODULE
int init_module(void);
void cleanup_module(void);
#include <linux/module.h>
MOD_INC_USE_COUNT;
MOD_DEC_USE_COUNT;
MOD_IN_USE
int register_symtab(struct symbol_table *);
scull0-3
scull0-3
scullpipe0-3
scullpipe will show how blocking and nonblocking read
and write
can be implemented; this happens
without having to resort to interrupts.
Although real drivers synchronize with their
devices using hardware interrupts, the topic of blocking and
nonblocking operations is an important one and is conceptually
detached from interrupt handling (covered in Chapter 9).crw-rw-rw- 1 root root 10, 3 Nov 30 1993 bmouseatixl crw-rw-rw- 1 root sys 1, 3 Nov 30 1993 null crw-rw-rw- 1 root root 4, 128 Apr 30 13:02 ptyp0 crw-rw-rw- 1 root root 4, 129 Apr 30 13:02 ptyp1 crw-rw-rw- 1 rubini staff 4, 0 Jan 30 1995 tty0 crw-rw-rw- 1 root tty 4, 64 Jan 25 1995 ttyS0 crw-rw-rw- 1 root root 4, 65 May 1 00:04 ttyS1 crw-rw-rw- 1 root sys 1, 5 Nov 30 1993 zero
file structure, and the kernel
uses the file_operations structure
to access the driver's functions. This design is the first evidence
we've seen of the object-oriented design of the Linux kernel. We'll
see more evidence of object-oriented design later. The
structure file_operations is a table of function pointers,
defined in <linux/fs.h>. The structure struct file is
going to be described next.fops pointer, which we've already seen as an argument
to the register_chrdev call, points to a table of operations
(open, read, and so on). Each entry in the table points
to the function defined by the driver to handle the requested
operation. The table can contain NULL pointers for the operations
you don't support. The exact behavior of the kernel when a NULL
pointer is specified is different for each function, as the list in
the next section shows.file_operations structure has been slowly getting bigger as
new functionality is added to the kernel (although no new fields were
added between 1.2.0 and 2.0.x). There should be no side effects
from this increase, because the C compiler takes care of any size mismatch
by zero-filling uninitialized fields in global or static
struct variables.
New items are added at the end of the structure,
so a NULL value inserted at compile time will
select the default behavior (remember that the module needs to be
recompiled in any case for each new kernel version it will be loaded into).fops fields,
actually changed slightly during 2.1 development. These differences
are covered in Section 17.2, in Chapter 17.
struct file, defined in <linux/fs.h>, is the
second most important data structure used in device drivers. Note
that a file has nothing to do with the FILEs of
user-space programs. A FILE is defined in the C library and never
appears in kernel code. A struct file, on the other hand, is a kernel
structure that never appears in user programs.file structure represents an ``open file.'' It is
created by the kernel on open and is passed to any function
that operates on the file, until close. After the file is
closed, the kernel releases the data structure. An ``open file'' is
different from a ``disk file,'' which is represented by struct
inode.struct file is usually
called either file or filp (``file
pointer''). I'll consistently
call the pointer filp to prevent ambiguities with the structure
itself--filp is a pointer (as such, it is one of the arguments to device
methods), while file is the structure itself.struct file are shown below.
As in the previous section, the list can be skipped on a first
reading. In the next section though, when we face some real C code,
I'll discuss some of the fields, so they are here for you to
refer back to.mode_t f_mode;
FMODE_READ and FMODE_WRITE. You might want to
check this field for read/write permission in your ioctl
function, but you don't need to check permissions for
read and write because the kernel checks
before invoking your driver. An attempt to write without
permission, for example, is rejected without the driver
even knowing about it.loff_t f_pos;
f_op pointer, if necessary.filp->private_data.inode->i_rdev.Scull_Dev. Each such structure can
refer to at most four million bytes, through an array of
intermediate pointers. The released source uses an array of
1000 pointers to areas of 4000 bytes. I call each memory area
a ``quantum'' and the array (or its length) a ``quantum set.'' A
<asm/segment.h>.
The functions devoted to performing such a copy are
optimized for different data sizes (char, short, int, long);
most of them will be introduced in
Section 5.1.4 in Chapter 5.void memcpy_fromfs(void *to, const void *from, unsigned long count); void memcpy_tofs(void *to, const void *from, unsigned long count);
struct file_operations and
struct file is not repeated here.#include <linux/fs.h>