Presentation is loading. Please wait.

Presentation is loading. Please wait.

Linux device-driver issues. Devices as special files Unix programs treat most devices as files Provides a familiar programming interface Standard C functions:

Similar presentations


Presentation on theme: "Linux device-driver issues. Devices as special files Unix programs treat most devices as files Provides a familiar programming interface Standard C functions:"— Presentation transcript:

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 > /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 < 0 ) { perror( open ); exit(1); } charindicator = 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 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 major=6 But line-printer driver (lp.c) uses major=6 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-number=15 and minor-number=0

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 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 0xC

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

21 init_module algorithm charnm = led; struct file_operations fops = { write: write, }; int major = register_chrdev(0, nm, &fops ); Dev_tdev_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 charmodname[] = led; unregister_chrdev( major, modname ); sys_unlink = sys_call_table[ __NR_unlink ]; set_fs( get_ds() ); const chardevname[] = /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 It was written and tested for kernel That kernel exported system-call functions sys_call_table[] lookups werent needed Can you modify stash.c for ?


Download ppt "Linux device-driver issues. Devices as special files Unix programs treat most devices as files Provides a familiar programming interface Standard C functions:"

Similar presentations


Ads by Google