How to make a pseudo-file examine the steps needed to

Download Report

Transcript How to make a pseudo-file examine the steps needed to

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 it’s 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() can’t 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/insmod hello.o
root# /sbin/rmmod hello
A non-trivial module-example
• Let’s 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
• We’ll 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 module’s ‘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
module’s 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 = -c –O
CFLAGS += -D__KERNEL__ -DMODULE
# primary pattern rule
%.o : %.c %.h
$(CC) -I$(INCLUDE) $CFLAGS $<
# fallback pattern rule
%.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?