Linux Device Drivers 3rd edition Reading Notes

Source: Internet
Author: User
Tags dmesg
Chapter 1 & 2: An Introduction to device driver & building and running modules
1. Concurrent, security -- module writting notes
2. Kernel stack is small, normally one page (4 K). So don't create a lot of local variables and don't have a long call stack.
3. kernel can't handle float pointing computing.
4. Compiling & Build:
OBJ-M: = module. o
Module-objs: = file1.o file2.o
Make-C ~ /Kernel-2.6 m = 'pwd' modules
5./proc/modules saves all modules load. lsmod uses this file as well.
Entries in/proc/modules contain the module name, the amount of memory each module occupies, and the usage count
6. Module codes will be linked with vermagic. O, this makes: When insmod, it checks the version in module codes and the version of current kernel, if mismatch, insmod failed.
7. use export_symbol/export_symbol_gpl, modules can export symbols to other module using. e. g: LP is the module we use, and the parport/parport_pc is the underlying modules. so, module symbol export can be used to define interfaces.
8. modprobe just search/lib/modules folder to find drivers, and insmod can be used to insert a module into kernel in the specified driver file path.
9. _ init & _ exit mocros. these are used to decorate the init & Exit functions. _ init tells kernel this is an init function and only be called when the module is loaded. after module loaded, the function will be dropped in kernel to save memory. _ Exit tells kernel this is the function which can only be called while module unloading. so, if you will call your cleanup functions in init function, don't add _ exit prefix in these cleanup function, because the function prefixed with _ exit can only be called when the module unloading.
10. Module Param: insmod xxx a = 1 B = 2
Module_param (howmany, Int, s_irugo );
Module_param_array (name, type, num, Perm); // array Param is allowed
The permission Param in module_param/module_param_array is used to tell kernel whether shoshould create an entry under/sys/module, and if shocould, the permission of this entry (file ). after that, changes to this entry can be got in module by module Param. but the module will be known about this automatically, We shoshould handle the module Param update ourselves.

