Hello everyone , From this chapter , I will teach you how to learn Linux drive , There is expected to be 20 The first part is about the knowledge of driving . This topic will be updated all the time , Have any questions , You can leave a message or add my wechat .

What is modular programming ?

Linux The developer of the , All over the world , They probably don't know each other . If it's really a unified management of these developers , That's hard to do . So Daniel , In the design Linux Kernel time , With the idea of modularity . in other words , Now you have a ready-made Linux The operating system , All the code that developers write for this Linux Operating system is a module , Developers can add their own code to the kernel in the form of modules , You can also uninstall your own modules from the operating system . This idea , It is especially useful in practical development .

for example : You've run a mature Limux operating system , Due to the changing needs of customers , You need to add some features to this operating system . Now you have two approaches :

The first one is : get Linux Source code , And then modify , Add functionality , It looks like a cow , But if you don't write code that works all at once , You have to modify , So you have to recompile the kernel every time , Is it too much trouble . The most terrible thing is that you are not careful , It's wrong to modify the kernel source code , What should we do then ?

The second kind : Write your own function code quickly , And then add it as a module to Linux Operating system , Then test , I can't find out , Unloading module , Continue to modify the code , Add modules ( Gao Fu Shuai's way of working ),.. Is it easier than forcing programmers to use the first method !
What you need to pay attention to , In general, we use a modular approach to Linux The operating system adds drivers , those Linux The core code , Personally, I don't think many people feel bad , Need to revise .

Linux The kernel module is mainly composed of the following parts :

  1. Module loading function ( must ): When passed insmod Command to load the kernel module , The module's load functions are automatically executed by the kernel , Complete the initialization of this module ;
    Module unload function ( must ): When passed rmmod Command to unload the module , The module's unload function is automatically executed by the kernel , Complete the function opposite to the module loading function ;
    Module license statement ( must ): Module license (LICENCE) The declaration describes the permissions of the kernel module , If you don't declare LICENCE, When a module is loaded, it will receive a kernel contamination warning . majority
    Module parameters ( Optional ): Module parameters are values that can be passed to a module when it is loaded , It itself corresponds to the global variables inside the module ;
    Module export symbol ( Optional ): Kernel modules can export symbols (symbol, Corresponding to a function or variable ), In this way, other modules can use the variables or functions in this module ;
    Module author, etc ( Optional ).

Two 、 Modular programming

Look directly at the code ,no code no bb!
 Insert picture description here

After reading the code above , Please believe that , You've got a basic understanding of modular programming . The above code is very simple , But he contains Linux All the information needed for kernel modular programming .
Let's summarize Linux The necessary steps of kernel modular programming :

First step :

   contain linux/init.h and inux/module.h These two header files ;

adopt MODULE LICENSE(“GPL”), Tell the kernel that your modules comply with "GPL" agreement , This has to be done . If you don't know GPL The readers of the book go to find the relevant materials themselves ;Linux One of the key factors to success is to follow GPL, It's out of control , Spread all over the world .
MODULE_AUTHOR(“yikoulinux”) Used to specify the author of the module , Don't write .

The second step :

Write functional code , Notice that there is no main function , This is called the entry function of the module , Function names are usually called “xxx_init”, This is called "hello_init". The name must be better , You can use the module's entry function as your main Two numbers , This is where your code starts !

When will this function be called ?
After the module is loaded into Linux Kernel time ,Linux The kernel calls the exit function of this function module , This function is usually called “xxx_exit”, This is called “hello_exit”. In this function , We usually release resources . When the module is unloaded, it will be called to . When a module is unloaded , We must release the resources it takes , Otherwise, resources will be wasted .

The third step :

Tell the kernel , Your module in and out .Linux The kernel provides two macros , Namely :module_init and module_exit.

Now let's talk about it in detail printk function .

3、 ... and 、Linux Kernel print functions printk

printk Usage and printf similar ,print For user space ,printk For kernel space . use printk Function time , According to the log level, the kernel , It's possible to print messages to the current console , This console is usually a character mode terminal 、 A serial printer or a parallel printer .
The premise of normal output of these messages is : The log output level is less than console_loglevel( In the kernel, the smaller the number, the higher the priority ).
There are a total of 8 A level ,printk The log level of is defined as follows ( stay include/linux/kern_levels.h in );

#define KERN_EMERG KERN_SOH "0" /* system is unusable */#define KERN_ALERT KERN_SOH "1" /* action must be taken immediately */#define KERN_CRIT KERN_SOH "2" /* critical conditions */#define KERN_ERR KERN_SOH "3" /* error conditions */#define KERN_WARNING KERN_SOH "4" /* warning conditions */#define KERN_NOTICE KERN_SOH "5" /* normal but significant condition */#define KERN_INFO KERN_SOH "6" /* informational */#define KERN_DEBUG KERN_SOH "7" /* debug-level messages */#define KERN_DEFAULT KERN_SOH "d" /* the default kernel loglevel */

