我正在尝试构建一个纯 C 代码(无标准 c 头文件)的静态辅助库,然后在编译时在 Makefile 中将其与内核模块链接,但我似乎无法让它工作.
假设我有一个库,它就是这个头文件 utils.h
:
#ifndef __UTILS__
#define __UTILS__
int initialize(int value);
void increment(void);
int get(void);
#endif // __UTILS__
及其实现utils.c
:
#include "utils.h"
int g_value;
int initialize(int value) {
g_value = value;
return 0;
}
void increment(void) {
g_value++;
}
int get(void) {
return g_value;
}
我正在使用这个 Makefile
从中构建库:
BIN_DIR := .
# Specify extensions of files to delete when cleaning
CLEANEXTS = o a
# Specify the target file and the install directory
OUTPUTFILE = libutils.a
INSTALLDIR = ../
# Default target
.PHONY: all
all: $(OUTPUTFILE)
# Build libutils.a from uilts.o
$(OUTPUTFILE): utils.o
ar cr $@ $^
ranlib $@
# No rule to build utils.o from .c
# files is required; this is handled by make's database of
# implicit rules
.PHONY: install
install:
mkdir -p $(INSTALLDIR)
cp -p $(OUTPUTFILE) $(INSTALLDIR)
.PHONY: clean
clean:
for file in $(CLEANEXTS); do rm -f *.$$file; done
# Indicate dependencies of .c files on .h files
utils.o: utils.h
我运行 make all
来构建库,我得到了 libutils.a
和 utils.o
文件。
然后我有一个简单的内核模块,它使用 utils 库 mymodule_main.c
#include <linux/kernel.h>
#include <linux/module.h>
MODULE_LICENSE("GPL");
#include "utils/utils.h"
int init_module(void) {
int i;
initialize(1);
for(i = 0; i < 10; ++i) {
increment();
}
return 0;
}
void cleanup_module(void)
{
pr_info("value=%d\n", get());
}
和它的Makefile
:
NAME := mymodule
target := $(shell uname -r)
KERNEL_DIR ?= /lib/modules/$(target)/build
obj-m := $(NAME).o
$(NAME)-y := mymodule_main.o libutils.a
all:
make -C $(KERNEL_DIR) M=$(shell pwd)
clean:
make -C $(KERNEL_DIR) M=$(shell pwd) clean
现在当我尝试构建这个内核模块时 make all
我得到了这些错误:
ERROR: "initialize" [/home/mosa/dev/mymodule.ko] undefined!
ERROR: "get" [/home/mosa/dev/mymodule.ko] undefined!
ERROR: "increment" [/home/mosa/dev/mymodule.ko] undefined!
然后我尝试使用 utils.o
文件代替 libutils.a
并相应地更新了内核模块的 Makefile
,我收到这些警告:
WARNING: "g_value" [/home/mosa/dev/mymodule] is COMMON symbol
WARNING: could not find /home/mosa/dev/.utils.o.cmd for /home/mosa/dev/utils.o
如果我尝试 insmod
生成的内核模块,我会在日志中收到此错误:
mymodule: 请使用-fno-common 编译
我尝试将 ccflags-y += -fno-common
添加到 Makefile
中,但仍然出现同样的错误。
我读到过可以这样做,但我无法让它工作。
我在这里要做的是不分发实用程序源代码,只分发内核模块代码以及实用程序的 header 和库目标文件。我该怎么办?
最佳答案
内核模块只能通过 syscalls 或 sysfs 或 ioctl 访问,....你不能将用户空间代码链接到内核,cf。 How to Link static or shared library to Kernel Module?
关于c - 构建静态库并在编译时将其链接到内核模块,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65216947/