Presentation is loading. Please wait.

Presentation is loading. Please wait.

Looking at kernel objects How a character-mode Linux device driver can be useful in viewing a ‘net_device’ structure.

Similar presentations


Presentation on theme: "Looking at kernel objects How a character-mode Linux device driver can be useful in viewing a ‘net_device’ structure."— Presentation transcript:

1 Looking at kernel objects How a character-mode Linux device driver can be useful in viewing a ‘net_device’ structure

2 Our ‘/proc/netdevs’ pseudo-file We wrote a Loadable Kernel Module that creates a pseudo-file allowing users to see some information about the kernel’s data lo struct net_device eth0 struct net_device eth1 struct net_device

3 The LKM’s source-code #include char modname[ ] = “netdevs”; … MODULE_LICENSE(“GPL”); netdevs.c module_init() module_exit() my_get_info() some header-files some global data this module’s ‘payload’ function required module administration functions

4 User-space/Kernel-space ‘cat’ application program open read write (etc) standard runtime library operating system kernel netdevs.ko installable module LINUX privilege barrier user-space (restricted privileges) kernel-space (unrestricted privileges)

5 Linux device drivers There is another kind of LKM, written to control the system’s hardware devices rather than merely to expose information Its code-structure will depend on the type of hardware device it is intended to control –‘character’ devices –‘block’ devices –‘network interface’ devices

6 Hardware’s operations In order to write the software that controls a particular device, the programmer needs to know details about its capabilities and about its mechanisms for being controlled This information is found in programming manuals, produced by the manufacturer These manuals may or not be available to the general public (often are ‘proprietary’)

7 A few devices are ‘simple’ If a particular device’s operations are very simple to understand, we may not need to consult the manufacturer’s documentation (just use ‘common sense’ and guesswork) EXAMPLE: The computer system’s main memory offers us an easy-to-understand hardware component for which we can directly write a device-driver module

8 ‘dram.c’ Two benefits of having a device-driver for the computer’s physical memory are: –We can directly look at kernel data-structures using ‘unprivileged’ application-programs –We get to see the general code-structure for Linux device-drivers in the simplest of cases

9 Using our ‘fileview’ utility Our previous ‘netdevs.c’ module tells us where the ‘struct net_device’ objects are located in our system’s physical memory So we can use ‘fileview’ to inspect these kernel data-structures once we’ve loaded our ‘dram.ko’ device-driver into the kernel Timeout for an in-class demonstration

10 The code-structure for ‘dram.c’ #include … char modname[ ] = “dram”; int my_major = 85; … MODULE_LICENSE(“GPL”); dram.c module_init() module_exit() my_read() some header-files some global data this module’s ‘payload’ (its ‘method’ functions and its ‘file_operations’ structure) required module administration functions my_llseek() my_fops

11 Kernel’s ‘helper-functions’ The Linux kernel provides quite a few aids to the authors of device-driver code: – ‘register_chrdev()’ and ‘unregister_chrdev()’ – ‘copy_to_user()’ and ‘copy_from_user()’ – ‘kmap()’ and ‘kunmap()’ The kernel also exports some of its ‘global variables’ (which drivers can reference): – ‘num_physpages’ and ‘mem_map[ ]’

12 Memory-mapping user space kernel space CPU’s virtual address-space HMA 896-MB physical RAM There is more physical RAM in our classroom’s systems than can be ‘mapped’ into the available address-range for kernel virtual addresses = persistent mapping = transient mappings

13 What does ‘kmap()’ do? The ‘kmap()’ helper-function allows your driver to create a temporary mapping for any one 4-KB ‘page’ of physical memory to some unused virtual address in kernel- space, then later ‘kunmap()’ lets your driver discard that mapping when it’s no longer needed (so there will be available that kernel-address for later reuse)

14 The ‘mem_map[ ]’ array The kernel creates an array of structures, named ‘mem_map[ ]’, whose entries hold detailed information about how each 4KB page of physical RAM is now being used The global variable named ‘phys_mem’ stores the total number of array-entries, and hence can be used by your driver to determine the amount of installed RAM

