Linux中编写了内核模块的C源程序之后怎么编写makefile文件的内容??

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux中编写了内核模块的C源程序之后怎么编写makefile文件的内容??相关的知识,希望对你有一定的参考价值。

实验源代码如下:
//my_proc.c
#include<linux/module.h>
#include<linux/kernel.h>
#include<linux/proc_fs.h>
#include<linux/sched.h>
#include<linux.uaccess.h>
#define STRINGLEN 1024

char global_buffer[STRINGLEN];
struct proc_dir_entry *example_dir,*Tang_file,*Yang_file,*symlink;

int proc_read_Tang(char *page,char **start,off_t off,int count,int *eof,void *data)
//用户读取Tang文件时,内核调用这个函数
int len;
try_module_get(THIS_MODULE);//模块引用计数器
len=printf(page,"Tang message:\nname: %s\npid: %d\n",current->comm,current->pid);

module_put(THISMODULE);
return len;


int proc_read_Yang(char *page,char **start,off_t off,int count,int *eof,void *data)
//用户读取Yu文件时,内核调用这个函数
int len;
try_module_get(THIS_MODULE);

len=printf(page,"Yang message:\n%s write: %s\n",current->comm,global_buffer);

module_put(THISMODULE);
return len;


int proc_write_Yang(struct file *file, const char *buffer, unsigned long count, void *data)
//用户读写数据入Yang文件时,内核调用这个函数
int len;
try_module_get(THIS_MODULE);

if(count>=STRINGLEN)
len=STRINGLEN-1;
else
len=count;
copy_from_user(global_buffer,buffer,len);
global_buffer[len]='\0';

module_put(THISMODULE);
return len;


int init_module()
//初始化函数

example_dir=proc_mkdir("13081175",NULL);
example_dir->owner=THIS_MODULE;

Tang_file=create_proc_read_entry("Tang",0444,example_dir,proc_rea d_current,NULL);
Tang_file->read_proc=proc_read_Tang;
Tang_file->owner=THIS_MODULE;

Yang_file=create_proc_entry("Yang",0666,example);
strcpy(global_buffer,"Tang");
Yang_file->read_proc=proc_read_Yang;
Yang_file->write_proc=proc_write_Yang;
Yang_file->owner=THIS_MOUDLE;

return 0;


void cleanup_module()
//卸载函数
remove_proc_entry("Yang",example_dir);
remove_proc_entry("Tang",example_dir);
remove_proc_entry("21",NULL);



编写Makefile文件,内容如下:
obj-m := my_proc.o
KERNELBUILD :=/lib/modules/$(shell uname -r)/build
default:
make -C $(KERNELBUILD) M=$(shell pwd) modules
clean:
rm -rf *.o *.ko *.mod.c .*.cmd *.markers *.order *.symvers .tmp_versions

make命令执行时,需要一个 Makefile 文件,以告诉make命令需要怎么样的去编译和链接程序。

首先,我们用一个示例来说明Makefile的书写规则。以便给大家一个感兴认识。这个示例来源于GNU的make使用手册,在这个示例中,我们的工程有8个C文件,和3个头文件,我们要写一个Makefile来告诉make命令如何编译和链接这几个文件。我们的规则是:
1)如果这个工程没有编译过,那么我们的所有C文件都要编译并被链接。
2)如果这个工程的某几个C文件被修改,那么我们只编译被修改的C文件,并链接目标程序。
3)如果这个工程的头文件被改变了,那么我们需要编译引用了这几个头文件的C文件,并链接目标程序。

只要我们的Makefile写得够好,所有的这一切,我们只用一个make命令就可以完成,make命令会自动智能地根据当前的文件修改的情况来确定哪些文件需要重编译,从而自己编译所需要的文件和链接目标程序。

一、Makefile的规则

在讲述这个Makefile之前,还是让我们先来粗略地看一看Makefile的规则。

target ... : prerequisites ...
command
...
...

target也就是一个目标文件,可以是Object File,也可以是执行文件。还可以是一个标签(Label),对于标签这种特性,在后续的“伪目标”章节中会有叙述。

prerequisites就是,要生成那个target所需要的文件或是目标。

command也就是make需要执行的命令。(任意的Shell命令)


