UNIX’s “grand illusion” How Linux makes a hardware device appear to be a ‘file’

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.
Computer System Laboratory
Using our device-drivers How can an application display the data in a device special file?
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.
Module R2 CS450. Next Week R1 is due next Friday ▫Bring manuals in a binder - make sure to have a cover page with group number, module, and date. You.
The Linux Kernel: Memory Management
Memory management.
Using VMX within Linux We explore the feasibility of executing ROM-BIOS code within the Linux x86_64 kernel.
I/O Multiplexing The role of the ‘poll()’ method in Linux device-driver operations.
Creating a device-file node An introduction to some privileged Linux system-calls (needed for an upcoming programming exercise)
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.
The Linux PCI Interface An introduction to the PCI configuration space registers.
IA32 Paging Scheme Introduction to the Pentium’s support for “virtual” memory.
The ‘system-call’ ID-numbers How can Linux applications written in assembly language create and access files?
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.
The ‘ioctl’ driver-function On implementing ‘show’ and ‘hide’ for the SiS 315 hardware cursor.
Standard C Library Application Programming Interface to System-Calls.
Home: Phones OFF Please Unix Kernel Parminder Singh Kang Home:
CS 311 – Lecture 10 Outline Review open() and close() Difference between fopen() and open() File management system calls – read() – write() – lseek() –
Managing physical memory
The ‘ioctl’ driver-function On implementing a way to query and modify our UART’s baudrate via the ‘device-file’ abstraction.
Adjusting out device-driver Here we complete the job of modifying our ‘nicf.c’ Linux driver to support ‘raw’ packet-transfers.
Looking at kernel objects How a character-mode Linux device driver can be useful in viewing a ‘net_device’ structure.
A device-driver for Video Memory Introduction to basic principles of the PC’s graphics display.
The ‘mmap()’ method Adding the ‘mmap()’ capability to our ‘vram.c’ device-driver.
Dr A Sahu Dept of Comp Sc & Engg. IIT Guwahati. Writing/Registering to /proc Character Device Driver – Characteristics and functionality – Basic IO functions.
7/13/20151 Topic 3: Run-Time Environment Memory Model Activation Record Call Convention Storage Allocation Runtime Stack and Heap Garbage Collection.
Silberschatz, Galvin and Gagne ©2009 Operating System Concepts – 8 th Edition Chapter 2: Operating-System Structures Modified from the text book.
Buffer Overflow Attacks. Memory plays a key part in many computer system functions. It’s a critical component to many internal operations. From mother.
File System. NET+OS 6 File System Architecture Design Goals File System Layer Design Storage Services Layer Design RAM Services Layer Design Flash Services.
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.
System Calls 1.
1 Further C  Multiple source code file projects  Structs  The preprocessor  Pointers.
MAC OS – Unit A Page: 10-11, Investigating Data Processing Understanding Memory.
Operating Systems Recitation 1, March th, 2002.
Computer Science and Software Engineering University of Wisconsin - Platteville 2. Pointer Yan Shi CS/SE2630 Lecture Notes.
Topic 2d High-Level languages and Systems Software
UNIX Files File organization and a few primitives.
© Janice Regan, CMPT 300, May CMPT 300 Introduction to Operating Systems Memory: Relocation.
Files & File system. A Possible File System Layout Tanenbaum, Modern Operating Systems 3 e, (c) 2008 Prentice-Hall, Inc. All rights reserved
Project 6 Unix File System. Administrative No Design Review – A design document instead 2-3 pages max No collaboration with peers – Piazza is for clarifications.
CE Operating Systems Lecture 17 File systems – interface and implementation.
Operating Systems 1 K. Salah Module 1.2: Fundamental Concepts Interrupts System Calls.
1 Computer Systems II Introduction to Processes. 2 First Two Major Computer System Evolution Steps Led to the idea of multiprogramming (multiple concurrent.
Interfacing Device Drivers with the Kernel
CSCI 330 UNIX and Network Programming Unit VII: I/O Management I.
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
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.
Week 4 - Friday.  What did we talk about last time?  Some extra systems programming stuff  Scope.
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.
Memory Management Chapter 5 Advanced Operating System.
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.
Using System Calls (Unix) Have to tell compiler (if C/C++) where to find the headers, etc. – i.e., the “include” files May have to tell compiler where.
DYNAMIC MEMORY ALLOCATION. Disadvantages of ARRAYS MEMORY ALLOCATION OF ARRAY IS STATIC: Less resource utilization. For example: If the maximum elements.
Operation System Program 4
Memory Allocation CS 217.
Memory Management Tasks
Loadable Kernel Modules
Presentation transcript:

UNIX’s “grand illusion” How Linux makes a hardware device appear to be a ‘file’

Basic char-driver components 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

Background 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

Standard File-I/O 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)

