Dr A Sahu Dept of Comp Sc & Engg. IIT Guwahati. Writing/Registering to /proc Character Device Driver – Characteristics and functionality – Basic IO functions.

Slides:



Advertisements
Similar presentations
DEVICE DRIVER VINOD KAMATH CS691X PROJECT WORK. Introduction How to write/install device drivers Systems, Kernel Programming Character, Block and Network.
Advertisements

Linux device-driver issues
Device Drivers. Linux Device Drivers Linux supports three types of hardware device: character, block and network –character devices: R/W without buffering.
RT_FIFO, Device driver.
Sogang University Advanced Operating Systems (Linux Device Drivers) Advanced Operating Systems (Linux Device Drivers) Sang Gue Oh, Ph.D.
Lecture for Lab 3, Exp1 of EE505 (Developing Device Driver) T.A. Chulmin Kim CoreLab. Mar, 11, 2011 [XenSchedulerPaper_Hotcloud-commits] r21 - /
Computer System Laboratory
USERSPACE I/O Reporter: R 張凱富.
R4 Dynamically loading processes. Overview R4 is closely related to R3, much of what you have written for R3 applies to R4 In R3, we executed procedures.
Using VMX within Linux We explore the feasibility of executing ROM-BIOS code within the Linux x86_64 kernel.
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.
Creating a device-file node An introduction to some privileged Linux system-calls (needed for an upcoming programming exercise)
I/o multiplexing On adding a ‘poll()’ method to our character-mode device-driver for an 82573L network controller.
The ‘system-call’ interface We see how an application program can invoke privileged kernel services.
Sleeping and waking An introduction to character-mode device-driver modules for Linux.
UNIX’s “grand illusion” How Linux makes a hardware device appear to be a ‘file’
The ‘system-call’ ID-numbers How can Linux applications written in assembly language create and access files?
04/14/2008CSCI 315 Operating Systems Design1 I/O Systems Notice: The slides for this lecture have been largely based on those accompanying the textbook.
On working with LKMs Using Linux Kernel Modules to quickly export privileged kernel information to ordinary users.
Character Driver Issues Implementing ‘/dev/physmem’
SiS 315 Graphics Engine Introduction to some capabilities of graphics accelerator hardware.
Standard C Libraries Application Programmming Interface to System-Calls.
Embedded Systems Programming Writing Device Drivers.
63 UQC152H3 Advanced OS Writing a Device Driver. 64 The SCULL Device Driver Simple Character Utility for Loading Localities 6 devices types –Scull-03.
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.
Files. System Calls for File System Accessing files –Open, read, write, lseek, close Creating files –Create, mknod.
I/O Hardware n Incredible variety of I/O devices n Common concepts: – Port – connection point to the computer – Bus (daisy chain or shared direct access)
Standard C Library Application Programming Interface to System-Calls.
CS 311 – Lecture 10 Outline Review open() and close() Difference between fopen() and open() File management system calls – read() – write() – lseek() –
The ‘ioctl’ driver-function On implementing a way to query and modify our UART’s baudrate via the ‘device-file’ abstraction.
Looking at kernel objects How a character-mode Linux device driver can be useful in viewing a ‘net_device’ structure.
Chapter 13: I/O Systems I/O Hardware Application I/O Interface
Device Drivers In Linux © Gregory Kesden Fall 2000.
I/O Tanenbaum, ch. 5 p. 329 – 427 Silberschatz, ch. 13 p
M. Muztaba Fuad Advanced Operating System Project Device Drivers.
POSIX: Files Introduction to Operating Systems: Discussion 1 Read Solaris System Interface Guide: Ch. 5.1 Basic File I/O.
Loadable Kernel Modules Dzintars Lepešs The University of Latvia.
Operating System Program 5 I/O System DMA Device Driver.
COMP 3438 – Part I - Lecture 4 Introduction to Device Drivers Dr. Zili Shao Department of Computing The Hong Kong Polytechnic Univ.
File System Review bottomupcs.com J. Kubiatowicz, UC Berkeley.
Operating Systems Recitation 1, March th, 2002.
Kernel Modules. Kernel Module Pieces of code that can be loaded and unloaded into the kernel upon demand. Compiled as an independent program With appropriate.
UNIX Files File organization and a few primitives.
Files & File system. A Possible File System Layout Tanenbaum, Modern Operating Systems 3 e, (c) 2008 Prentice-Hall, Inc. All rights reserved
Linux Device Driver 2009/04/08. Reference Book Another Reference Book Embedded Linux Primer: A Practical, Real-World Approach By Christopher Hallinan.
Chapter 13 – I/O Systems (Pgs ). Devices  Two conflicting properties A. Growing uniformity in interfaces (both h/w and s/w): e.g., USB, TWAIN.
Interfacing Device Drivers with the Kernel
Linux File system Implementations
Laface 2007 File system 2.1 Operating System Design Filesystem system calls buffer allocation algorithms getblk brelse bread breada bwrite iget iput bmap.
Lab 12 Department of Computer Science and Information Engineering National Taiwan University Lab12 – Driver 2014/12/16 1 /21.
COMP 3438 – Part I - Lecture 5 Character Device Drivers
Device Driver Concepts Digital UNIX Internals II Device Driver Concepts Chapter 13.
CSE333 SECTION 3. Important Dates Jan 27 th – Homework 1 Due Feb 6 th – Midterm.
January 7, 2003Serguei Mokhov, 1 File I/O System Calls Reference COMP 229, 444, 5201 Revision 1.2 Date: July 21, 2004.
Copyright ©: Nahrstedt, Angrave, Abdelzaher1 Tarek Abdelzaher Vikram Adve CS241 Systems Programming System Calls and I/O.
File I/O open close lseek read and write – unbuffered I/O dup and dup2.
Silberschatz, Galvin, and Gagne  Applied Operating System Concepts Module 12: I/O Systems I/O hardwared Application I/O Interface Kernel I/O.
I/O Software CS 537 – Introduction to Operating Systems.
OS interface: file and I/O system calls File operations in C/C++? –fopen(), fread(), fwrite(), fclose(), fseek() in C f.open(…), f.close(…) in C++ I/O.
C Programming Day 2. 2 Copyright © 2005, Infosys Technologies Ltd ER/CORP/CRS/LA07/003 Version No. 1.0 Union –mechanism to create user defined data types.
Lecture 3 Module Programming and Device Driver (Homework#1 included) Kyu Ho Park Sept. 15, 2015.
File table: a list of opened files Each entry contains: – Index: file descriptors – Pointer to the file in memory – Access mode File descriptor is a positive.
File System Design David E. Culler CS162 – Operating Systems and Systems Programming Lecture 23 October 22, 2014 Reading: A&D a HW 4 out Proj 2 out.
Lecture 31: Introduction to File System
Linux Kernel Driver.
Unix Directories unix etc home pro dev motd snt unix ... slide1 slide2
CS703 - Advanced Operating Systems
Computer System Laboratory
Loadable Kernel Modules
Unix Directories unix etc home pro dev motd snt unix ... slide1 slide2
Presentation transcript:

Dr A Sahu Dept of Comp Sc & Engg. IIT Guwahati

Writing/Registering to /proc Character Device Driver – Characteristics and functionality – Basic IO functions – Examples (ADC, DAC, Printer, Test data generator) Create 30S Delay SR using CMOS Data – Real Time CMOS Clock – 30S Delay

application standard “runtime” libraries standard “runtime” libraries call ret user spacekernel space Operating System kernel Operating System kernel syscall sysret module Linux allows us to write our own installable kernel modules and add them to a running system call ret

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 module- init and our module-exit routines These special kernel-functions serve to ‘register’, and ‘unregister’, our payload

Your module-initialization function should ‘register’ the module’s ‘get_info()’ function: create_proc_info_entry( modname, 0, NULL, get_info ); Your cleanup should do an ‘unregister’: remove_proc_entry( modname, NULL ); 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 file’s name directory

A device driver is a kernel module responsible for managing low-level I/O operations for a particular hardware device. VFS Block drivers: Physically addressable media (disks) All other devices are considered character devices Line printer, ADC, DAC, …

System Call Interface VFS File System Buffer Cache Buffer Cache Block Device Driver Block Device Driver Character Device Driver Character Device Driver Network Device Driver Network Device Driver Network Protocol Network Protocol Socket Hardware

All drivers are required to implement the loadable module entry points – init () // (load) – finalize () //unload – info () // Gather information of device Drivers should allocate and initialize any global resources in init() and release their resources in finalize().

Device Properties – can’t be randomly accessed – can’t be buffered – usually are slow devices Export Interface – file_operations Data Flow in read/write

init exit fops function... Device-driver LKM layout registers the ‘fops’ unregisters the ‘fops’ module’s ‘payload’ is a collection of callback-functions having prescribed prototypes AND a ‘package’ of function-pointers the usual pair of module-administration functions

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.

FunctionMeanings Lseekto change the current read/write position in a file Readto retrieve data from the device WriteSends data to the devic ReaddirNULL for device files; reading dirs & only useful to FS. Pollback end of two system calls, poll and select, used to inquire a device is readable or writable or in some special state Ioctlto issue device-specific commands Mmapto request a mapping of device mem to a process's address space Openfirst operation performed on the device file Flush.. Lock.. Release.. Fsync.. Fasync..

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.

To appreciate the considerations that have motivated the over-all Linux driver’s design requires an understanding of how normal application-programs get their access to services that the operating system offers This access is indirect – through specially protected interfaces (i.e., system calls) – usually implemented as ‘library’ functions

int open( char *pathname, int flags, … ); int read( int fd, void *buf, size_t count ); int write( int fd, void *buf, size_t count ); int lseek( int fd, loff_t offset, int whence ); int close( int fd ); (and other less-often-used file-I/O functions)

UNIX systems treat hardware-devices as special files, so that familiar functions can be used by application programmers to access devices (e.g., open, read, close) But a System Administrator has to create these device-files (in the ‘/dev’ directory) Or alternatively (as we’ve seen), an LKM could create these necessary device-files # mknod /dev/cmos c 70 0

Breaks link between file and file-descriptor Returns 0 on success, or -1 if an error #include int close( int fd ); #include int close( int fd );

Attempts to write up to ‘count’ bytes Bytes are taken from ‘buf’ memory-buffer Returns the number of bytes written Or returns -1 if some error occurred Return-value 0 means no data was written #include int write( int fd, void *buf, size_t count); #include int write( int fd, void *buf, size_t count);

Attempts to read up to ‘count’ bytes Bytes are placed in ‘buf’ memory-buffer Returns the number of bytes read Or returns -1 if some error occurred Return-value 0 means ‘end-of-file’ #include int read( int fd, void *buf, size_t count ); #include int read( int fd, void *buf, size_t count );

These functions have (as a “side-effect”) the advancement of a file-pointer variable They return a negative function-value of -1 if an error occurs, indicating that no actual data could be transferred; otherwise, they return the number of bytes read or written The ‘read()’ function normally does not return 0, unless ‘end-of-file’ is reached

Modifies the file-pointer variable, based on the value of whence Returns the new value of the file-pointer (or returns -1 if any error occurred) #include off_t lseek(int fd, off_t offset, int whence ); enum { SEEK_SET, SEEK_CUR, SEEK_END }; #include off_t lseek(int fd, off_t offset, int whence ); enum { SEEK_SET, SEEK_CUR, SEEK_END };

For normal files, your application can find out how many bytes belong to a file using the ‘lseek()’ function: int filesize=lseek(fd,0,SEEK_END); But afterward you need to ‘rewind’ the file if you want to read its data: lseek( fd, 0, SEEK_SET );

LKM implements a simple character-mode device-driver For RT Clock's non-volatile memory(128 bytes). It should fully supports read() and lseek() access, Its support restricted access to – write(), only clock-and-calendar locations – The non-configuration data. root# mknod /dev/cmos c 70 0

We implement three callback functions: – llseek:// sets file-pointer’s position – read:// inputs a byte from CMOS – write:// outputs a byte to CMOS We omit other callback functions, such as: – open:// we leave this function-pointer NULL – release:// we leave this function-pointer NULL The kernel has its own ‘default’ implementation for any function with NULL as its pointer-value

init exit fops function... Device-driver LKM layout registers the ‘fops’ unregisters the ‘fops’ module’s ‘payload’ is a collection of callback-functions having prescribed prototypes AND a ‘package’ of function-pointers the usual pair of module-administration functions

The GNU C-compiler supports a syntax for ‘struct’ field-initializations that lets you give your field-values in any convenient order: struct file_operations my_fops = { llseek:my_llseek, write:my_write, read:my_read, }; struct file_operations my_fops = { llseek:my_llseek, write:my_write, read:my_read, };

#include // for printk() #include // for register_chrdev() #include // for put_user(), get_user() #include // for inb(), outb() char modname[] = "cmosram";// name of this kernel module char devname[] = "cmos";// name for the device's file intmy_major = 70;// major ID-number for driver intcmos_size = 128;// total bytes of cmos memory intwrite_max = 9;// largest 'writable' address #include // for printk() #include // for register_chrdev() #include // for put_user(), get_user() #include // for inb(), outb() char modname[] = "cmosram";// name of this kernel module char devname[] = "cmos";// name for the device's file intmy_major = 70;// major ID-number for driver intcmos_size = 128;// total bytes of cmos memory intwrite_max = 9;// largest 'writable' address

ssize_t my_read( struct file *file, char *buf, size_t len, loff_t *pos ) { unsigned char datum; if ( *pos >= cmos_size ) return 0; outb( *pos, 0x70 ); datum = inb( 0x71 ); if ( put_user( datum, buf ) ) return –EFAULT; *pos += 1; return 1; } ssize_t my_write( struct file *file, const char *buf, size_t len, loff_t *pos ) { unsigned chardatum; if ( *pos >= cmos_size ) return 0; if ( *pos > write_max ) return –EPERM; if ( get_user( datum, buf ) ) return –EFAULT; outb( *pos, 0x70 ); outb( datum, 0x71 ); *pos += 1; return 1; } ssize_t my_read( struct file *file, char *buf, size_t len, loff_t *pos ) { unsigned char datum; if ( *pos >= cmos_size ) return 0; outb( *pos, 0x70 ); datum = inb( 0x71 ); if ( put_user( datum, buf ) ) return –EFAULT; *pos += 1; return 1; } ssize_t my_write( struct file *file, const char *buf, size_t len, loff_t *pos ) { unsigned chardatum; if ( *pos >= cmos_size ) return 0; if ( *pos > write_max ) return –EPERM; if ( get_user( datum, buf ) ) return –EFAULT; outb( *pos, 0x70 ); outb( datum, 0x71 ); *pos += 1; return 1; }

loff_t my_llseek( struct file *file, loff_t pos, int whence ) { loff_tnewpos = -1; switch ( whence ) { case 0:newpos = pos; break;// SEEK_SET case 1: newpos = file->f_pos + pos; break;// SEEK_CUR case 2: newpos = cmos_size + pos; break;// SEEK_END } if (( newpos cmos_size )) return –EINVAL; file->f_pos = newpos; returnnewpos; } loff_t my_llseek( struct file *file, loff_t pos, int whence ) { loff_tnewpos = -1; switch ( whence ) { case 0:newpos = pos; break;// SEEK_SET case 1: newpos = file->f_pos + pos; break;// SEEK_CUR case 2: newpos = cmos_size + pos; break;// SEEK_END } if (( newpos cmos_size )) return –EINVAL; file->f_pos = newpos; returnnewpos; }

struct file_operations my_fops = { owner:THIS_MODULE, llseek:my_llseek, write:my_write, read:my_read, }; static int __init my_init( void ) { printk( " \nInstalling \'%s\' module ", devname ); printk( "(major=%d) \n", my_major ); returnregister_chrdev( my_major, devname, &my_fops ); } static void __exit my_exit(void ) { unregister_chrdev( my_major, devname ); printk( " Removing \'%s\' module\n", devname ); } module_init( my_init ); module_exit( my_exit ); MODULE_LICENSE("GPL"); struct file_operations my_fops = { owner:THIS_MODULE, llseek:my_llseek, write:my_write, read:my_read, }; static int __init my_init( void ) { printk( " \nInstalling \'%s\' module ", devname ); printk( "(major=%d) \n", my_major ); returnregister_chrdev( my_major, devname, &my_fops ); } static void __exit my_exit(void ) { unregister_chrdev( my_major, devname ); printk( " Removing \'%s\' module\n", devname ); } module_init( my_init ); module_exit( my_exit ); MODULE_LICENSE("GPL");

#include // for printf(), perror() #include // for open() #include // for read() int main( int argc, char **argv ) { int status = 0; int fd = open( "/dev/cmos", O_RDONLY ); if ( fd < 0 ) { perror( "/dev/cmos" ); return -1; } // Repeatedly reads Status_Reg until its bit has 'flipped‘ 30 times for (int i = 0; i < 30; i++) { do { // do busy-wait until UpdateInProgress is 'true' lseek( fd, 10, SEEK_SET ); read( fd, &status, 1 ); } while ( ( status & 0x80 ) == 0x00 ); do{ // do busy-wait until UpdateInProgress is 'false’ lseek( fd, 10, SEEK_SET ); read( fd, &status, 1 ); } while ( ( status & 0x80 ) == 0x80 ); printf( " %d Second Elapsed\n", i+1 ); } #include // for printf(), perror() #include // for open() #include // for read() int main( int argc, char **argv ) { int status = 0; int fd = open( "/dev/cmos", O_RDONLY ); if ( fd < 0 ) { perror( "/dev/cmos" ); return -1; } // Repeatedly reads Status_Reg until its bit has 'flipped‘ 30 times for (int i = 0; i < 30; i++) { do { // do busy-wait until UpdateInProgress is 'true' lseek( fd, 10, SEEK_SET ); read( fd, &status, 1 ); } while ( ( status & 0x80 ) == 0x00 ); do{ // do busy-wait until UpdateInProgress is 'false’ lseek( fd, 10, SEEK_SET ); read( fd, &status, 1 ); } while ( ( status & 0x80 ) == 0x80 ); printf( " %d Second Elapsed\n", i+1 ); }

Download mmake.cpp and cmosram.c Course Website, tested on Fedora 12 Compile mmake.cpp using ‘g++’ Then compile cmosram.c using ‘make’ Install ‘cmos.ko’ (and see printk-message) See $cat /proc/cmos Compile ThirtySec.cpp and execute..