Dr A Sahu Dept of Comp Sc & Engg. IIT Guwahati. Character Device Driver – Characteristics and functionality – Basic IO functions Multi tasking (pre requisite.

Slides:



Advertisements
Similar presentations
Linux device-driver issues
Advertisements

Device Drivers. Linux Device Drivers Linux supports three types of hardware device: character, block and network –character devices: R/W without buffering.
Linux kernel internals Introduction to process descriptors.
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.
CSCC69: Operating Systems
The Linux Kernel: Memory Management
The ‘process’ abstraction
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?
Standard C Libraries Application Programmming Interface to System-Calls.
Processes CSCI 444/544 Operating Systems Fall 2008.
The kernel’s task list Introduction to process descriptors and their related data-structures for Linux kernel version
Introduction to Kernel
Home: Phones OFF Please Unix Kernel Parminder Singh Kang Home:
The kernel’s task list Introduction to process descriptors and their related data-structures for Linux kernel version
Scientific Visualization Using imagery to aid humans in understanding a complicated phenomenon.
Advanced OS Chapter 3p2 Sections 3.4 / 3.5. Interrupts These enable software to respond to signals from hardware. The set of instructions to be executed.
CS-502 Fall 2006Processes in Unix, Linux, & Windows 1 Processes in Unix, Linux, and Windows CS502 Operating Systems.
Linux Review COMS W4118 Spring Linux Overview History Distributions Licensing Components Kernel, daemons, libraries, utilities, etc Modules Build.
Unix & Windows Processes 1 CS502 Spring 2006 Unix/Windows Processes.
CSE 451 Section 4 Project 2 Design Considerations.
Dr A Sahu Dept of Comp Sc & Engg. IIT Guwahati. Writing/Registering to /proc Character Device Driver – Characteristics and functionality – Basic IO functions.
Using Two Queues. Using Multiple Queues Suspended Processes Processor is faster than I/O so all processes could be waiting for I/O Processor is faster.
CSE 451: Operating Systems Autumn 2013 Module 6 Review of Processes, Kernel Threads, User-Level Threads Ed Lazowska 570 Allen.
Operating System Program 5 I/O System DMA Device Driver.
CS 6560 Operating System Design Lecture 13 Finish File Systems Block I/O Layer.
Introduction to Processes CS Intoduction to Operating Systems.
CS1550 Assignment 5 Multiprogramming Implementation notes Matt Craven.
Lecture 5 Process, Thread and Task September 22, 2015 Kyu Ho Park.
The Structure of Processes. What is a Process? an instance of running program Program vs process(task) Program : just a passive collection of instructions.
File System Review bottomupcs.com J. Kubiatowicz, UC Berkeley.
The Structure of Processes (Chap 6 in the book “The Design of the UNIX Operating System”)
Lecture 3 Process Concepts. What is a Process? A process is the dynamic execution context of an executing program. Several processes may run concurrently,
Device Drivers CPU I/O Interface Device Driver DEVICECONTROL OPERATIONSDATA TRANSFER OPERATIONS Disk Seek to Sector, Track, Cyl. Seek Home Position.
ITEC 502 컴퓨터 시스템 및 실습 Chapter 2-1: Process Mi-Jung Choi DPNM Lab. Dept. of CSE, POSTECH.
Threads G.Anuradha (Reference : William Stallings)
Files & File system. A Possible File System Layout Tanenbaum, Modern Operating Systems 3 e, (c) 2008 Prentice-Hall, Inc. All rights reserved
Linux Processes Travis Willey Jeff Mihalik. What is a process? A process is a program in execution A process includes: –program counter –stack –data section.
Operating Systems Process Creation
4300 Lines Added 1800 Lines Removed 1500 Lines Modified PER DAY DURING SUSE Lab.
I/O, Devices & Device Drivers I/O subsystem It is the responsibility of the I/O subsystem of an OS to schedule, manage, & control the interactions between.
CSC 660: Advanced Operating Systems
COMP 3438 – Part I - Lecture 5 Character Device Drivers
What is a Process ? A program in execution.
Embedded Real-Time Systems Processing interrupts Lecturer Department University.
Processes David Ferry, Chris Gill CSE 522S - Advanced Operating Systems Washington University in St. Louis St. Louis, MO
Advanced Operating Systems CS6025 Spring 2016 Processes and Threads (Chapter 2)
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.
Threads prepared and instructed by Shmuel Wimer Eng. Faculty, Bar-Ilan University 1July 2016Processes.
Input/Output (I/O) Important OS function – control I/O
Introduction to Kernel
Chapter 13: I/O Systems Modified by Dr. Neerja Mhaskar for CS 3SH3.
Process Management Process Concept Why only the global variables?
Structure of Processes
Protection of System Resources
Processes David Ferry, Chris Gill
Chapter 2: The Linux System Part 2
CS703 - Advanced Operating Systems
System Calls David Ferry CSCI 3500 – Operating Systems
Lecture 6: Multiprogramming and Context Switching
Chapter 13: I/O Systems I/O Hardware Application I/O Interface
Chapter 3: Processes.
Unix Process Control B.Ramamurthy 4/11/2019 B.Ramamurthy.
Processes in Unix, Linux, and Windows
Processes in Unix and Windows
CS510 Operating System Foundations
COMP755 Advanced Operating Systems
Structure of Processes
In Today’s Class.. General Kernel Responsibilities Kernel Organization
Threads CSE 2431: Introduction to Operating Systems
Presentation transcript:

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

Character Device Driver – Characteristics and functionality – Basic IO functions Multi tasking (pre requisite to do this) Examples Drivers (in detail) ADC, Printer, Tape drive

$cd /dev/block/ $ ls –l rwxrwxrwx 1 root root :32 1:0 ->../ram0 lrwxrwxrwx 1 root root :32 1:1 ->../ram1 … lrwxrwxrwx 1 root root :32 1:15 ->../ram15 lrwxrwxrwx 1 root root :02 11:0 ->../sr0 lrwxrwxrwx 1 root root :02 7:0 ->../loop0 lrwxrwxrwx 1 root root :02 7:1 ->../loop1 …. rwxrwxrwx 1 root root :02 7:7 ->../loop7 lrwxrwxrwx 1 root root :02 8:0 ->../sda lrwxrwxrwx 1 root root :02 8:1 ->../sda1 …. lrwxrwxrwx 1 root root :02 8:5 ->../sda5 Mount –o loop CD.iso /mnt/cdrom # Formats, mounts, and sets permissions on my 16MB ramdisk $/bin/mount /dev/ram0 /mnt/rd

$cd /dev/char/ $ ls –l lrwxrwxrwx 1 root root :02 10:144 ->../nvram lrwxrwxrwx 1 root root :32 10:223 ->../input/uinput lrwxrwxrwx 1 root root :02 10:227 ->../mcelog lrwxrwxrwx 1 root root :02 10:228 ->../hpet lrwxrwxrwx 1 root root :33 10:229 ->../fuse lrwxrwxrwx 1 root root :02 10:231 ->../snapshot lrwxrwxrwx 1 root root :32 10:232 ->../kvm lrwxrwxrwx 1 root root :32 10:57 ->../vboxnetctl lrwxrwxrwx 1 root root :32 10:58 ->../vboxdrv lrwxrwxrwx 1 root root :02 10:59 ->../network_throughput lrwxrwxrwx 1 root root :02 10:60 ->../network_latency lrwxrwxrwx 1 root root :02 10:61 ->../cpu_dma_latency lrwxrwxrwx 1 root root :02 10:62 ->../mapper/control lrwxrwxrwx 1 root root :02 10:63 ->../vga_arbiter

$cd /dev/char/ $ ls –l lrwxrwxrwx 1 root root :02 1:1 ->../mem lrwxrwxrwx 1 root root :02 1:11 ->../kmsg lrwxrwxrwx 1 root root :02 1:12 ->../oldmem lrwxrwxrwx 1 root root :42 116:10 ->../snd/pcmC1D0c lrwxrwxrwx 1 root root :42 116:11 ->../snd/controlC1 lrwxrwxrwx 1 root root :32 116:2 ->../snd/timer lrwxrwxrwx 1 root root :32 116:3 ->../snd/seq lrwxrwxrwx 1 root root :32 116:4 ->../snd/pcmC0D1p lrwxrwxrwx 1 root root :32 116:5 ->../snd/pcmC0D0p lrwxrwxrwx 1 root root :32 116:6 ->../snd/pcmC0D0c lrwxrwxrwx 1 root root :32 116:7 ->../snd/hwC0D3 lrwxrwxrwx 1 root root :32 116:8 ->../snd/controlC0 lrwxrwxrwx 1 root root :42 116:9 ->../snd/pcmC1D0p lrwxrwxrwx 1 root root :02 1:3 ->../null lrwxrwxrwx 1 root root :02 13:32 ->../input/mouse0 lrwxrwxrwx 1 root root :02 13:33 ->../input/mouse1 lrwxrwxrwx 1 root root :02 13:63 ->../input/mice

$cd /dev/char/ $ ls –l lrwxrwxrwx 1 root root :02 13:64 ->../input/event0 lrwxrwxrwx 1 root root :02 13:65 ->../input/event1 lrwxrwxrwx 1 root root :02 13:66 ->../input/event2 rwxrwxrwx 1 root root :02 162:0 ->../raw/rawctl lrwxrwxrwx 1 root root :02 1:7 ->../full lrwxrwxrwx 1 root root :02 1:8 ->../random lrwxrwxrwx 1 root root :02 189:0 ->../bus/usb/001/001 lrwxrwxrwx 1 root root :02 189:128 ->../bus/usb/002/001 lrwxrwxrwx 1 root root :02 189:256 ->../bus/usb/003/001 lrwxrwxrwx 1 root root :02 189:384 ->../bus/usb/004/001 lrwxrwxrwx 1 root root :02 189:512 ->../bus/usb/005/001 lrwxrwxrwx 1 root root :02 189:513 ->../bus/usb/005/002 lrwxrwxrwx 1 root root :02 189:640 ->../bus/usb/006/001 lrwxrwxrwx 1 root root :42 189:649 ->../bus/usb/006/010 lrwxrwxrwx 1 root root :02 189:768 ->../bus/usb/007/001 lrwxrwxrwx 1 root root :02 1:9 ->../urandom lrwxrwxrwx 1 root root :02 202:0 ->../cpu/0/msr lrwxrwxrwx 1 root root :02 202:1 ->../cpu/1/msr lrwxrwxrwx 1 root root :02 202:2 ->../cpu/2/msr lrwxrwxrwx 1 root root :02 203:0 ->../cpu/0/cpuid lrwxrwxrwx 1 root root :02 203:1 ->../cpu/1/cpuid lrwxrwxrwx 1 root root :02 203:2 ->../cpu/2/cpuid

$cd /dev/char/ $ ls –l lrwxrwxrwx 1 root root :02 21:0 ->../sg0 lrwxrwxrwx 1 root root :02 21:1 ->../sg1 lrwxrwxrwx 1 root root :02 226:0 ->../dri/card0 lrwxrwxrwx 1 root root :02 226:64 ->../dri/controlD64 lrwxrwxrwx 1 root root :02 250:0 ->../hidraw0 lrwxrwxrwx 1 root root :42 250:1 ->../hidraw1 lrwxrwxrwx 1 root root :02 251:0 ->../usbmon0 … lrwxrwxrwx 1 root root :02 251:7 ->../usbmon7 lrwxrwxrwx 1 root root :02 252:0 ->../bsg/0:0:0:0 lrwxrwxrwx 1 root root :02 254:0 ->../rtc0 lrwxrwxrwx 1 root root :02 29:0 ->../fb0 lrwxrwxrwx 1 root root :02 4:0 ->../tty0 … lrwxrwxrwx 1 root root :02 4:38 ->../tty38 lrwxrwxrwx 1 root root :02 5:1 ->../console lrwxrwxrwx 1 root root :02 5:2 ->../ptmx lrwxrwxrwx 1 root root :02 7:0 ->../vcs.. lrwxrwxrwx 1 root root :02 7:1 ->../vcs6 lrwxrwxrwx 1 root root :02 7:128 ->../vcsa.. lrwxrwxrwx 1 root root :32 7:134 ->../vcsa6 lrwxrwxrwx 1 root root :32 7:2 ->../vcs2 lrwxrwxrwx 1 root root :32 7:3 ->../vcs3 lrwxrwxrwx 1 root root :32 7:4 ->../vcs4 lrwxrwxrwx 1 root root :32 7:5 ->../vcs5 lrwxrwxrwx 1 root root :32 7:6 ->../vcs6 lrwxrwxrwx 1 root root :32 99:0 ->../parport0

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.

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) root# mknod /dev/cmos c 70 0 Read /dev/cmos as a FILE root# mknod /dev/cmos c 70 0 Read /dev/cmos as a FILE