Our ‘elfcheck.cpp’ example #include # for open() #include # for perror(), printf() #include # for read(), close() #include # for strncpy() charbuf[4]; int main( int argc, char *argv[] ) { if ( argc == 1 ) return -1;// command-line argument is required intfd = open( argv[1], O_RDONLY );// open specified file if ( fd < 0 ) { perror( argv[1] ); return -1;// quit if open failed intnbytes = read( fd, buf, 4 );// read first 4 bytes if ( nbytes < 0 ) { perror( argv[1] ); return -1;// quit if read failed if ( strncmp( buf, “\177ELF”, 4 ) == 0 )// check for ELF id printf( “File \’%s\’ has ELF signature \n”, argv[1] ); elseprintf( “File \’%s\’ is not an ELF file \n”, argv[1] ); close( fd );// close the file }

Special ‘device’ files 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

UNIX ‘man’ pages A convenient online guide to prototypes and semantics of the C library functions Example of usage: $ man 2 open

The ‘open’ function #include int open( char *pathname, int flags, … ); Converts a pathname to a file-descriptor File-descriptor is a nonnegative integer Used as a file-ID in subsequent functions ‘flags’ is a symbolic constant: O_RDONLY, O_WRONLY, O_RDWR

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

The ‘write’ function #include int write( int fd, void *buf, size_t count ); 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

The ‘read’ function #include int read( 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’

Notes on ‘read()’ and ‘write()’ 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

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

Getting the size of a file 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 );

Device knowledge Before you can write a device-driver, you must understand how the hardware works Usually this means you need to obtain the programmer manual (from manufacturer) Nowdays this can often be an obstacle But some equipment is standardized, or is well understood (because of its simplicity)

Our RTC example We previously learned how the Real-Time Clock device can be accessed by module code, using the ‘inb()’ and ‘outb()’ macros: So we can create a simple char driver that lets application-programs treat the RTC’s memory as if it were in an ordinary file outb( addr, 0x70 ); outb( data, 0x71 ); outb( addr, 0x70 ); data = inb( 0x71 );

How device-access works Physical peripheral device (hardware) Device-driver module (software) Operating system (software) Application program Standard runtime library supervisor space (privileged) user space (unprivileged) call ret int $0x80 iret int $0x80 iret call ret out in

Our ‘cmosram.c’ driver 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

The ‘fops’ syntax 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, };

‘init’ and ‘exit’ The module’s initialization function has to take care of registering the driver’s ‘fops’: register_chrdev( major, devname, &fops ); Then the module’s cleanup function must make sure to unregister the driver’s ‘fops’: unregister_chrdev( major, devname ); (These are prototyped in )

Our ‘dump.cpp’ utility We have written an application that lets users display the contents of any file in both hexadecimal and ascii formats It also works on ‘device’ files! With our driver-module installed, you can use it to view the CMOS memory-values: $./dump /dev/cmos

Now for a useful char-driver… We can create a character-mode driver for the processor’s physical memory (i.e. ram) (Our machines have 2-GB of physical ram) But another device-file is named ‘/dev/ram’ so ours will be: ‘/dev/dram’ (dynamic ram) We’ve picked 85 as its ‘major’ ID-number Our SysAdmin setup a device-node using: root# mknod /dev/dram c 85 0