15 The function-prototypes void *kmap( struct page *page_ptr ); This function accepts a pointer to an entry of type ‘struct page’ in the kernel’s ‘mem_map[ ]’ array, and returns a kernel address where that page of physical RAM has been temporarily ‘mapped’ void kunmap( void *virt_addr ); This function accepts an address where the kernel temporarily has mapped a page of physical RAM and it deletes that mapping, thus freeing the address for reuse later when the kernel is asked to setup a different temporary mapping of physical RAM into kernel-space

16 Our driver ‘read()’ method… It has to support the traditional stream-of- bytes paradigm, so a ‘sanity check’ will be needed for the caller’s argument-values ssize_t my_read( struct file *file, char *buf, size_t count, loff_t *pos ); // There’s nothing to be ‘read’ beyond the end of physical RAM if ( *pos >= dram_size ) return 0; number of bytes that caller wants to read the current position of the file-pointer Physical RAM *pos dram_size

17 ‘read()’ method (continued) Our driver has to accommodate the CPU’s ‘page-granular’ memory-architecture, and the ‘kmap()’ function’s ability to map one- page-at-a-time *pos intpage_number = *pos / PAGE_SIZE; intpage_indent = *pos % PAGE_SIZE; if ( page_indent + count > PAGE_SIZE ) count = PAGE_SIZE – page_indent; struct page*pp = &mem_map[ page_number ]; void*from = kmap( pp ) + page_indent; intmore = copy_to_user( buf, from, count );

18 Another argument-value pitfall… It is possible that the caller did not supply a large-enough buffer for the amount of data that is supposed to be transferred That potential ‘buffer-overflow’ problem could be detected during execution of the ‘copy_to_user()’ helper-function, if fewer than ‘count’ bytes can be copied without triggering a ‘segmentation violation’

19 The driver’s solution… The ‘copy_to_user()’ function return the number of bytes that remain to be copied (normally this is zero: all copying got done) But if it’s NOT zero, the driver’s duty is to notify the user that a ‘segmentation fault’ error occurred – but AFTER ‘kunmap()’ intmore = copy_to_user( buf, from, count ); // first unmap the page, then notify the user if necessary kunmap( pp ); if ( more ) return –EFAULT;

20 The ‘llseek()’ method Our ‘dram.c’ driver needs to implement its own ‘llseek()’ function, in order to allow an application-program to ‘seek’ to the end of the device-file (so it will know what total amount of physical RAM is installed) This feature is used by our ‘fileview’ tool when a user hits the -key, and to display the total size for the device-file

21 ‘llseek()’ implementation unsigned intdram_size;// equals PAGE_SIZE * num_physpages loff_t my_llseek( struct file *file, loff_t offset, int whence ) { loff_tnewpos = -1; switch ( whence ) { case 0:newpos = offset; break; // SEEK_SET case 1:newpos = file->f_pos + offset; break; // SEEK_CUR case 2:newpos = dram_size + offset; break; // SEEK_END } if (( newpos dram_size )) return –EINVAL; file->f_pos = newpos; returnnewpos; }

22 Demo: ‘vwnetdev.cpp’ This application makes use of information from the ‘/proc/netdevs’ pseudo-file, plus the information that can be read from the computer’s physical memory using the capabilities implemented by our ‘dram.c’ device-driver It lets a user view the ‘struct net_device’ object for a specified network-interface

23 Our ‘offsets.c’ module This module creates a pseudo-file that can help a user to interpret the hexadecimal output produced by ‘vwnetdev’ It shows the locations within a ‘net_device’ structure for some structure-members of particular significance for network device drivers (which we shall explore next time)

24 In-class exercise #1 One of the ‘struct net_device’ fields that is significant in a Linux network device driver is the ‘get_stats’ function-pointer field Modify our ‘offsets.c’ module so that the pseudo-file this module creates will include the offset for the ‘get_stats’ member Turn in a printout of the enhanced output (created using our ‘ljpages’ printing tool); be sure your name is handwritten on it

25 In-class exercise #2 Take a look at our kernel’s definition for a ‘struct net_device’ object, in header-file: and identify three additional member-fields that you would like to show the offsets for Then implement the display of those three offsets (by adding code to our ‘offsets.c’)


Download ppt "Looking at kernel objects How a character-mode Linux device driver can be useful in viewing a ‘net_device’ structure."

Similar presentations


Ads by Google