编写一个简单的linux模块 hello

今天看着《Linux设备驱动程序》,跟着编写一个简单的hello模块:

hello.c

#include <linux/init.h>
#include <linux/module.h>

MODULE_LICENSE("Dual BSD/GPL");

static int hello_init(void)
{
	printk(KERN_INFO "Hello, world\n");
	return 0;
}

static void hello_exit(void)
{
	printk(KERN_INFO "Goodbye, cruel world\n");
}

module_init(hello_init);
module_exit(hello_exit);

Makefile:(取自 https://www.cnblogs.com/mrzhangxinjie/p/7170736.html

obj-m :=hello.o                     //目标文件
#module-objs := file1.o file.o      //当模块有多个文件组成时,添加本句
KDIR :=/usr/src/linux               //内核路径,根据实际情况换成自己的内核路径,嵌入式的换成嵌入式,PC机的指定PC机路径
PWD := $(shell pwd)                 //模块源文件路径
all:     
    $(MAKE)  -C  $(KDIR)  SUBDIRS=$(PWD)  modules 
    @rm -rf *.mod.* 
    @rm -rf .*.cmd 
    @rm -rf *.o 
    @rm -rf Module.* 
clean: 
    rm -rf *.ko 

结果make编译出现错误;

Makefile:7: *** commands commence before first target。 停止。
Makefile:7: *** 遗漏分隔符 。 停止。

查找原因,发现是因为复制的原因, 第一个错误是make行开头不是tab,第二个错误是其他行开头不是tab,改成tab后:

obj-m :=hello.o                     //目标文件
#module-objs := file1.o file.o      //当模块有多个文件组成时,添加本句
KDIR :=/usr/src/linux               //内核路径,根据实际情况换成自己的内核路径,嵌入式的换成嵌入式,PC机的指定PC机路径
PWD := $(shell pwd)                 //模块源文件路径
all:     
	$(MAKE)  -C  $(KDIR)  SUBDIRS=$(PWD)  modules
	@rm -rf *.mod.* 
	@rm -rf .*.cmd 
	@rm -rf *.o 
	@rm -rf Module.* 
clean: 
	rm -rf *.ko 

再次make,依然有错误:

make  -C  /usr/src/linux               //内核路径,根据实际情况换成自己的内核路径,嵌入式的换成嵌入式,PC机的指定PC机路径  SUBDIRS=/home/zhangjian/huangzhe/linux_drive/misc-modules                 //模块源文件路径  modules
make: *** /usr/src/linux: 没有那个文件或目录。 停止。
make: *** [all] 错误 2

原来是没有更改内核路径(参考https://www.jianshu.com/p/62eff1275b77):

obj-m :=hello.o                     //目标文件
#module-objs := file1.o file.o      //当模块有多个文件组成时,添加本句
KDIR :=/lib/modules/`uname -r`/build  //内核路径,根据实际情况换成自己的内核路径,嵌入式的换成嵌入式,PC机的指定PC机路径
PWD := $(shell pwd)                 //模块源文件路径
all:     
	$(MAKE)  -C  $(KDIR)  SUBDIRS=$(PWD)  modules
	@rm -rf *.mod.* 
	@rm -rf .*.cmd 
	@rm -rf *.o 
	@rm -rf Module.* 
clean: 
	rm -rf *.ko 

再次make,仍有问题,继续查找原因,发现注释符不对,shell中应该用#:

obj-m :=hello.o                     #目标文件
#module-objs := file1.o file.o      #当模块有多个文件组成时,添加本句
KDIR :=/lib/modules/`uname -r`/build               #内核路径,根据实际情况换成自己的内核路径,嵌入式的换成嵌入式,PC机的指定PC机路径
PWD := $(shell pwd)                 #模块源文件路径
all:     
	$(MAKE)  -C  $(KDIR)  SUBDIRS=$(PWD)  modules
	@rm -rf *.mod.* 
	@rm -rf .*.cmd 
	@rm -rf *.o 
	@rm -rf Module.* 
clean: 
	rm -rf *.ko 

再次make,成功编译出hello.ko模块!

VirtualBox:~/linux_drive/misc-modules$ ls
complete.c  hello.ko  jit.c         Makefile         modules.order  sleepy.c
faulty.c    hellop.c  kdataalign.c  Makefile1        seq.c
hello.c     jiq.c     kdatasize.c   Makefile (复件)  silly.c

执行 sudo insmod hello.ko 安装hello模块:

sudo insmod hello.ko

执行lsmod命令查看模块是否安装成功:

VirtualBox:~/linux_drive/misc-modules$ lsmod
Module                  Size  Used by
hello                  16384  0 
nls_utf8               16384  1 
isofs                  40960  1 
vboxsf                 40960  1 

执行 sudo rmsmod hello 卸载hello模块:

sudo rmmod hello

再次执行lsmod命令查看模块是否卸载成功:

VirtualBox:~/linux_drive/misc-modules$ lsmod
Module                  Size  Used by
nls_utf8               16384  1 
isofs                  40960  1 
vboxsf                 40960  1 
bnep                   20480  2 

在安装卸载模块期间,发现没有打印信息,查阅资料(https://blog.csdn.net/FallingU/article/details/76166194

查看内核打印信息需要用到dmesg命令:

VirtualBox:~/linux_drive/misc-modules$ dmesg
/太多,省略/
[ 6162.325693] Hello, world
[ 6164.141443] Goodbye, cruel world

模块的编译有两种形式,一种是编译成模块,即上面的obj-m,另一中是直接编译到内核文件中,则上面的obj-m需要更改为obj-y(https://www.jianshu.com/p/62eff1275b77

 

 

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值