Modern operating systems allow multiple users to share a computer’s resources Users are allowed to run multiple tasks The OS kernel must protect each task from interference by other tasks, while allowing every task to take its turn using some of the processor’s available time

To manage multitasking, the OS needs to use a data-structure which can keep track of every task’s progress and usage of the computer’s available resources (physical memory, open files, pending signals, etc.) Such a data-structure is called a ‘process descriptor’ – every active task needs one Every task needs its own ‘private’ stack

Upon entering ‘main()’: A program’s exit-address is on user stack Command-line arguments on user stack Environment variables are on user stack During execution of ‘main()’: Function parameters and return-addresses Storage locations for ‘automatic’ variables

A user process enters ‘kernel-mode’: when it decides to execute a system-call when it is ‘interrupted’ (e.g. by the timer) when ‘exceptions’ occur (e.g. divide by 0)

Entering kernel-mode involves not only a ‘privilege-level transition’ (from level 3 to level 0), but also a stack-area ‘switch’ This is necessary for robustness: e.g., user-mode stack might be exhausted This is desirable for security: e.g, privileged data might be accessible

Upon entering kernel-mode: task’s registers are saved on kernel stack (e.g., address of task’s user-mode stack) During execution of kernel functions: Function parameters and return-addresses Storage locations for ‘automatic’ variables

