Dr A Sahu Dept of Comp Sc & Engg. IIT Guwahati • • • • Kernel Module Writing/Registering to /proc FS Payload of kernel module Reading CMOS Data – Real.

Download Report

Transcript Dr A Sahu Dept of Comp Sc & Engg. IIT Guwahati • • • • Kernel Module Writing/Registering to /proc FS Payload of kernel module Reading CMOS Data – Real.

Dr A Sahu
Dept of Comp Sc & Engg.
IIT Guwahati
•
•
•
•
Kernel Module
Writing/Registering to /proc FS
Payload of kernel module
Reading CMOS Data
– Real Time CMOS Clock
• Type of devices and drivers
– Character
– Block
– Network/Stream
•
•
•
•
Kernel and Device driver
Device Driver Types
CMOS
Reading CMOS Clock and printing at /proc
Linux allows us to write our own
installable kernel modules
and add them to a running system
application
module
call
call
ret
standard
“runtime”
libraries
user space
syscall
ret
Operating System
kernel
sysret
kernel space
#include <linux/module.h> // for printk()
int init( void ){
printk( "\n
Kello, everybody! \n\n" );
return 0;
}
void exit( void ){
printk( "\n
Goodbye now... \n\n" );
}
MODULE_LICENSE("GPL");
module_init(init);
module_exit(exit);
• We can write code to implement our own
‘pseudo’ files, located in ‘/proc’ directory
• We do this by adding a ‘payload’ function to a
Linux Kernel Module, and by including calls to
special kernel-functions within our moduleinit and our module-exit routines
• These special kernel-functions serve to
‘register’, and ‘unregister’, our payload
• When an application-program (like ‘mycat’)
tries to read our pseudo-file, the kernel will
call our ‘get_info()’ function, passing it four
function arguments -- and will expect it to
return an integer value:
int get_info( char *buf, char **start,
off_t off, int count );
pointer to a kernel buffer
pointer (optional) to module’ own buffer
current file-pointer offset
size of space available in the kernel’s buffer
function should return the number of bytes it has written into its buffer
• The kernel provides a function you module
can call to print formatted text into a buffer
• It resembles a standard C library-function:
int sprintf( char *dstn,
<arguments> );
pointer to destination
const char *fmt,
formatting specification string
list of the argument-values to format
will return the number of characters that were printed to the destination-buffer
Example:
int len = sprintf( buf, “count = %d \n”, count );
• Your module-initialization function should
‘register’ the module’s ‘get_info()’ function:
create_proc_info_entry( modname, 0, NULL, get_info );
the name for your proc file
the file-access attributes (0=default)
directory where file will reside (NULL=default)
function-pointer to your module’s ‘callback’ routine
• Your cleanup should do an ‘unregister’:
remove_proc_entry( modname, NULL );
file’s name
directory
#include <linux/module.h>
#include <linux/proc_fs.h>
create_proc_info_entry()
#include <asm/io.h>
// for init_module()
// for
// for inb(), outb()
char modname[] = "cmos";
unsigned char cmos[10];
char *day[] = { "", "MON", "TUE", "WED", "THU",
"FRI", "SAT", "SUN" };
char *month[] = { "", "JAN", "FEB", "MAR", "APR",
"MAY", "JUN",
"JUL", "AUG", "SEP", "OCT",
"NOV", "DEC" };
0x0
Current seconds
Range is 0..59
0x1
Alarm seconds
Range is 0..59
0x2
Current minutes
Range is 0..59
0x3
Alarm minutes
Range is 0..59
0x4
Current hours
Range is 0..23 or 1..12
0x5
Alarm hours
Range is 0..23 or 1..12
0x6
0x7
0x8
0x9
Day-of-the-Week
Date of the Month
Current Month
Current Year
Range is 1..7 (Sunday=7)
Range is 1..31
Range is 1..12 (January=1)
Range is 0..99
int my_get_info( char *buf, char **start, off_t off,
int count ) {
…….
// show the current time and date
len += sprintf( buf+len, "CMOS Real-Time Clock:\
%02X:%02X:%02X on ", mos[4], cmos[2],cmos[0]);
// cur h,m,s
len += sprintf( buf+len, " %s, ", day[ cmos[6] ] );
// day-name
len += sprintf( buf+len, "%02X", cmos[7] );
// day-number
// convert 'cmos[ 8 ]' from BCD-format to
integer-format
month_index = ((cmos[ 8 ] & 0xF0)>>4)*10 +
(cmos[ 8 ] & 0x0F);
len += sprintf( buf+len, " %s", month[
month_index ] ); // month-name
int my_get_info( char *buf, char **start,
off_t off, int count ) {
int
i, len = 0;
int
month_index;
// input and store the first ten CMOS entries
for (i = 0; i < 10; i++) {
outb( i, 0x70 );
cmos[i] = inb( 0x71 );
Here’s }“C” code to read the N-th location:
{
…………………..
int
datum;
// storage for a CMOS dataoutb( N, 0x70 ); // select cell number N for acces
datum = inb( 0x71 );
// input value from selecte
}
static int __init my_init( void ){
printk( "<1>\nInstalling \'%s\' module\n",
modname );
create_proc_read_entry( modname, 0, NULL,
my_get_info, NULL );
return 0; //SUCCESS
}
static void __exit my_exit(void ) {
remove_proc_entry( modname, NULL );
printk( "<1>Removing \'%s\' module\n",
modname );
}
module_init( my_init );
module_exit( my_exit );
MODULE_LICENSE("GPL");
• A device driver is a kernel module responsible
for managing low-level I/O operations for a
particular hardware device.
• Block device drivers manage devices with
physically addressable storage media, such as
disks.
• All other devices are considered character
devices
• VFS (Virtual File System)
• Driver Types
– Basic:
• Character (ADC, Line printer)
• Block (SCSI DISK)
• Network
– Special
• Stream
• Terminal
System Call Interface
VFS
Socket
File System
Network
Protocol
Buffer
Cache
Block
Character
Device Driver Device Driver
Hardware
Network
Device Driver
• Operation Modes
– polling
– interrupt
– DMA
• All drivers are required to implement the
loadable module entry points
– init ()
– finialise ()
– info ()
// (load)
//unload
// Gather information of device
• Drivers should allocate and initialize any global
resources in init() and release their resources
in finilise().
• Device Properties
– can’t be randomly accessed
– can’t be buffered
– usually are slow devices
• Export Interface
– file_operations
• Data Flow in read/write
• Character device drivers normally perform I/O
in a byte stream.
• Examples of devices using character drivers
include tape drives and serial ports.
• Character device drivers can also provide
additional interfaces not present in block
drivers,
– I/O control (ioctl) commands
– memory mapping
– device polling.
Function
Meanings
Lseek
to change the current read/write position in a file
Read
to retrieve data from the device
Write
Sends data to the devic
Readdir
NULL for device files; reading dirs & only useful to FS.
Poll
back end of two system calls, poll and select, used to inquire a
device is readable or writable or in some special state
Ioctl
to issue device-specific commands
Mmap
to request a mapping of device mem to a process's address space
Open
first operation performed on the device file
Flush
..
Lock
..
Release
..
Fsync
..
Fasync
..
• Block Devices that support a file system are
known as block devices.
• Drivers written for these devices are known as
block device drivers.
• Block device drivers take a file system request, in
the form of a buffer structure,
– And issue the I/O operations to the disk to transfer
the specified block.
• The main interface to the file system is the
strategy routine
• Device Properties
– can be randomly accessed
– accessed in units of blocks
– to speed up access, buffer cache is used
• Export Interface
– file_operations
– request_fn()
• Data Flow in read/write
Processes
Read/Write System Call
Buffer
Cache
Invoke Request Function
Check buffer upto date
Done
Call
Scheduler
• Drivers for character and block devices export
a cb_ops structure
• which defines the driver entry points for block
device access and character device access.
• Both types of drivers are required to support
open and close.
• Block drivers are required to support strategy,
while character drivers can choose to
implement whatever mix of
– read, write, ioctl, mmap, or devmap
– These entry points as appropriate for the type of
device.
• Character drivers can also support a polling
interface through
– ch_poll
– as well as asynchronous I/O through aread and
awrite.
• STREAMS is a separate programming model
for writing a character driver.
• Devices that receive data asynchronously
(such as terminal and network devices) are
suited to a STREAMS implementation.
• STREAMS device drivers must provide the
loading and autoconfiguration support
• Drivers are required to implement these Entry
points for device autoconfiguration.
– Attach
– Detach,
– Getinfo
• Drivers might need to implement probe if the
driver supports devices that are not self
identifying, such as SCSI target devices
• Export Interface
• Data Flow in read/write
User Application
Berkley Socket API
INET Socket
TCP
UDP
IP
ARP
ICMP
Network Device Driver
Transmit Data:
Xmit
Network Device
Receive Data
Int. Handler
• I/O ports reservations
– request_region()
• Memory Allocations
– kmalloc(), vmalloc(), get_free_page()
• Interrupt Handler Registration
– request_irq()
• Data Transfer between User/Kernel
– memcpy_fromfs()
•
•
•
•
•
•
Download mmake.cpp and cmos.c
Course Website, tested on Fedora 12
Compile mmake.cpp using ‘make’
Then compile cmos.c using ‘make’
Install ‘cmos.ko’ (and see printk-message)
See $cat /proc/cmos