========================================================== ========================================================== ============================
Chapter 3: Char drivers
1. major number -- related with one perticular driver. minor number -- kernel doesn't care about it, it means a lot for drivers. e. g: If a driver implements multiple device files, it can distinguish them by minor number.
2. mkdev macro to generate a dev_t structure. Major & minor macros can be used to check out the major & minor numbers in a dev_t structure.
3. alloc_chrdev_region -- request a major number from kernel and register it.
Register_chrdev_region -- regist a major number manually
Unregist_chrdev_region -- free the major number
/Proc/devices -- list devices and their major numbers. You can check this file to get a major number free to use
4. every file has a file structure in kernel (named "struct file "). there is a member named f_op in this structure which is the type of file_operations. driver shocould implement the function pointers in f_op. when the open system call called, the open function in kernel will be called first, then the function will call driver's open function pointer.
5. Lots of function pointers in f_op. refer to page 70 for details. Sample Code:
Struct file_operations scull_fops = {
. Owner = this_module,
. Llseek = scull_llseek,
. Read = scull_read,
. Write = scull_write,
. IOCTL = scull_ioctl,
. Open = scull_open,
. Release = scull_release,
6. inode. inode represents a file while "struct file" represents a FD. so a file can be opened multiple times which generates a lot of "struct file" s, but inode only has one for one file.
7. cdev_alloc/cdev_init/cdev_add -- register the char device driver.
8. kmalloc/kfree. kmalloc is not the good way to malloc a large area of memory.
9. Why the user space pointer shocould not be dereferenced directly? Here are the reasons:
(1) depending on which architecture your driver is running on, and how the kernel was configured, the user-space pointer may not be valid while running in kernel mode at all. there may be no mapping for that address, or it cocould point to some other, random data.
(2) even if the pointer does mean the same thing in kernel space, user-space mem-ory is paged, and the memory in question might not be resident in Ram when the system call is made. attempting to reference the user-Space Memory directly cocould generate a page fault, which is something that kernel code is not allowedto do. the result wocould be an "Oops," which wowould result in the death of the process that made the system call.
(3) the pointer in question has been supplied by a user program, which cocould be buggy or malicious. if your driver ever blindly dereferences a user-supplied pointer, it provides an open doorway allowing a user-space program to access or overwrite memory anywhere in the system. if you do not wish to be responsible for compromising the security of your users systems, you cannot ever derefer-ence a user-space pointer directly.
10. use copy_to_user & copy_from_user to access user space pointers. these functions act like memcpy with differences: (1) the memory pointed by user space pointer may be in swapped in disk right now, so these "memcpy" like functions will execute longer, so make sure your driver code is thread/process safe. (2) These functions check whether the user space pointer is valid.
11. Use "strace" to trace the system call -- Params and return values.

========================================================== ========================================================== ============================
Chapter 4: Debugging techniques
1. when config kernel, there is a "kernel Hacking" menu in it. all entries in it are about kernel debugging. e. g: Magic sysrq function/debug Slab (alloced memory will be set to 0xa5, after kfree, It will be set to 0xb6)/init debug... and etc.
2. Print debugging skills:
(1) printk prints information to the current console. This console can be a terminal of text, or a serial port or parallel printer. The requirement is that the priority of the current message is smaller than the console_loglevel. Remember: the end of the message of printk must be \ n. Otherwise, the message will not be printed.
(2) If both klogd and syslogd are running, the printk information will be stored in/var/log/messages. This is irrelevant to lele_loglevel. All messages are recorded in the file.
(3) If klogd is not running, read/proc/kmsg to view the information. The dmesg command also prints the information.
3. How to modify lele_loglevel? There are many methods:
(1) Call sys_syslog.
(2) Add-C option when klogd is started.
(3) Use a program for modification. No program is provided in this book. You can download it from ftp of oreilly.
(4) modify the file/proc/sys/kernel/printk. This file contains four items, which are described in the following section. You can directly set a value for this file, which indicates modifying the current loglevel.
4. How the printk texts can be displayed in a lot of places:
The printk function writes messages into a circular buffer that is _ log_buf_len bytes long: A value from 4 kb to 1 MB chosen While locking ing the kernel. the function then wakes any process that is waiting for messages, that is, any process that is sleep-ing in the syslog system call or that is reading/proc/kmsg.
5. About klogd & syslogd:
If klogd is started, klogd passes the message to Syslogd, and syslogd records the information into the file. Facility is the correspondence between log_kern, priority, and printk.
If klogd is not started, the message will not be read unless you use dmesg or read/proc/kmsg
If you do not like Syslogd, you can configure klogd to allow him to directly write information to the file. Or klogd is not started. As mentioned above, send the information to another dedicated console, or open a separate terminal to read/proc/kmsg.
6. driver can implement it's own/proc or/sys files to expose a lot of driver Internals to the user space. It's better than use printk heavily.
7. read_proc/create_proc_read_entry can be used to create & Response read proc files. But this read_proc just permit us to return one page data.
8. To avoid the one page issue in read_proc, seq_file interface comes up. Four function pointers shoshould be implemented:
Use create_proc_entry to create the proc file and associate with the four functions listed above.
Refer to page 109 for more details.
9. IOCTL is another way to debugging. No page limit. More generic than read_proc & seq_file interface.
10. Oops message reading. Refer to "Debug hacks" book.
11. Magic sysrq key. Refer to "Debug hacks" book.
12. Use GDB debug kernel: can only check variables, can't set breakpoints, change variables...
Config_debug_info selected when config Kernel
GDB/usr/src/Linux/vmlinux/proc/kcore -- vmlinux is not stripped/compressed Linux Kernel File. /proc/kcore like other proc entries, It outputs data when you read it automatically.
How to debug loadable module: (1) load the module (2) Check the/sys/module/<Module name>/sections to check out the Section Address (. text ,. BSS ,. data ...) (3) then use GDB "Add-symbol-file" command: Add-symbol-file... /scull. ko 0xd0832000-s. BSS 0xd0837100-s. data 0xd0836be0
13. KDB is not the official kernel builtin debugger. Is provided by, and now only IA-32 is supported. This is useless. Arm does not support it.
14. There are two patches for GDB, both of which are kgdb. After the patch, GDB can debug the kernel, set the breakpoint, and modify the data. The working mode is also different from the normal one. It is usually independent of DEBUG on one machine. The developers are on another machine. The two machines are connected by a serial port and then remotely debug.

========================================================== ========================================================== ============================
Chapter 5: concurrency and race conditions
1. sema_init -- semaphone init. semaphone has P, V functions.
2. declare_mutex/declare_mutex_locked -- declare a static mutex (actually it is a semaphone with value 1 ).
3. init_mutex/init_mutex_locked -- allocate a mutex at runtime
4. Down/down_interruptible/down_trylock -- down_interruptible can be cancalled, so check the return value of the function to see whether we got this semaphone or the down operation was cancalled.
5. Up-The semaphone V function
6. init_rwsem/down_read/down_read_trylock/up_read/down_write/down_write_trylock/up_write -- init a read/write semaphone. read/write semaphone allows multiple read operation at one time, but if has write operation, all read/write trying will be blocked. like windows 'srwlock. it can improve performances.
7. Completion -- like pthread condition. init_completion/declare_completion/wait_for_completion/complete/complete_all
8. spinlock-not waiting but always trying with a light loop. spin_lock_init/spin_lock/spin_unlock
Once the kernel code gets a spinlock, the preemption will be disable. The reason is as described above. If the thread that obtains the spinlock is preemptible at this time, other threads may wait for the spinlock for a long time or even long, if the preemptible thread cannot be executed. Unlike semaphore, if a thread cannot get semaphore, the thread will sleep. When a thread cannot get a spinlock, the thread will perform tight loop round robin, which consumes a lot of CPU and brings about a possibility: the chance of getting the CPU from the thread that gets the spinlock is greatly reduced.
Therefore, the kernel requires that the thread that uses the spinlock cannot perform any operation that may sleep after obtaining the spinlock. However, sleep has many operations, such as reading or writing content from userspace to userspace. The memory of userspace may be transferred to the disk by SWAP, so the disk thread may sleep until disk I/O ends; the memory allocated by kmalloc may also cause the thread to sleep, because when the memory is insufficient, kmalloc will wait.
Therefore, after getting the spinlock, you should be very careful when writing the code later.

Another common locking scenario: our thread gets a spinlock, which starts execution and is interrupted at the same time. In the Interrupt Processing code, you also need to obtain this spinlock, but this lock cannot be used, so spin. In this way, our thread will not be executed, and the spinlock will not be released, so it will be locked. Therefore, the second note of using the spinlock is as follows: after obtaining the spinlock, disable is interrupted. If the interrupt uses the same spinlock as ours.

Third Note: after obtaining the spinlock, the code execution time should be as short as possible and then be released.
9. Atomic operations. atomic_t type/atomic_add/atomic_inc/atomic_dec...
10. Read-copy-update operation.

========================================================== ========================================================== ============================
Chapter 6: Advanced char driver operations

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.