How to make a pseudo-file
As a follow-up to our first lab, we
examine the steps needed to
create our own /proc file
The extensibility imperative
A modern OS needs the ability to evolve
It will need to support new devices
It will need to allow bugs to be repaired
It will need to permit performance gains
Otherwise: suffer early obsolescence!
Two Extensibility Mechanisms
Open Source programming
Installable kernel modules
Open Source
Source text for the Linux kernel is on disk
(usual directory-location is /usr/src/linux)
Majority of the sources are written in C
(so portable across CPU architectures)
Some are written in assembly languages
(for nearly twenty different architectures)
Files are grouped into major categories
(kernel, mm, fs, net, ipc, lib, drivers, init)
You could edit and recompile your kernel
Installable kernel modules
Great mechanism for kernel extensibility
Neat tool for studying how kernel works
Kernel can be modified while its running
Unnecessary to recompile and then reboot
But inherently unsafe: programming bugs
in the kernel can cause system crashes!
Some superuser privileges
Since modifying a running kernel is risky,
only authorized system administrators
are normally allowed to install kernel
modules
But our systems are specially configured
to permit you to install or remove modules
This is purely for educational purposes
(so you should use this privilege wisely)
Linux module structure
Two module administration functions are
mandatory components in every module
plus
Appropriate module service functions and
their supporting kernel data-structures are
optional components in particular modules
also
Recent kernels require a Module License!
A minimal module-template
#include <linux/module.h>
int init_module( void )
{
// code here gets called during module installation
}
void cleanup_module( void )
{
// code here gets called during module removal
}
MODULE_LICENSE(GPL);
How to compile a module
You could directly invoke the C-compiler:
$ gcc c O D__KERNEL__ -DMODULE
I/lib/modules/2.4.26/build/include mod.c
OR: you can use the make utility:
$ make mod.o
The printk() function
Kernel modules cannot call any functions
in the C runtime library (e.g., printf())
But similar kernel versions of important
functions are provided (e.g., printk())
Syntax and semantics are slightly different
(e.g., priority and message-destination)
Capabilities may be somewhat restricted
(e.g., printk() cant show floating-point)
Simple module example
#include <linux/module.h>
int init_module( void )
{
printk( <1>Hello, world!\n );
return 0;
// SUCCESS
}
void cleanup_module( void )
{
printk( <1>Goodbye everyone\n );
}
MODULE_LICENSE(GPL);
How to install and remove
root#/sbin/insmodhello.o
root#/sbin/rmmodhello
A non-trivial module-example
Lets see how we can use kernel functions
to create our own /proc file
Easy if we use create_proc_read_entry()
during module-initialization (and then use
remove_proc_entry() during cleanup)
Prototypes in the <linux/proc_fs.h> header
Well show the current value of a volatile
kernel variable, named jiffies
jiffies
unsigned long volatile jiffies;
global kernel variable (used by scheduler)
Initialized to zero when system reboots
Gets incremented when timer interrupts
So it counts clock-ticks since cpu restart
tick-frequency is architecture dependent
Writing the jiffies.c module
We need to declare a name for pseudo-file
static char modname[ ] = jiffies;
We need to define a proc_read function
(see code on the following slide)
We need to register our filename, along
with its read method, in init_module()
We need to unregister our pseudo-file in
cleanup_module()
Our modules read method
static int
my_proc_read( char *buf, char **start,
off_t off, int count, int *eof, void *data )
{
return sprintf( buf, jiffies=%lu\n, jiffies );
}
Our initialization function
int init_module( void )
{
create_proc_read_entry( modname,
0, NULL, my_proc_read, NULL );
return 0;
}
Our cleanup function
void cleanup_module( void )
{
remove_proc_entry( modname, NULL );
}
In-class exercise #1
Use an editor (e.g., vi) to create a source
file in C (named jiffies.c) for your module
Use the make command to compile your
modules source-file into an object-file
Use the insmod command to install your
module object-file into the running kernel
Use the cat command to display jiffies
Then use rmmod to remove your module
Makefile
We need it to automate module compiles
Otherwise we type a VERY long command
To compile jiffies.c type: $ make jiffies.o
Our Makefile defines some implicit rules
make works by doing pattern-matching
Rule syntax
targets:dependencies
commands
...
Pattern Rule example
CC=gcc
INCLUDE=
/lib/modules/2.4.26/build/include
CFLAGS=cO
CFLAGS+=D__KERNEL__DMODULE
#primarypatternrule
%.o:%.c%.h
$(CC)I$(INCLUDE)$CFLAGS$<
#fallbackpatternrule
%.o:%.c
$(CC)I$(INCLUDE)$CFLAGS$<
Makefile is on class website
You can download the Makefile from our
website: http://cs.usfca.edu/~cruse/cs326/
Put the Makefile in your current working
directory (along with your module source)
Then you can compile by typing this short
command: $ make jiffies.o
In-class exercise #2
Use your knowledge of standard C library
functions (e.g., open(), read(), close() ) to
write an application-program (name it
showjifs.cpp) which reads the information
from your proc/jiffies pseudo-file and then
prints it on the screen
Use a program-loop to re-read the pseudo
file multiple times
How rapidly does jiffies value increase?