Linux device-driver issues - PowerPoint PPT Presentation

About This Presentation
Title:

Linux device-driver issues

Description:

Linux device-driver issues. Devices as special' files. Unix programs ... Maintaining this registry is a big hassle' (e.g., delays, arguments, too few numbers) ... – PowerPoint PPT presentation

Number of Views:16
Avg rating:3.0/5.0
Slides: 26
Provided by: professora5
Learn more at: https://www.cs.usfca.edu
Category:
Tags: device | driver | hassle | issues | leds | linux

less

Transcript and Presenter's Notes

Title: Linux device-driver issues


1
Linux device-driver issues

2
Devices as special files
  • Unix programs treat most devices as files
  • Provides a familiar programming interface
  • Standard C functions open(), read(), etc
  • But such devices need to have filenames
  • Device files are located in /dev directory

3
Example our led device
  • We created a char device-driver led.c
  • It operated a standard keyboards LEDs
  • It was a write-only character device
  • Applications saw it as a file /dev/led
  • We tested it using echo 7 gt /dev/led
  • That command turned on all three LEDs

4
Example C application
  • int main( void )
  • int fd open( /dev/led, O_WRONLY )
  • if ( fd lt 0 ) perror( open ) exit(1)
  • char indicator 7
  • write( fd, indicator, 1 )
  • close( fd )

5
Kernel uses different ID-scheme
  • Kernel uses number-pairs (major,minor)
  • The major number identifies the driver
  • The minor number identifies the device
  • One driver can control multiple devices
  • Range for major numbers is 0..255
  • Certain of these values are reserved

6
Assigning major numbers
  • Driver-author can select a major number
  • Kernel is told during driver registration
  • But author must be careful no duplication!
  • Registration fails if number already used
  • View currently used major numbers with
  • cat /proc/devices

7
Dynamic module loading
  • Linux lets module be loaded on demand
  • This could cause contention for numbers
  • Example your driver uses major6
  • But line-printer driver (lp.c) uses major6
  • During printing your module wont install
  • And printing fails if your module is installed

8
Official device-numbers
  • There is a registry of device-numbers
  • See file devices.txt in kernel sources
  • Look in /usr/src/linux/Documentation
  • Maintaining this registry is a big hassle
  • (e.g., delays, arguments, too few numbers)
  • So some alternative solution was needed

9
Dynamic assignment
  • Module author can let kernel choose major
  • This is why major-number 0 is never used
  • If programmer requests major-number 0,
  • kernel assigns an available major-number
  • Kernel informs driver during registration

10
Driver registration
  • int register_chrdev( unsigned int major,
  • const char driver_name,
  • struct file_operations fops )
  • Returns major-number (or error-code)
  • Using 0 as first argument (major) tells
  • kernel to pick an unused major-number

11
Chicken-and-Egg problem?
  • A drivers device-file(s) must be created
  • Creator must know device major-number
  • (Also creator will need root privileges!)
  • Example root mknod /dev/led c 15 0
  • Creates a character device-node having
  • major-number15 and minor-number0

12
Obstacles for us
  • How to we find out what major-number the kernel
    dynamically assigned to our driver?
  • How can we create special files in /dev
  • that allow applications to use our driver?
  • How to we set the file permissions so a normal
  • program can open, read/write to our devices?

13
Overcoming those obstacles
  • Our driver will know its major-number
  • init_module() will register our driver
  • Return-value will be the major-number
  • We could use printk() to display its value
  • Then a user could create the device-file
  • BUT will the user be allowed to do it?
  • mknod and chmod need root privileges

14
One convenient solution
  • Let our module setup its own device-file(s)
  • Our module will know the major-number
  • and our module has root privileges
  • BUT
  • Can modules execute mknod? chmod?

15
Kernel System Calls
  • Kernel function is named sys_mknod
  • In kernel 2.4.20 this symbol isnt exported
  • Module loader cant link our module to it
  • Which kernel symbols ARE exported?
  • Use cat /proc/ksyms
  • Ugh! Hundreds of exported kernel symbols
  • Better grep sys_mknod /proc/ksyms

16
sys_call_table is exported
  • Try cat sys_call_table /proc/ksyms
  • We CAN link our with sys_call_table
  • Declare extern void sys_call_table
  • I.e., sys_call_table is an array of pointers
  • A pointer to sys_mknod is in this array!
  • But where?

17
Header-file asm/unistd.h
  • Kernel-header defines symbolic constants
  • Examples
  • define __NR_mknod 14
  • define __NR_chmod 15
  • These are indexes into sys_call_table
  • So function-pointers can be looked up

18
Programming Syntax
  • Declare static function-pointer variables
  • static int (sys_mknod)( const char , )
  • static int (sys_chmod)( const char , )
  • Initialize these function-pointer variables
  • sys_mknod sys_call_table __NR_mknod
  • sys_chmod sys_call_table __NR_chmod

19
One further gotcha
  • System-call expect user-space arguments
  • E.g., filename is a string from user-space
  • Kernel will check for an illegal argument
  • A system-call from kernel-space will fail!
  • PAGE_OFFSET is origin of kernel-space
  • Normally PAGE_OFFSET is 0xC0000000

20
Raising the user-space roof
  • Top of user-space is a task-variable
  • Each task has its own local copy
  • Kept in the struct task_struct structure
  • Assigned during task-creation (e.g., fork() )
  • Kernel can change this variables value!
  • Syntax set_fs( get_ds() )
  • Needs header include ltasm/uaccess.hgt

21
init_module algorithm
  • char nm led
  • struct file_operations fops write write,
  • int major register_chrdev(0, nm, fops )
  • Dev_t dev_id MKDEV( major, minor )
  • sys_mknod sys_call_table __NR_mknod
  • set_fs( get_ds() )
  • sys_mknod( /dev/led, S_IFCHR, dev_id )

22
How to remove a device-file
  • Another privileged command
  • Example root unlink /dev/led
  • We can let our cleanup_module() do it
  • But cleanup and init are different tasks
  • root /sbin/insmod led.o
  • root /sbin/rmmod led
  • insmod will call our init_module()
  • rmmod will call our cleanup_module()

23
Algorithm for cleanup
  • const char modname led
  • unregister_chrdev( major, modname )
  • sys_unlink sys_call_table __NR_unlink
  • set_fs( get_ds() )
  • const char devname /dev/led
  • sys_unlink( devname )

24
pseudo-code versus C
  • Previous slides showed algorithm-steps
  • BUT C language has special requirement
  • Within each C program-block
  • all of blocks local variables are declared
  • (and, optionally, initialized)
  • BEFORE any executable-statements appear
  • This differs from C (which is less strict)

25
Now an in-class exercise
  • See online version of our stash.c driver
  • Accessible on our class webpage
  • http//nexus.cs.usfca.edu/cruse/cs635/
  • It was written and tested for kernel 2.4.18
  • That kernel exported system-call functions
  • sys_call_table lookups werent needed
  • Can you modify stash.c for 2.4.20?
Write a Comment
User Comments (0)
About PowerShow.com