linux驱动开发入门与实战_ubuntu怎么编译[通俗易懂]

linux驱动开发入门与实战_ubuntu怎么编译[通俗易懂]Linux驱动的第一个程序:helloworld|内核编程part11.内容摘要前提条件helloworld程序如何编译一个modul加载和卸载一个模块2.前提条件2.1Kernelheaders当前内核的内核头文件:

linux驱动开发入门与实战_ubuntu怎么编译[通俗易懂]"

linux设备驱动:hello world | 内核编程 part 1 内核版本:5.12

1.内容摘要

  • 前提条件
  • hello world程序
  • 如何 编译 一个 modul
  • 加载和卸载一 个 模块

2.前提条件

2.1 Kernel headers

当前内核的内核头文件:通常,除非您已编译自己定制的内核,否则您将无法在系统上调用该 头文件

2.1.1获得头文件的两种方式
  • 编译 并安装 自己定制的内核:参考我上一篇帖子
  • 输入以下命令从 网上下载
# Arch, my fav :)
$ pacman -S linux-headers
# Debian & Ubuntu
$ apt-get install linux-headers-$(uname -r) 
  • 安装完 kernel 或从网上下载完成后 ,可以在此处找到头文件:
/usr/lib/modules/$(uname -r)/build/include/linux 

2.2 关于 editor

我个人推荐 virsual studio code,关于如何下载请参考我的另一篇博文

关于C拼写检查器,大多数编辑器都不会识别#include <linux / …>,所以我建议将Linux文件夹下的herder文件复制到开发目录中,从而使我们的编辑器的C拼写检查器对linux 中的header 也可以进行检查。

假设您在开发目录中,请输入以下命令,拷贝Linux文件夹下的herder到当前目录:

cp -r /usr/lib/modules/$(uname -r)/build/include/linux .

3.程序: hello world

#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("GPL");
static int hello_init(void){ 
   
    printk(KERN_ALERT "Hello, world\n");
    return 0;
}
static void hello_exit(void){ 
   
    printk(KERN_ALERT "Goodbye, cruel world\n");
}
module_init(hello_init);
module_exit(hello_exit);

要点:

  • 加载库init.hmodule.h。第一个提供初始化数据的宏,第二个定义函数module_init()module_exit()
  • MODULE_LICENSE(“ GPL”)基本上告诉内核该驱动程序已获得GPL许可。——> 无关紧要,加上即可
  • hello_init(void)kernel消息日志中以KERN_ALERT的级别输出“ Hello,world”(此级别设置得很严格,使其在日志中可见,而较低的级别可能会被忽略)
  • 调用hello_exit函数时 会以KERN_ALERT级别在 kernel 消息日志中记录Goodbye, cruel world
  • module_init()告诉内核在加载模块时要调用哪个函数。是的,您猜对了,它将是hello_init();)
  • module_exit()定义在删除模块时要调用哪个函数。它通常用于清理您在module_init()中所做的所有事情(释放在初始化分配的内存等等)

4.编译

不幸的是,编译内核模块并不像编译cpp程序那样容易。要编译内核模块,正确的方法是使用kbuild。但是,这可能会导致非常复杂的makefile,因此,处于简化的目的,我们将使用非常简化的makefile。

  • 第一步: create a Makefile(首字母大写)
code Makefile
  • 第二步: 手动输入 Makefile 内容
obj-m += myDriver.o
all:
	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
  • 第三步 编译 ,使用command: make
    • 编译结果
yaoxin@ubuntu:~/kernelDep/helloWorld$ make
make -C	 /lib/modules/5.12.0-rc7+/build M=/home/yaoxin/kernelDep/helloWorld modules
make[1]: Entering directory '/home/yaoxin/linux'
  CC [M]  /home/yaoxin/kernelDep/helloWorld/myDriver.o
  MODPOST /home/yaoxin/kernelDep/helloWorld/Module.symvers
  CC [M]  /home/yaoxin/kernelDep/helloWorld/myDriver.mod.o
  LD [M]  /home/yaoxin/kernelDep/helloWorld/myDriver.ko
make[1]: Leaving directory '/home/yaoxin/linux'

5.加载 卸载 该modul

5.1 加载 modul 可以使用的 工具

  • insmod: 加载 一个modul
  • rmmod: 卸载一个modul
  • modprobe: 加载一个modul

insmod和modprobe的异同:
The modprobe utility is worth a quick mention. modprobe, like insmod, loads a module into the kernel. It differs in that it will look at the module to be loaded to seewhether it references any symbols that are not currently defined in the kernel. If anysuch references are found, modprobe looks for other modules in the current modulesearch path that define the relevant symbols. When modprobe finds those modules(which are needed by the module being loaded), it loads them into the kernel as well.If you use insmod in this situation instead, the command fails with an “unresolvedsymbols” message left in the system logfile.

5.2 实践

  • 加载一个modul
sudo insmod myDriver.ko
  • 在 kernel log 最后中查看“Hello, world”
yaoxin@ubuntu:~/kernelDep/helloWorld$ sudo dmesg | tail
[ 4405.075417] e1000: ens33 NIC Link is Up 1000 Mbps Full Duplex, Flow Control: None
[ 4515.954117] e1000: ens33 NIC Link is Down
[ 4519.987707] e1000: ens33 NIC Link is Up 1000 Mbps Full Duplex, Flow Control: None
[ 4522.002993] e1000: ens33 NIC Link is Down
[ 4526.035896] e1000: ens33 NIC Link is Up 1000 Mbps Full Duplex, Flow Control: None
[10032.376776] psmouse serio1: VMMouse at isa0060/serio1/input0 lost synchronization, throwing 1 bytes away.
[10032.927991] psmouse serio1: resync failed, issuing reconnect request
[12254.950269] myDriver: loading out-of-tree module taints kernel.
[12254.950448] myDriver: module verification failed: signature and/or required key missing - tainting kernel
[12254.951248] Hello, world

dmesgshows the kernel log and since it is too big we filter it to show only the last 10 lines withtail.

  • 您还可以使用lsmod检查所有已经加载到kernel的模块,或者查看/ proc / modules目录下的内容
yaoxin@ubuntu:~/kernelDep/helloWorld$ lsmod
Module                  Size  Used by
myDriver               16384  0
algif_hash             16384  0
algif_skcipher         16384  0
af_alg                 28672  2 algif_hash,algif_skcipher
rfcomm                 81920  16
  • 卸载 modul
sudo rmmod myDriver
  • 在 kernel log 最后中查看“Goodbye, cruel world “
yaoxin@ubuntu:~/kernelDep/helloWorld$ sudo dmesg | tail
[ 4515.954117] e1000: ens33 NIC Link is Down
[ 4519.987707] e1000: ens33 NIC Link is Up 1000 Mbps Full Duplex, Flow Control: None
[ 4522.002993] e1000: ens33 NIC Link is Down
[ 4526.035896] e1000: ens33 NIC Link is Up 1000 Mbps Full Duplex, Flow Control: None
[10032.376776] psmouse serio1: VMMouse at isa0060/serio1/input0 lost synchronization, throwing 1 bytes away.
[10032.927991] psmouse serio1: resync failed, issuing reconnect request
[12254.950269] myDriver: loading out-of-tree module taints kernel.
[12254.950448] myDriver: module verification failed: signature and/or required key missing - tainting kernel
[12254.951248] Hello, world
[12363.751089] Goodbye, cruel world

6.最后

希望能帮助到大家,么么哒

今天的文章linux驱动开发入门与实战_ubuntu怎么编译[通俗易懂]分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/88665.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注