One: mechanism and strategy (turn)
Http://www.51hei.com/bbs/dpj-29441-1.html
Mechanism mechanism, strategy policy. If you've seen Linux device drivers, here's an overview. What the mechanism provides (do-what), and how the policy provides (how-to-do). The driver completes the function of the mechanism, leaving the implementation of the policy to the user's application.
usually in the mechanism, the driver must complete the functions of opening, closing, reading and writing, controlling and so on. These are the most basic operations when the device is used. In the strategy, some advanced data processing or interface functions should be realized. It would be better to illustrate by example. Take the RTC (real-time clock device) as an example. Assume that RTC has 8 Reg, which are 2 control registers, year register, Month register, day register, time register, Sub register, second register. The start and shutdown of the RTC is done by setting a bit of the control register, respectively. 1. The driver provides the Open,release,write,read function. Open and release not much to say, specifically about the read and write features. The value of these 8 registers can be read through the IO port operation in read, and the value of these 8 registers can be written through the IO port operation in write. Just like this, the driver has provided the application with all the interfaces that complete the access to the RTC device. This may not be convenient for the application to operate RTC, so we provide a library of user functions for the RTC when we release the driver. such as Setdate,settime, these functions are nothing more than the driver in the read and write combinations are called. But with this strategy, it is easier for users to write applications, and it is not necessary to know much about the underlying details. 2. Another alternative mechanism is to introduce the IOCTL function in the driver, which implements the function of the setdate,settime operation in the IOCTL function. The IOCTL accesses 8 registers via an IO port operation to complete. You do not have to provide a library of user functions when a driver is released. Just tell the developer the operation code of the IOCTL function, and use different IOCTL calls to complete the Setdate,settime function. it can be seen from the above two cases that the mechanism provides different policy choices, and the mechanism can integrate some functions in the strategy. But how do you choose the right combination of mechanisms and strategies? for the above 2 mechanisms provided, analysis of their advantages and disadvantages:in the first scenario, because the IOCTL function is not provided, the driver inevitably consumes less memory. And for RTC devices, we don't often go to setdate,settime, so the small probability of using the function in the user library is better. The second program, do not provide user function library, publishing convenience. But the IOCTL function will reside in memory, although he may not have been called! This approach is more consistent with the idea of object-oriented programming.
--------------------------------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------------------------------- ---------------
Two: User space and kernel space
a single module running in kernel space while the application is running in user space. This concept is the basis of operating system theory,
The driver module involves the kernel state and the user state, when the application issues a systerm call or is suspended by the hardware interrupt, the kernel executes systerm calls in context, memory of the kernel and the application map is different, so
The memory space of the kernel and the memory space of the application are not accessible to each other, copy_to_user and copy_from_user functions are used;
The biggest difference between a kernel program and an application is that the kernel is concurrent and the application executes sequentially, so the application does not have to worry about switching the text on the line, and the kernel has to do a context switch.
After the 2.6 kernel, the kernel is preemptive, which must require that the kernel code be re-entered
The kernel stack is very small, the kernel is a 4k stack, so when large structures are needed, heap memory is used; Kzalloc
The function in the code of the driver module and the data structure are closely connected with the kernel version, so we should choose the correct kernel version when compiling the module, and select the correct kernel version when installing the module.
If
2.6 Preliminary knowledge
#include <linux/module.h> contains a large number of modules to load unloaded header files such as Module_init, Module_exit and other functions
#include <linux/init.h> Specifies the initialization function of the cleanup, init function
Module_license ("GPL"); Specific licenses recognized by the kernel, "GPL" (for any version of the GNU general Public License),
Module_author (declares who wrote the module),
Module_descripion (a person-readable statement about what the module does),
Module_version (A code revision number
Module_alias (module known as another name)
As well as module_device_table (to inform the user of space, the module supports those devices).
2.7 Error Handling in initialization
This is important, such as when you insmodu a module when the load fails, if the code of the driver module is not related to error handling, there will be more problems loading
Error recovery is best to use goto statement;
1 int__init My_init_function (void)2 {3 interr;4Err = Register_this (PTR1,"Skull");/*registration takes a pointer and a name*/5 if(ERR)6 GotoFail_this;7Err = Register_that (PTR2,"Skull");8 if(ERR)9 GotoFail_that;TenErr = Register_those (PTR3,"Skull"); One if(ERR) A GotoFail_those; - return 0;/*Success*/ - Fail_those: theUnregister_that (PTR2,"Skull"); - Fail_that: -Unregister_this (PTR1,"Skull"); - Fail_this: + returnErr/*Propagate the error*/ -}
Or you can simply execute your cleanup function at the time of failure, but it requires more context switching, consumes more memory space, registers, and so on, or one of the following functions;
Check the status of each operation, in the cleanup, but the downside of this is the need to define a lot of song variables, or goto better;
1 structSomething *item1;2 structSomethingElse *item2;3 intStuff_ok;4 voidMy_cleanup (void)5 {6 if(item1)7 release_thing (item1);8 if(ITEM2)9 release_thing2 (item2);Ten if(STUFF_OK) One Unregister_stuff (); A return; -}
1 int__init My_init (void)2 {3 intErr =-Enomem;4Item1 =allocate_thing (arguments);5ITEM2 =allocate_thing2 (arguments2);6 if(!ITEM2 | |!item2)7 Gotofail;8Err =Register_stuff (item1, item2);9 if(!err)TenSTUFF_OK =1; One Else A Gotofail; - return 0;/*Success*/ - fail: the My_cleanup (); - returnerr; -}
Linux Device Driver3 reading notes (i)