是一个文件的依赖关系,也就是说,target这一个或多个的目标文件依赖于prerequisites中的文件,其生成规则定义在command中。说
白一点就是说,prerequisites中如果有一个以上的文件比target文件要新的话,command所定义的命令就会被执行。这就是
Makefile的规则。也就是Makefile中最核心的内容。

说到底,Makefile的东西就是这样一点,好像我的这篇文档也该结束了。呵呵。还不尽然,这是Makefile的主线和核心,但要写好一个Makefile还不够,我会以后面一点一点地结合我的工作经验给你慢慢到来。内容还多着呢。:)

二、一个示例

正如前面所说的,如果一个工程有3个头文件,和8个C文件,我们为了完成前面所述的那三个规则,我们的Makefile应该是下面的这个样子的。

edit : main.o kbd.o command.o display.o /
insert.o search.o files.o utils.o
cc -o edit main.o kbd.o command.o display.o /
insert.o search.o files.o utils.o

main.o : main.c defs.h
cc -c main.c
kbd.o : kbd.c defs.h command.h
cc -c kbd.c
command.o : command.c defs.h command.h
cc -c command.c
display.o : display.c defs.h buffer.h
cc -c display.c
insert.o : insert.c defs.h buffer.h
cc -c insert.c
search.o : search.c defs.h buffer.h
cc -c search.c
files.o : files.c defs.h buffer.h command.h
cc -c files.c
utils.o : utils.c defs.h
cc -c utils.c
clean :
rm edit main.o kbd.o command.o display.o /
insert.o search.o files.o utils.o


斜杠(/)是换行符的意思。这样比较便于Makefile的易读。我们可以把这个内容保存在文件为“Makefile”或“makefile”的文件中,
然后在该目录下直接输入命令“make”就可以生成执行文件edit。如果要删除执行文件和所有的中间目标文件,那么,只要简单地执行一下“make
clean”就可以了。

在这个makefile中,目标文件(target)包含:执行文件edit和中间目标文件(*.o),依赖文件
(prerequisites)就是冒号后面的那些 .c 文件和 .h文件。每一个 .o 文件都有一组依赖文件,而这些 .o 文件又是执行文件
edit 的依赖文件。依赖关系的实质上就是说明了目标文件是由哪些文件生成的,换言之,目标文件是哪些文件更新的。

在定义好依赖关系
后,后续的那一行定义了如何生成目标文件的操作系统命令,一定要以一个Tab键作为开头。记住,make并不管命令是怎么工作的,他只管执行所定义的命
令。make会比较targets文件和prerequisites文件的修改日期,如果prerequisites文件的日期要比targets文件的
日期要新,或者target不存在的话,那么,make就会执行后续定义的命令。

这里要说明一点的是,clean不是一个文件,它只不过
是一个动作名字,有点像C语言中的lable一样,其冒号后什么也没有,那么,make就不会自动去找文件的依赖性,也就不会自动执行其后所定义的命令。
要执行其后的命令,就要在make命令后明显得指出这个lable的名字。这样的方法非常有用,我们可以在一个makefile中定义不用的编译或是和编
译无关的命令,比如程序的打包,程序的备份,等等。
参考技术A linux内核的源代码都在

的/pub/linux目录下

软件的源代码在该一般项目主页或发行版的“源”,或其他开源软件的网站

参考技术B TARGET?=此处填c源程序名称,不要后缀
KDIR?=此处填你的内核路径
PWD:=$(shell pwd)
ifneq ($(KERNELRELEASE),)
obj-$(CONFIG_TEST01) += $(TARGET).o
else
default:
make -C $(KDIR) M=$(PWD) modules
clean:
rm -rf $(shell ls --hide=$(TARGET).c --hide=Makefile) .*.cmd .tmp*
endif
参考技术C linux内核的源代码都在

的/pub/linux目录下

软件的源代码在该一般项目主页或发行版的“源”,或其他开源软件的网站
参考技术D obj-m := my_proc.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) clean

不过我觉得你那个没错,可能你有写东西木有安装

为 Linux VM 编写内核模块

【中文标题】为 Linux VM 编写内核模块【英文标题】:Write a Kernel-Modul for Linux VM 【发布时间】:2022-01-06 05:48:50 【问题描述】:

