1 / 20

Character Driver Issues

Character Driver Issues. Implementing ‘/dev/physmem’. Goals for ‘physmem’. Let user-programs ‘read’ physical memory Make this convenient for the programmer Treat physical memory as just one big file Then can use standard C library functions: i.e., open(), lseek(), read(), close()

romeo
Download Presentation

Character Driver Issues

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Character Driver Issues Implementing ‘/dev/physmem’

  2. Goals for ‘physmem’ • Let user-programs ‘read’ physical memory • Make this convenient for the programmer • Treat physical memory as just one big file • Then can use standard C library functions: i.e., open(), lseek(), read(), close() • But don’t give user-programs write-access!

  3. The ‘mknod’ command • Device-file: usually created by command # mknod /dev/physmem c 251 0 • ‘mknod’ takes 4 command-line arguments: the pathname of the special file ‘c’ indicates it’s a character device 251 is driver’s ID-number (i.e., major) 0 is the device’s ID-number (i.e., minor) • Need ‘root’ privileges to create /dev file

  4. Default file permissions • Without ‘root’ privileges, we can’t try it • But if we could, we’d see file-permissions • Example: # mknod /dev/xxx c 251 0 # ls -l /dev/xxx crw-r—r-- 1 root root 251, 0 25 Feb dev/xxx • We don’t want users to ‘write’ to physmem

  5. Modifying file-permissions • Supervisor can change file-permissions • ‘chmod’ is the privileged command to use • Example: # chmod 0444 /dev/xxx # ls -l /dev/xxx cr--r—r-- 1 root root 251, 0 25 Feb dev/xxx • Now the device-file has ‘read-only’ access

  6. A ‘smarter’ driver • Our drivers can create their own files: syscall: mknod( pathname, mode, devid); • Our drivers can modify file-permissions: syscall: chmod( pathname, mode); • Our drivers can also delete their own files: syscall: unlink( pathname );

  7. Some manifest constants • Header-file: #include <linux/stat.h> #define S_IFCHR 0020000 #define S_IRUSR 0000400 #define S_IRGRP 0000040 #define S_IROTH 0000004 By ‘or’-ing the latter three values, can get: #define S_IRUGO 0000444

  8. Driver’s ‘read()’ function • Must conform to standard prototype • Otherwise: can’t ‘register_chrdev()’ • Return-value has type ‘ssize_t’ • Function takes four arguments: struct file *filp; // pointer to file-structure char *buf; // pointer to user-buffer size_t count; // size of user-buffer loff_t *pos; // points to file-position

  9. Algorithm for ‘read()’ • Step 1: Check for an invalid request: if ( *pos >= filesize ) return –EINVAL; • Step 2: Adjust ‘count’ for remaining bytes: If ( *pos + count > filesize ) count = filesize - *pos;

  10. Algorithm (continued) • Step 3: Find location of next data bytes void *from = phys_to_virt( *pos ); • Step 4: Copy data into user-space buffer more = copy_to_user( buf, from, count ); • Step 5: Return error if copying unfinished if ( more ) return –EFAULT;

  11. Algorithm (conclusion) • Step 6: Advance file’s current position *pos += count; • Step 7: Return number of bytes copied return count;

  12. Driver needs ‘llseek()’ • ‘fileview.cpp’ checks for size of device-file • Standard C library function is ‘lseek()’: filesize = lseek( fd, 0, SEEK_END ); ‘fd’ is the file-descriptor for an opened file 0 is the ‘offset’ to seek to SEEK_END says offset is from end-of-file

  13. Default ‘llseek()’ won’t work • No way for kernel to know device’s filesize • So default ‘llseek()’ will give a wrong result • Driver must implement its own ‘llseek()’ • For ‘/dev/physmen’ with 1GB memory: FILESIZE = 0x38000000 • But more generally: FILESIZE = virt_to_phys( high_memory );

  14. Sample ‘llseek()’ in LDD text • ‘llseek()’ must handle three cases: #define SEEK_SET 0 #define SEEK_CUR 1 #define SEEK_END 2 (See author’s example-code on page 163)

  15. Prototype for ‘llseek()’ • Function has three arguments: struct file *filp; // pointer to file-structure loff_t offset; // file-offset to seek to int whence; // where to seek from • Return-value has type ‘loff_t’ (new offset)

  16. Algorithm for ‘llseek()’ • Step 1: Use ‘switch’ statement: switch( whence ) { case 0: // for SEEK_SET case 1: // for SEEK_CUR case 2: // for SEEK_END default: // should never happen! }

  17. Actions for ‘switch’ cases • case SEEK_SET: newpos = offset; break; • case SEEK_CUR: newpos = file->f_pos + offset; break; • case SEEK_SET: newpos = filesize + offset; break; • default: return -EINVAL;

  18. Algotithm (conclusion) • Step 2: Check for illegal ‘newpos’ value: if ( newpos < 0 ) return –EINVAL; • Step 3: Update ‘f_pos’ in file-structure: filp->f_pos = newpos; • Step 4: Return new file-pointer position: return newpos;

  19. ‘physmem’ is read-only • If device-file lacks ‘write’ permissions, then kernel won’t call driver’s ‘write()’ function • So omit write-function from device-driver in order to avoid having ‘dead code’

  20. Consider your legacy • Your driver-code may have a future life! • Another programmer could ‘inherit’ it • Or you, yourself, may want to ‘reuse’ it • Keeping ‘dead code’ will cause confusion • Omitting commentary will cause frustration • Need the author’s name (and contact-info) • Need code’s revision-history (when/why)

More Related