So every task, in addition to having its own code and data, will also have a stack-area that is located in user-space, plus another stack- area that is located in kernel-space Each task also has a process-descriptor which is accessible only in kernel-space

User space Kernel space User-mode stack-area Task’s code and data Privilege-level 0 Privilege-level 3 process descriptor and kernel-mode stack Shared runtime-libraries

task_struct state *stack flags *mm exit_code *user pid *files *parent mm_struct *pgd pagedir[] user_struct signal_struct *signal files_struct Each process descriptor contains many fields and some are pointers to other kernel structures which may themselves include fields that point to structures

Linux uses part of a task’s kernel-stack page-frame to store ‘thread information’ The thread-info includes a pointer to the task’s process-descriptor data-structure Task’s kernel-stack Task’s thread-info page-frame aligned Task’s process-descriptor Task’s process-descriptor struct task_struct 8-KB

From kernel-header: #define TASK_RUNNING 0 #define TASK_INTERRUPTIBLE1 #define TASK_UNINTERRUPTIBLE2 #define TASK_STOPPED4 #define TASK_TRACED8 #define TASK_NONINTERACTIVE64 #define TASK_DEAD128

struct task_struct { volatile longstate; void*stack; unsigned longflags; struct mm_struct*mm; struct thread_struct*thread; pid_tpid; charcomm[16]; /* plus many other fields */ };