There is no log level specified printk The default level of the statement is DEFAULT_MESSAGE_LOGLEVEL( The default level is generally <4>, I.e KERN_WARNING On one level ).
We can go through cat/proc/sys/kemel/printk This file , View the system default log level  Insert picture description here

printk, It's not that complicated , You think of it as printf It's OK to use it , We can't test it here yet printk Output message , Can I get to the console , Because we don't know how to compile our module code 、 How to load our module 、 How to uninstall our module .
good , So let's see , How to compile our modules .

Four 、 Module compilation

here , Given first Linux Modular compilation process :
 Insert picture description here

Module compilation is divided into two steps :
First step : call linux Source tree Makefile Collect the information needed to compile a module
The second step :linux Source tree Makefile After collecting the information , Call the Makefile. Get the “.c” file , Finally, the module file is generated

Understand the module compilation process , Next, let's see how to write the module Makefile

# KERNELRELEASE : In the kernel source tree Makefile In the definition of , In the current Makefile in , Its value is empty
#$(shell uname-r) : Get when the system Linux Kernel version #KDIR      : Set the current Linux Operating system source code path , That is to say, the compiled module is used in the current system
# If you want to put your module , Run on your development board Linux In the system ,
Just in KDIR Variable to specify your development board Linux System source tree path #PWD:=$(shell pwd) Get the current path 

 Insert picture description here

Let's analyze Makefile Implementation process of

  1. Execute in the source code directory of the module make, here , macro “KERNELRELEASE”【 Kernel source tree Makefile Will define 】 No definition , So enter else;

  2. Record the kernel path KDIR And the current working directory PWD;
     Insert picture description here

  3. because make There's no target in the back , therefore make Will be in Makefile The first one in is not to . The initial target is executed as the default target , therefore all Become make The goal of ;
    all: The first order of
     Insert picture description here

Be similar to printf function , After compiling, a prompt message will be printed here .

  1. make The second order of will be executed make -C                             (                         K                         D                         I                         R                         )                         M                         =                            (KDIR) M=                 (KDIR)M=(PWD) modules
    Translation is :
make -C /lib/modules/3.2.0-29-generic-pae/build M=/home/peng/driver/1/module modules-C  Indicates that the kernel is executed in the directory where it is stored Makefile,
M=$(PWD) Returns to the current directory ,
modules To compile into a module 

It's written at the top of the kernel source tree Makefile Tell us , When we call Linux At the top of the kernel source tree Makefile when , It's the top floor Makefile Of “modules” The goal is . Let's take a look at the top floor Makefile Of modules What does the goal say :

 Insert picture description here

【 Intercepted part of the content , We don't need to know all about it , Just care about the red part , Especially the corresponding English notes 】

  1. find modules After the goal , Next Linux The top level of the source tree Makeflle You need to know what's going on ".c" Files are compiled into modules . Who told it ? Yes , Modular Makefile file . So the next step is to call back the module Makefile. It should be noted that , here KERNELRELEASE Already in Linux The top level of the kernel source tree Makefile It's defined , So the information it gets at this point is :
    obj-m:=hello.o
    obj-m Indicates that it will hello.o The target is compiled into .ko modular ; It tells linux The top level of the source tree Makefile Is dynamic compilation ( Compile into modules ) Instead of compiling into the kernel (obj-y),linux The top level of the source tree Makefile Will be based on hello.o find hello.c file

  2. Put the module file hello.c Compiled into .o, Then link multiple targets to .ko.

The final compilation result is as follows :
 Insert picture description here

According to the execution results ,Makefile It was eventually called three times
1) Carry out orders make call
2) By linux The top level of the kernel source tree Makefile call , produce .o file
3) By linux The top level of the source tree Makefile call , take .o File link generation .ko file

5、 ... and 、 Module loading 、 uninstall

How to add a compiled module to Linux kernel ? How to go from Linux The kernel unloads our modules ?
1. Module load command

insmod xxx.ko

for example : stay ubuntu Add your own module to the system

sudo insmod hello.ko

Be careful : stay Linux Only super user can add modules to the kernel .
2. View the module commands in the system

lsmod

for example : Search the system for the ones you added hello modular

sudo lsmod | grep hello

3. Unload module command

sudo rmmod  Module name 

for example : Uninstall... From the system hello modular

sudo mmod hello

4. View load module and unload module through printk Printed information commands

dmesg or dmesg|tail

This order is mainly from Linux Kernel ring buffer( Ring buffer ) Reading information in .

What is ring buffer Well ?
stay Limux In the system , All through printk The printed information will be sent to ring buffer in . We know , The information we print out needs to be displayed on the console device . stay Linux When the kernel is initialized , When the console device is not initialized , Use printk Will there be a problem
Console devices , Because at this time printk It's just sending information to ring buffer in , After the console device is initialized , On the basis of ring buffer The priority of the message in determines whether it needs to be delivered to the console device .

How to empty ring buffer Well ?

 sudo dmesg -c

The results are as follows :
 Insert picture description here

All operations are in privileged mode , If you add... In front of ordinary user permissions sudo.