The device driver (DD) implements these user functions, which translate system calls into device-specific operations that act on real hardware

Similar documents
Character Device Drivers

Linux Device Drivers

Introduction Reading Writing scull. Linux Device Drivers - char driver

Kernel Modules. Kartik Gopalan

Abstraction via the OS. Device Drivers. Software Layers. Device Drivers. Types of Devices. Mechanism vs. Policy. Jonathan Misurda

Device Drivers. CS449 Fall 2017

Software Layers. Device Drivers 4/15/2013. User

CS5460/6460: Operating Systems. Lecture 24: Device drivers. Anton Burtsev April, 2014

Concurrency and Race Conditions (Linux Device Drivers, 3rd Edition (

REVISION HISTORY NUMBER DATE DESCRIPTION NAME

Linux Kernel Modules & Device Drivers April 9, 2012

Linux Device Drivers. 3. Char Drivers. 1. Introduction 2. Kernel Modules 3. Char Drivers 4. Advanced Char Drivers 5. Interrupts

Designing and developing device drivers. Coding drivers

Linux Kernel Module Programming. Tushar B. Kute,

Unix (Linux) Device Drivers

/dev/hello_world: A Simple Introduction to Device Drivers under Linux

Linux Device Drivers. 3. Char Drivers cont. 3. Char Drivers. 1. Introduction 2. Kernel Modules 3. Char Drivers 4. Advanced Char Drivers 5.

Loadable Kernel Module

Virtual File System (VFS) Implementation in Linux. Tushar B. Kute,

CS 423 Operating System Design: Introduction to Linux Kernel Programming (MP1 Q&A)

Linux drivers - Exercise

Scrivere device driver su Linux. Better Embedded 2012 Andrea Righi

Workspace for '5-linux' Page 1 (row 1, column 1)

Finish up OS topics Group plans

Character Device Drivers One Module - Multiple Devices

MP3: VIRTUAL MEMORY PAGE FAULT MEASUREMENT

Device Drivers Demystified ESC 117. Doug Abbott, Principal Consultant Intellimetrix. Why device drivers? What s a device driver?

Introduction to Operating Systems. Device Drivers. John Franco. Dept. of Electrical Engineering and Computing Systems University of Cincinnati

ECEN 449: Microprocessor System Design Department of Electrical and Computer Engineering Texas A&M University

ASE++ : Linux Kernel Programming

CS 453: Operating Systems Programming Project 5 (100 points) Linux Device Driver

Section 3: File I/O, JSON, Generics. Meghan Cowan

7.4 Simple example of Linux drivers

Linux Device Driver. Analog/Digital Signal Interfacing

What is a Linux Device Driver? Kevin Dankwardt, Ph.D. VP Technology Open Source Careers

Linux Operating System

Pebbles Kernel Specification September 26, 2004

CS 378 (Spring 2003)

Kthreads, Mutexes, and Debugging. Sarah Diesburg CS 3430 Operating Systems

CPSC 8220 FINAL EXAM, SPRING 2016

CSE 333 SECTION 3. POSIX I/O Functions

POSIX Shared Memory. Linux/UNIX IPC Programming. Outline. Michael Kerrisk, man7.org c 2017 November 2017

OS COMPONENTS OVERVIEW OF UNIX FILE I/O. CS124 Operating Systems Fall , Lecture 2

Operating System Concepts Ch. 11: File System Implementation

NPTEL Course Jan K. Gopinath Indian Institute of Science

RCU. ò Walk through two system calls in some detail. ò Open and read. ò Too much code to cover all FS system calls. ò 3 Cases for a dentry:

VFS, Continued. Don Porter CSE 506

Android 多核心嵌入式多媒體系統設計與實作

Operating systems for embedded systems

Linux Kernel Development (LKD)

Operating systems for embedded systems. Embedded Operating Systems

1. Overview This project will help you understand address spaces and virtual memory management.

we are here Page 1 Recall: How do we Hide I/O Latency? I/O & Storage Layers Recall: C Low level I/O

TIP675-SW-82. Linux Device Driver. 48 TTL I/O Lines with Interrupts Version 1.2.x. User Manual. Issue November 2013

SmartHeap for Multi-Core

Run time environments

- Knowledge of basic computer architecture and organization, ECE 445

Programs. Function main. C Refresher. CSCI 4061 Introduction to Operating Systems

NPTEL Course Jan K. Gopinath Indian Institute of Science

CSE 333 SECTION 3. POSIX I/O Functions

Lecture 3. Introduction to Unix Systems Programming: Unix File I/O System Calls

The Embedded I/O Company TIP700-SW-82 Linux Device Driver User Manual TEWS TECHNOLOGIES GmbH TEWS TECHNOLOGIES LLC

University of Texas at Arlington. CSE Spring 2018 Operating Systems Project 4a - The /Proc File Systems and mmap. Instructor: Jia Rao

QUESTION BANK UNIT I

Logical disks. Bach 2.2.1

Kernel. Kernel = computer program that connects the user applications to the system hardware Handles:

CS 0449 Project 4: /dev/rps Due: Friday, December 8, 2017, at 11:59pm

Lecture 20. Log into Linux. Copy directory /home/hwang/cs375/lecture20 Project 5 due today. Project 6 posted, due Tuesday, April 8. Questions?

Computer Science 2500 Computer Organization Rensselaer Polytechnic Institute Spring Topic Notes: C and Unix Overview

ECE 550D Fundamentals of Computer Systems and Engineering. Fall 2017

Interrupt handling. Interrupt handling. Deferred work. Interrupt handling. Remove an interrupt handler. 1. Link a struct work to a function

CSC369 Lecture 2. Larry Zhang

Operating systems. Lecture 7

Operating System Design Issues. I/O Management

Operating Systems. Lecture 06. System Calls (Exec, Open, Read, Write) Inter-process Communication in Unix/Linux (PIPE), Use of PIPE on command line

82V391x / 8V893xx WAN PLL Device Families Device Driver User s Guide

I/O Management Software. Chapter 5

CSE 565 Computer Security Fall 2018

Simple char driver. for Linux. my_first.c: headers. my_first.c: file structure. Calcolatori Elettronici e Sistemi Operativi.

Files and Directories Filesystems from a user s perspective

The bigger picture. File systems. User space operations. What s a file. A file system is the user space implementation of persistent storage.

CS 3113 Introduction to Operating Systems Midterm October 11, 2018

CS 3113 Introduction to Operating Systems Midterm October 11, 2018

pthreads CS449 Fall 2017

Loadable Kernel Modules

Linux Loadable Kernel Modules (LKM)

MaRTE OS Misc utilities

Chapter 12 IoT Projects Case Studies. Lesson-01: Introduction

CS 31: Intro to Systems Pointers and Memory. Kevin Webb Swarthmore College October 2, 2018

Basic OS Progamming Abstrac7ons

Linux Driver and Embedded Developer

USB. Development of a USB device driver working on Linux and Control Interface. Takeshi Fukutani, Shoji Kodani and Tomokazu Takahashi

CSE 410: Systems Programming

Basic OS Progamming Abstrac2ons

Developing Real-Time Applications

CS510 Operating System Foundations. Jonathan Walpole

Operating Systems. VI. Threads. Eurecom. Processes and Threads Multithreading Models

Lab 09 - Virtual Memory

Operating Systems (234123) Spring 2017 (Homework Wet 1) Homework 1 Wet

Operating Systems Comprehensive Exam. Spring Student ID # 3/16/2006

Transcription:

Introduction (Linux Device Drivers, 3rd Edition (www.makelinux.net/ldd3)) Device Drivers -> DD They are a well defined programming interface between the applications and the actual hardware They hide completely the details of how the device works Users interact with hardware through a set of standardized calls that are independent of the specific driver The device driver (DD) implements these user functions, which translate system calls into device-specific operations that act on real hardware Note that some DD functions are NOT callable by the user but instead act on behalf of the hardware, e.g., interrupt service routines (more on this later) Also, as we already know, the programming interface for DDs in Linux allows them to be built separately as a module, and plugged in at runtime. This simplifies the development/debug of DDs and improves kernel customization capabilities (important for resource constrained systems) ECE UNM 1 (9/22/15)

Introduction Note that DDs should focus on mechanism, i.e., the capabilities to be provided by the DD, and NOT on policy, on deciding how those capabilites can be used The focus on mechanism will require that you have an intimate knowledge of the hardware component that will be controlled A major challenge of DD developement is supporting concurrency, i.e., simultaneous use by multiple processes With SMP, supporting concurrency has become even more important The kernel is a large executable in charge of handling a variety of tasks: Process management: Creating and destroying processes, providing inter-process communication mechanisms, supporting the notion of concurrency Memory management: Implementing virtual memory systems, and providing for dynamic allocation and de-allocation of memory to programs Filesystems Device control (the topic of this lecture) Networking ECE UNM 2 (9/22/15)

Introduction Overview of the kernel Loadable modules enable functionality to be added at runtime The figure shows the different classes of modules that can be loaded You use functions such as insmod and rmmod to add/remove modules at runtime ECE UNM 3 (9/22/15)

Introduction Three basic classes of modules: char(acter) device: A char device is one that can be accessed as a stream of bytes, similar to a file Examples include the text console and serial ports These devices are accessed using filesystem nodes in /dev Unlike files, char devices usually do not allow random movement within the stream block device: Also represented as filesystem nodes in /dev, but can host a filesystem Best example is a hard drive Block devices support the transfer of entire blocks of data, e.g., 512 bytes, at a time All-in-all, block devices are similar to char devices from the user perspective and differ only in how data is managed internally by the kernel network device: Are stream oriented devices such as eth0 but have no entry in /dev ECE UNM 4 (9/22/15)

Introduction Note that some devices, such as USB, can serve multiple roles, e.g., as a char device (a USB serial port), a block device (a USB memory card reader) and as a network device (a USB ethernet interface) Linux supports other types of modules, including filesystems, that layer on top of device based modules Building and Running Modules Building modules for 2.6.x requires that you have a configured and built kernel tree on your system This is a change from previous versions of the kernel, where a current set of header files was sufficient 2.6 modules are linked against object files found in the kernel source tree Fortunately for us, the Zedboard provides a ideal platform to experiment with modulues, without the danger of destroying a Linux installation, e.g., on your laptop As is traditional, we begin with a Hello world module. ECE UNM 5 (9/22/15)

Building and Running Modules Hello world module: #include <linux/init.h> #include <linux/module.h> MODULE_LICENSE("Dual BSD/GPL"); // Free license static int hello_init(void) { printk(kern_alert "Hello, world\n"); return 0; } static void hello_exit(void) { printk(kern_alert "Goodbye, cruel world\n"); } module_init(hello_init); module_exit(hello_exit); ECE UNM 6 (9/22/15)

Building and Running Modules This module is about as simple as it gets It has only two functions: hello_init: Invoked when the module is loaded into the kernel hello_exit: Invoked when the module is removed module_init and module_exit functions are special kernel macros that tell the kernel the names of the functions to be used for these two roles printk is similar to the standard C library function printf This special version is used with DD code b/c DD code does NOT have access to the C library printk provides for a special indicator string, here KERN_ALERT, to indicate the priority of the message There are a variety of priorities, each with their own unique symbol Bear in mind that where the printk writes its message is dependent on the priority level ECE UNM 7 (9/22/15)

Building and Running Modules To compile and run: % make make[1]: Entering directory /usr/src/linux-2.6.10 CC [M] /home/ldd3/src/misc-modules/hello.o Building modules, stage 2. MODPOST CC /home/ldd3/src/misc-modules/hello.mod.o LD [M] /home/ldd3/src/misc-modules/hello.ko make[1]: Leaving directory /usr/src/linux-2.6.10 % su root# insmod./hello.ko Hello, world root# rmmod hello Goodbye cruel world root# Note that you must have a properly configured and built kernel tree (here it is located at /usr/src/linux-2.6.10 ) in order for this to work ECE UNM 8 (9/22/15)

Building and Running Modules Compiling Modules: There are special considerations in the command make for building kernel modules For the hello_world program, a makefile with the following line is sufficient: obj-m := hello.o This line leverages the extended syntax provided by GNU make and states that there is one module to be built, hello.ko, from the object file hello.o If you have more than one source file, this expands to: obj-m := module.o module-objs := file1.o file2.o Type this command from the source directory of the module (change ~/kernel-2.6) make -C ~/kernel-2.6 M= pwd modules You can write the hello.ko module to your SD disk (mount it on your host system and copy it there), so it is available when you boot the Zedboard ECE UNM 9 (9/22/15)

Building and Running Modules Important distinction between DDs and user applications: Unlike applications, you can only link to functions that are part of the kernel, i.e., never to lib C functions (see header files in include/linux and include/asm ) You must be very digilent in the exit function to clean up, e.g., de-allocate memory, etc. since it is NOT automatic as it is in applications Unlike seg faults in an application, a DD fault can kill the whole kernel A module runs in kernel space (highest priviledge level), while applications run in user space (lowest priviledge level) Other distinctions: Memory in an application is virtual and can be swapped out to disk (kernel memory is never swappable ) Most DD functions serve as system calls for applications, which can copy to and from the memory in a user space process Interrupt service routines (ISRs) (also included in DD modules) are asynchronous to processes and are NOT system calls ECE UNM 10 (9/22/15)

Building and Running Modules The most important distinction between user applications and DD (kernel) code -> CONCURRENCY Most user applications (except multithreading) run from start to finish, and do not need to worry about their environment Even the simpliest kernel modules must assume many things can be happening at once Multiple processes may be accessing a DD simultaneously ISRs can be invoked through interrupts, and can execute while other DD functions in the same module are executing The DD functions can be invoked simultaneously on multiple processors (SMP environments) Kernel code (as of release 2.6) is preemptible, which makes uniprocessor systems subject to the same issues as multiprocessor systems This means that DD code must be reentrant, i.e., it must be capable of running on behalf of more than one process simultaneously For example, data structures must be carefully designed to keep multiple threads of execution separate, and shared data must be protected, e.g., semiphores ECE UNM 11 (9/22/15)

Building and Running Modules Race conditions, i.e., where the results of a computation depend on the relative order of execution, must be avoided when writing DD code You can no longer assume that your DD functions are not preemptive, i.e., you can not assume that a segment of code in a DD function will execute from start to finish without the possibility of being put to sleep Concurrency problems are very difficult to debug, so you must learn how to program for concurrency There are a set of kernel support functions to assist with concurrency, as we shall see The scull device (simple character utility for loading localities) is used as an example in the text http://www.makelinux.net/ldd3/?u=chp-10-sect-5 scull controls a memory area as though it was a device, and is hardware independent ECE UNM 12 (9/22/15)

We will look at several variants of scull The first variants are referred to as scull0 to scull3 Each has a memory area that is global (can be opened multiple times with data shared) and persistent (can be opened and closed without loosing contents). Major and Minor Numbers Char devices are accessed through special files that are traditionally located in /dev, and have a c as the first character in a long list (ls -ltra /dev) crw-rw-rw- 1 root root 1, 3 Apr 11 2002 null crw------- 1 root root 10, 1 Apr 11 2002 psaux crw------- 1 root root 4, 1 Oct 28 03:04 tty1 The major device numbers in the above listing are 1, 10 and 4 while the minor numbers are 3 and 1. The major number identifies the DD associated with the device (in rare cases, several drivers may be associated with a major number) ECE UNM 13 (9/22/15)

The minor number is used by the kernel to determine the actual device You can either get a direct pointer to your device from the kernel, or you can use the minor number yourself as an index into a local array of devices Within the kernel, the dev_t type defines device numbers Given a dev_t or the numbers, you can convert between them in your DD: maj_num = MAJOR(dev_t dev); min_num = MINOR(dev_t dev); my_dev_t = MKDEV(int major, int minor); You must setup a char device within your DD using: int register_chrdev_region(dev_t first, unsigned int count, char *name); where first is the first number you want to allocate and name is the name that shows up in /proc/devices and /sys There is also an alloc_chrdev_region version that allows the kernel to choose the number As is almost always the case, the kernel returns 0 if the call is successful ECE UNM 14 (9/22/15)

The directory /proc/devices is populated first with the device number If the /dev nodes do not exist, then there is a script (run as root) that can be used to create them. See section 3.2.3 in http://www.makelinux.net/ldd3/?u=chp-10-sect-5 Important Data Structures: file_operations, file, and inode file_operations: Used to connect device numbers to the DD system call functions It is a structure with fields for function pointers (a jump table) which implement systems calls such as open, read, etc. Each time a device is opened, the kernel creates a file structure with a field f_op, that points to this file_operations structure The types of system calls supported are provided as a function pointers in the file_operations structure -- here are a few: int (*open) (struct inode *, struct file *); ssize_t (*read) (struct file *, char user *, size_t, loff_t *); ssize_t (*write) (struct file *, const char user *, size_t, loff_t *); ECE UNM 15 (9/22/15)

scull implements the following functions: struct file_operations scull_fops = {.owner = THIS_MODULE,.llseek = scull_llseek,.read = scull_read,.write = scull_write,.ioctl = scull_ioctl,.open = scull_open,.release = scull_release, }; THIS_MODULE is a pointer to the module that "owns" the structure struct file: Usually referred to as filp for file pointer in code Has no relation to user space FILE (which is a C library structure) The kernel creates it when the device is first opened Some of its fields mode_t f_mode; struct file_operations *f_op; void *private_data; ECE UNM 16 (9/22/15)

inode: Used by the kernel internally to represent files The major and minor numbers can be obtained from inode using: unsigned int iminor(struct inode *inode); unsigned int imajor(struct inode *inode); Character device registration: The kernel uses structures of type struct cdev to represent char devices internally Before the kernel invokes your device s operations, you must allocate and register one of these structures First let s cover how scull manages its data, using a struct scull_dev struct scull_dev { struct scull_qset *data; /* Pointer to first quantum set */ int quantum; /* the current quantum size */ int qset; /* the current array size */ unsigned long size; /* amount of data stored here */ unsigned int access_key; /* used by sculluid and scullpriv */ struct semaphore sem; /* mutual exclusion semaphore */ struct cdev cdev; /* Char device structure */ }; ECE UNM 17 (9/22/15)

The initialization function which interfaces the scull device to the kernel: static void scull_setup_cdev(struct scull_dev *dev, int index) { int err, devno = MKDEV(scull_major, scull_minor + index); cdev_init(&dev->cdev, &scull_fops); dev->cdev.owner = THIS_MODULE; dev->cdev.ops = &scull_fops; err = cdev_add (&dev->cdev, devno, 1); /* Fail gracefully if need be */ if (err) printk(kern_notice "Error %d adding scull%d", err, index); } A kernel struct cdev is initialized using: void cdev_init(struct cdev *cdev, struct file_operations *fops); Once the cdev structure is set up, the final step is to tell the kernel about it: int cdev_add(struct cdev *dev, dev_t num, unsigned int count); Here, dev is the cdev structure, num is the first device number, and count is usually 1 ECE UNM 18 (9/22/15)

Notes: cdev_add can fail with a negative return value (usually doesn t but you need to check) When cdev_add returns, your device is "live" and its operations can be called by the kernel immediately! Let s start looking at the system calls registered in struct file_operations The open method Preps the driver for later operations int (*open)(struct inode *inode, struct file *filp); The inode argument has a pointer to cdev structure just setup above, but we really want the scull_dev structure that contains a pointer to the cdev structure struct scull_dev *dev; /* device information */ dev = container_of(inode->i_cdev, struct scull_dev, cdev); filp->private_data = dev; /* for other methods */ The macro container_of returns a pointer to its parent struct scull_dev ECE UNM 19 (9/22/15)

The entire scull_open routine: int scull_open(struct inode *inode, struct file *filp) { struct scull_dev *dev; /* device information */ dev = container_of(inode->i_cdev, struct scull_dev, cdev); filp->private_data = dev; /* for other methods */ /* Trim to 0 the length of the device if open was write-only */ if ( (filp->f_flags & O_ACCMODE) = = O_WRONLY) scull_trim(dev); /* ignore errors */ return 0; /* success */ } Not a whole lot is done here b/c scull uses memory as the device The release method Deallocate anything that open allocated in filp->private_data and shut down the device on last close int scull_release(struct inode *inode, struct file *filp) { return 0;} ECE UNM 20 (9/22/15)

The read and write methods These functions copy data to and from user space into memory allocated by scull ssize_t read(struct file *filp, char user *buff, size_t count, loff_t *offp); ssize_t write(struct file *filp, const char user *buff, size_t count, loff_t *offp); For both methods, filp is the file pointer and count is the size of the requested data transfer (See Section 3.6 of http://www.makelinux.net/ldd3/?u=chp-10-sect-5 for details on scull memory allocation model) The buff argument points to the user buffer holding the data to be written or the empty buffer where the newly read data should be placed offp is a pointer to a "long offset type" object that indicates the file position the user is accessing ECE UNM 21 (9/22/15)

It is important to realize that buff is a user-space pointer, and therefore, cannot be directly dereferenced by kernel code The buff pointer may be: Invalid or The user-space page may be in swap (generating a page fault results in an "oops" and the death of the process making the sys call) The pointer may be malicious, allowing memory to overwritten anywhere in the system, opening a security hole Access to user-space must be done using kernel-supplied functions: unsigned long copy_to_user(void user *to, const void *from, unsigned long count); unsigned long copy_from_user(void *to, const void user *from, unsigned long count); These functions behave like the memcpy C library function ECE UNM 22 (9/22/15)

Couple of important notes: The user-space memory may be in swap, and therefore, the process will be put to sleep, requiring the DD code to be reentrant and in a position where it can legally sleep These kernel functions also check whether the user-space pointer is valid If invalid, no copy is performed If it becomes invalid during the copy, only part of the data is copied and the return value is the amount of memory still to be copied ECE UNM 23 (9/22/15)

The read and write DD methods return -1 if an error occurs (user processes use errno to determine the reason), while a value >= 0 tells the user-space process how many bytes were successfully transferred Interestingly, if the value returned by the DD method is >= 0 but not equal to count, C library routines, such as fread reissue the system call until it succeeds But what about the case "this is no data, but it may arrive later" Here, the read system call should block (covered later) Interesting things can happen for example if process A is reading the device while process B opens it for writing, which truncates the file to 0 Process A suddenly finds itself past end-of-file and next read call returns 0 The read and write methods are given in the on-line text With those included, you have a complete driver that can be compiled and run as a module ECE UNM 24 (9/22/15)