During a task’s execution in kernel-mode, it’s very quick to find that task’s thread-info object Just use two assembly-language instructions: movl$0xFFFFF000, %eax andl%esp, %eax Ok, now %eax = the thread-info’s base-address There’s a macro that implements this computation

Use a macro ‘task_thread_info( task )’ to get a pointer to the ‘thread_info’ structure: struct thread_info *info = task_thread_info( task ); Then one more step gets you back to the address of the task’s process-descriptor: struct task_struct *task = info->task;

Kernel keeps a list of process descriptors A ‘doubly-linked’ circular list is used The ‘init_task’ serves as a fixed header Other tasks inserted/deleted dynamically Tasks have forward & backward pointers, implemented as fields in the ‘tasks’ field To go forward: task = next_task( task ); To go backward: task = prev_task( task );

init_task (pid=0) init_task (pid=0) newest task newest task … next_task prev_task

We can’t know ahead of time how many tasks are active in our system – this will depend on many varying factors, such as who else is logged in, which commands have been issued, whether we’re using text-mode console or graphical desktop So it’s perfectly possible our pseudo-file might ‘overflow’ its kernel-supplied buffer!

Our module’s ‘get_info()’ callback-function has four parameter-values passed to it by the kernel: char *buf - address of a small kernel buffer char **start - address of a pointer variable off_toffset - current offset of file-pointer intbuflen - size of the kernel buffer The initial conditions are: offset == 0 and *start == NULL Kernel’s behavior will vary if we modify *start

