【问题标题】:Build static library and link it to kernel module at compile time构建静态库并在编译时将其链接到内核模块
【发布时间】:2021-03-20 20:07:18
【问题描述】:

我正在尝试构建一个纯 C 代码(无标准 c 头文件)的静态 -helper- 库,然后在 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.autils.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: please compile with -fno-common

我尝试将ccflags-y += -fno-common 添加到Makefile,但仍然出现同样的错误。

我已经读到可以做到这一点,但我无法让它发挥作用。

我在这里要做的是不分发 utils 源代码,只分发内核模块代码以及 utils 和库对象文件的标头。我该怎么办?

【问题讨论】:

  • 最后一个 makefile 将工作委托给另一个我们看不到的 makefile。您是否尝试过制作另一个 makefile 的本地副本,并将整个问题简化为 minimal complete example
  • 使用标准方式构建模块。许多模块有两个或多个要链接的文件。内核构建系统很复杂。主 Makefile 将执行另一个 make(其中将包含其他路径),因此您的示例无法运行,您处于错误的进程中。
  • 尝试搜索 SO 来寻找答案。在过去的几年里,我看到过两三个这样的问题。是有可能实现的。通常的问题是如何形成一个Makefile。寻找如何将静态对象链接到内核模块类型的问题。
  • @Beta 我认为另一个 Makefile 是内核中 Kbuild 的一部分。
  • @GiacomoCatenazzi 你能提供一个链接来指导我想要实现的目标吗?

标签: c makefile linux-kernel kernel-module static-linking


【解决方案1】:

内核模块只能通过 syscalls 或 sysfs 或 ioctl 访问,....您不能将用户空间代码链接到内核,参见。 How to Link static or shared library to Kernel Module?

【讨论】:

  • 您似乎没有得到 OP 的要求。
  • 我认为您的意思是 _shipped 机制,您将二进制 blob 链接到内核模块中,如 kernel.org/doc/html/latest/kbuild/modules.html#binary-blobs 以及此链接的第 3.2 章,但我认为这里不需要这样做
  • @ralfhtp 我在这里有点困惑。我想要做的是,将我的部分代码(不依赖任何用户空间 API)编译成一个静态库(binray blob?),然后我可以将其包含在我的实际内核模块的 Makefile 中以解决我在内核模块代码中使用的依赖项/符号。如果这有任何意义。
  • 据我所知,这只有在您的库不依赖于其他任何东西(不依赖外部符号)(即其他库)时才有可能。任何事物的这种独立性将使您的库成为二进制 blob。这包括不允许您的库依赖 libc ,...如果您的库具有其他用户空间依赖项,则不可能像 stackoverflow.com/questions/20487512/…stackoverflow.com/questions/31928255/… 中所说的那样
  • @ralfhtp 是的,我正在尝试创建一个不依赖任何东西的库。您是否碰巧知道如何编写实现此目的的 Makefile?上面的 Makefile 不起作用。
猜你喜欢
  • 2015-12-16
  • 2013-12-27
  • 2011-06-03
  • 1970-01-01
  • 2011-01-10
  • 1970-01-01
  • 2018-09-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多