这是我第一次在这里写问题,所以如果信息丢失或我写错了格式,我提前道歉。我目前正在参加一个系统课程,我们正在使用 Ubuntu VM 学习“基本”Linux 指令和命令/编程。我们目前的项目是编写自己的 Kernel-Modul 并安装在 Linux 中。不幸的是它是德语的,但会发布整个内容并尽我所能翻译。

Bauen Sie ihr eigenes Kernel-Modul mod_kmalloc.ko。 Hierzu müssen Sie ein eigenes C-File anbieten und den Makefile anpassen。 Ihr Modul soll den Parameter „loop_cnt“ nehmen, der angibt wie häufig Speicher der Größe „alloc_size“ (ein weiterer Parameter) allokiert werden soll。 Diese Speicherallokation messen Sie mittels des 时间戳计数器 mittels der Instruktion „rdtsc“ (auf Intel x86 / AMD64) bzw。 mit hrtimers (ARM) und geben das auf der Kernel-Console mittels printk() aus

我们应该构建自己的 Kernel-Modul 并将其命名为 mod_kmalloc.ko。然后我们使用 loop_cnt 参数,它告诉我们使用 alloc_size 分配内存的频率,使用另一个参数,以及应该多久分配一次。为了测量我们需要使用 rdtsc 命令的数量,然后通过 printk() 命令/函数将所有内容发送到控制台。

根据我目前所学和理解的内容,我制作了一个“正确”的 Makefile。

obj-m = mod_kmalloc.o

KVERSION = $(shell uname -r)

modules all:
    make -C /lib/modules/$(KVERSION)/build M=$(PWD) modules
clean:
    make -C /lib/modules/$(KVERSION)/build M=$(PWD) clean

让我困惑的是 C-File 应该如何/有什么,以及如何安装新的 Modul/Kernal 并使其运行。 遗憾的是,我仍然对 Linux 了解不多,完全不知道第一步应该是什么。我知道我需要使用类似的东西

uint64_t rdtsc()
    return __rdtsc();

但除此之外,我完全不知所措。

【问题讨论】:

这会有帮助吗? Hello world kernel module. 另一个灵感 ;) github.com/ngtkt0909/linux-kernel-module-template 【参考方案1】:

我不会为你的练习提供答案,但我可以为你提供解决问题所需的信息:

参数

你的内核模块需要定义2个参数(loop_cnt, alloc_size),这可以使用module_param() macro来完成。

结构

你的模块需要声明一个 init 和 exit 方法,看看下面的Hello World example 对内核模块的结构有一个基本的了解。

使用 kmalloc 分配内存

练习表明你应该分配loop_cnt 乘以alloc_size 大小的内存。为此,请在循环中使用kmalloc(alloc_size, GFP_KERNEL) 方法并分配通过参数传递的大小。 此外,您应该在模块的退出方法中释放分配的空间(请参阅kfree)。

测量时钟周期

使用rdtsc 方法将返回自上次处理器复位以来的时钟周期数。如果您在每次调用kmalloc 之前和之后调用rdtsc 并将返回的值保存在两个变量中,您可以减去两个值,例如使用printk 打印它。

使用内核模块

确保您的 Makefile 和 C-File 在同一目录中。 要构建您的模块,只需在此目录中运行命令 make。 要将模块插入内核,您需要运行insmod 命令。 此外,您需要将模块参数传递给此命令,例如sudo insmod mod_kmalloc.ko loop_cnt=3 alloc_size=3. 现在您可以检查是否添加了模块:lsmod | grep mod_kmallloc. 您可以使用以下命令检查输出:dmesg | tail. 要删除模块,您可以致电sudo rmmod mod_kmalloc

【讨论】:

以上是关于Linux中编写了内核模块的C源程序之后怎么编写makefile文件的内容??的主要内容,如果未能解决你的问题,请参考以下文章

Linux下makefile文件的编写问题!

linux中用C语言编写完模块后怎么编写makefile文件?用到啥命令?以啥格式编写?

编写简单Linux内核模块

Linux 内核模块开发怎么进行单元测试

编写简单的内核模块

i.MX6ULL驱动开发 | 01-Linux内核模块的编写与使用