We expect the ‘/proc’ file to deliver a small amount of text-data (not more than would fit in the kernel-supplied buffer (e.g., 3KB) So we make no change to ‘*start’ Then kernel will deliver the data it finds in the buffer it had supplied to ‘get_info()’ The kernel will not call ‘get_info()’ again (unless our file is closed and reopened)

Our ‘get_info()’ function modifies the value of the (initially NULL) ‘*start’ pointer – for example, maybe assigning it the address of some buffer we’ve allocated, or even assigning the address of the kernel-buffer: *start = buf; In this case, the kernel will again call our module’s ‘get_info()’ function, provided we returned a nonzero function-value before!

Knowing about this alternative option, we can design our ‘get_info()’ function so that it delivers a big amount of data in several small- size chunks, never overflowing the size- limitations on the kernel’s buffer We just need to think carefully about the differing senarios under which ‘get_info()’ will be repeatedly called

The value of ‘offset’ will be zero We set *start to a buffer-address where we place a positive number of data-bytes Kernel delivers those bytes to the ‘reader’, taking them from the *start address, then advances the file-pointer by that amount Kernel calls our ‘get_info()’ again, but with a non-zero ‘offset’ value this time!

When our ‘get_info()’ function has finally finished delivering all the desired data to the file’s ‘reader’, and still we receive yet another ‘get_info()’ call, then we simply return a function-value equal to zero, telling the kernel that the data has been exhausted -- and so not to call again!

struct task_struct *task;// ‘global’ variables’ values remembered int my_get_info( char *buf, char **start, off_t offset, int buflen ) { intlen = 0; if ( offset == 0 )// our first time through this function { task = &init_task;// start of circular linked-list } else if ( task == &init_task ) return 0;// our final pass // put some data into the kernel-supplied buffer len += sprintf( buf+len, “pid=%d \n”, task->pid ); *start = buf;// tell kernel where to find data, and to call again task = next_task( task );// advance to next node of circular list returnlen;// and tell kernel how far to advance } struct task_struct *task;// ‘global’ variables’ values remembered int my_get_info( char *buf, char **start, off_t offset, int buflen ) { intlen = 0; if ( offset == 0 )// our first time through this function { task = &init_task;// start of circular linked-list } else if ( task == &init_task ) return 0;// our final pass // put some data into the kernel-supplied buffer len += sprintf( buf+len, “pid=%d \n”, task->pid ); *start = buf;// tell kernel where to find data, and to call again task = next_task( task );// advance to next node of circular list returnlen;// and tell kernel how far to advance }

Some tasks don’t have a page-directory of their own – because they don’t need one They only execute code, and access data, that resides in the kernel’s address space They can just ‘borrow’ the page-directory that belongs to another task These ‘kernel thread’ tasks will store the NULL-pointer value (i.e., zero) in the ‘mm’ field of their ‘task_struct’ descriptor (mm:mem map)