2-GB RAM has ‘zones’ ZONE_NORMAL ZONE_HIGH ZONE_LOW MB 16-MB 2048-MB (= 2GB) 896-MB Installed physical memory

Legacy DMA Various older devices rely on the PC/AT’s DMA controller to perform data-transfers This chip could only use 24-bit addresses Only the lowest 16-megabytes of physical memory are ‘visible’ to these devices: 2 24 = 0x (16-megabytes) Linux tries to conserve its use of memory from this ZONE_LOW region (so devices will find free DMA memory if it’s needed)

‘Normal’ memory zone This zone extends from 16MB to 896MB Linux uses the lower portion of this zone for an important data-structure that tracks how all the physical memory is being used It’s an array of records: mem_map[] (We will soon be studying this structure) The remainder of ZONE_NORMAL is free for ‘dynamic’ allocations by the OS kernel

‘HIGH’ memory Linux traditionally tried to ‘map’ as much physical memory as possible into virtual addresses allocated to the kernel-space Before the days when systems had 1-GB or more of installed memory, Linux could linearly map ALL of the physical memory into the 1-GB ‘virtual’ kernel-region: 0xC – 0xFFFFFFFF But with 2-GB there’s not enough room!

always mapped The 896-MB limit Virtual address-space HIGH MEMORY application program’s code and data goes here HIGH ADDRESSES 896-MB User space (3-GB) Kernel space (1-GB) Physical address-space Installed ram (2-GB) A special pair of kernel-functions named ‘kmap()’ and ‘kunmap()’ can be called by device-drivers to temporarily map ‘vacant’ areas in the kernel’s ‘high’ address-space to pages of actual physical memory temporary mappings using kmap()

‘dram.c’ module-structure We will need three kernel header-files: –#include // for printk(), register_chrdev(), unregister_chrdev() –#include // for kmap(), kunmap(), and ‘num_physpages’ –#include // for copy_to_user()

Our ‘dram_size’ global Our ‘init_module()’ function will compute the size of the installed physical memory It will be stored in a global variable, so it can be accessed by our driver ‘methods’ It is computed from a kernel global using the PAGE_SIZE constant (=4096 for x86) dram_size = num_physpages * PAGE_SIZE

‘major’ ID-number Our ‘major’ device ID-number is needed when we ‘register’ our device-driver with the kernel (during initialization) and later when we ‘unregister’ our device-driver (during the cleanup procedure): int my_major = 85; // static ID-assignment

Our ‘file_operations’ Our ‘dram’ device-driver does not need to implement special ‘methods’ for doing the ‘open()’, ‘write()’, or ‘release()’ operations (the kernel ‘default’ operations will suffice) But we DO need to implement ‘read()’ and ‘llseek()’ methods Our ‘llseek()’ code here is very standard But ‘read()’ is specially crafted for DRAM

Using our driver We have provided a development tool on the class website (named ‘fileview.cpp’) which can be used to display the contents of arbitrary files -- including device-files! The data is shown in hex and ascii formats The arrow-keys can be used for navigation The enter-key allows an offset to be typed Keys ‘b’, ‘w’, ‘d’ and ‘q’ adjust data-widths

In-class exercise #1 Install the ‘dram.ko’ device-driver module; then use ‘fileview’ to browse the contents of the processor’s physical memory: $./fileview /dev/dram Be sure to try the ‘b’, ‘w’, ‘d’, ‘q’, and keys Also try:$./fileview /dev/cmos

In-class exercise #2 The read() and write() callback functions in our ‘cmosram.c’ device-driver only transfer a single byte of data for each time called, so it takes 128 system-calls to read all of the RTC storage-locations! Can you improve this driver’s efficiency, by modifying its read() and write() functions, so they’ll transfer as many valid bytes as the supplied buffer’s space could hold?