DOC PREVIEW
USF CS 635 - Linux device-driver issues

This preview shows page 1-2-24-25 out of 25 pages.

Save
View full document
View full document
Premium Document
Do you want full access? Go Premium and unlock all 25 pages.
Access to all documents
Download any document
Ad free experience
View full document
Premium Document
Do you want full access? Go Premium and unlock all 25 pages.
Access to all documents
Download any document
Ad free experience
View full document
Premium Document
Do you want full access? Go Premium and unlock all 25 pages.
Access to all documents
Download any document
Ad free experience
View full document
Premium Document
Do you want full access? Go Premium and unlock all 25 pages.
Access to all documents
Download any document
Ad free experience
Premium Document
Do you want full access? Go Premium and unlock all 25 pages.
Access to all documents
Download any document
Ad free experience

Unformatted text preview:

Linux device-driver issuesDevices as ‘special’ filesExample: our ‘led’ deviceExample C++ applicationKernel uses different ID-schemeAssigning ‘major’ numbers‘Dynamic’ module loading‘Official’ device-numbersDynamic assignmentDriver registration‘Chicken-and-Egg’ problem?Obstacles for usOvercoming those obstaclesOne convenient solutionKernel System Calls‘sys_call_table’ is exportedHeader-file: ‘asm/unistd.h’Programming SyntaxOne further ‘gotcha’Raising the ‘user-space’ roof‘init_module’ algorithmHow to remove a device-fileAlgorithm for ‘cleanup’‘pseudo-code’ versus CNow: an in-class exerciseLinux device-driver issuesDevices 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’ directoryExample: our ‘led’ device•We created a ‘char’ device-driver: ‘led.c’•It operated a standard keyboard’s 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 LEDsExample C++ application int main( void ){int fd = open( “/dev/led”, O_WRONLY );if ( fd < 0 ) { perror( “open” ); exit(1); }char indicator = 7;write( fd, &indicator, 1 );close( fd );}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’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‘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 won’t install•And printing fails if your module is installed‘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 neededDynamic 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’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’) tellskernel to pick an unused major-number‘Chicken-and-Egg’ problem?•A driver’s 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 havingmajor-number=15 and minor-number=0Obstacles 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 normalprogram can open, read/write to our devices?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 privilegesOne 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’?Kernel System Calls •Kernel function is named ‘sys_mknod’•In kernel 2.4.20 this ‘symbol’ isn’t exported•Module loader can’t 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‘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?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’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];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 0xC0000000Raising 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 variable’s value!•Syntax: set_fs( get_ds() );•Needs header: #include <asm/uaccess.h>‘init_module’ algorithmchar 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 );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.oroot# /sbin/rmmod led•‘insmod’ will call our init_module()•‘rmmod’ will call


View Full Document

USF CS 635 - Linux device-driver issues

Download Linux device-driver issues
Our administrator received your request to download this document. We will send you the file to your email shortly.
Loading Unlocking...
Login

Join to view Linux device-driver issues and access 3M+ class-specific study document.

or
We will never post anything without your permission.
Don't have an account?
Sign Up

Join to view Linux device-driver issues 2 2 and access 3M+ class-specific study document.

or

By creating an account you agree to our Privacy Policy and Terms Of Use

Already a member?