Отсутствует компонент в модуле ядра с несколькими исходными файлами - PullRequest
3 голосов
/ 20 сентября 2011

У меня был маленький модуль с одним исходным файлом C foo.c, и все было хорошо.

#include <linux/init.h>
#include <linux/module.h>
static int __init foo_init(void) {
        printk(KERN_INFO "foo_init says hello (%d)\n");
        return 0;
}
static void __exit foo_exit(void) {
}
module_init(foo_init);
module_exit(foo_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("ACME");

Makefile было просто:

obj-m += foo.o

Теперь, когда источник вырос, я хочу добавить второй исходный файл bar.c:

#include <linux/init.h>
#include <linux/module.h>
int aux(int x) {
        return x + 1;
}

Я добавил вызов функции aux в foo.c. (Ну, в реальной жизни я объявляю функцию aux в заголовке, и мой код делает больше, чем просто печатает сообщение, но я сократил мою проблему до этого небольшого примера.) И я добавил строку, чтобы объявить компоненты модуля в make-файле, следующие Documentation/kbuild/makefiles.txt.

foo-objs += bar.o
obj-m += foo.o

Но теперь, когда я собираю модуль, кажется, что foo.o не связан (modinfo сообщает об отсутствии лицензии на модуль и автора, nm foo.ko не находит символы, определенные в foo.c, foo_init очевидно не запускается при загрузке модуля). Помещение foo-objs := foo.o bar.o в make-файл не помогает.

Почему при добавлении второго исходного файла происходит смещение первого исходного файла и как мне вернуть foo обратно?

В случае, если это имеет значение: версия ядра 2.6.35, архитектура arm, а модуль встроен в дерево.

Ответы [ 2 ]

3 голосов
/ 20 сентября 2011

Чтобы получить вашу вещь для компиляции, я бы предложил переименовать foo.c, например. foo-base.c (идея заключается в том, чтобы не иметь файл .c с тем же именем, что и у модуля. foo-objs будет создавать foo.o из других указанных вами объектов, но не из foo.c ).

Тогда вы можете сделать:

foo-objs := foo-base.o bar.o
obj-m += foo.o

(foo-y := ... тоже работает, но файлы Makefile, на которые я смотрел, используют -objs версию.)
И это должно работать:

$ modprobe foo
$ dmesg|tail
...
[ 8375.303738] foo_init says hello (100)
$ modinfo foo
filename:       /lib/modules/3.0.3-gentoo/kernel/drivers/usb/test/foo.ko
author:         ACME
license:        GPL
depends:        
vermagic:       3.0.3-gentoo SMP mod_unload 

[то есть, после того, как вы дали достаточно аргументов printk в вашем примере: -)]

Примечание: не забудьте очистить все сгенерированные файлы перед перестройкой модуля после этого изменения.

0 голосов
/ 21 сентября 2011

Сокращение до небольшого примера - это 90% решения этой проблемы.Это позволило мне увидеть, что с foo-objs := foo.o bar.o в make-файле make жалуется:

make[1]: Circular z/foo.o <- z/foo.o dependency dropped.

Проблему труднее обнаружить с помощью foo-objs += bar.o, но она скрыта в выходных данных make V=1:

ld -EL    -r -o z/foo.o z/bar.o

То, что происходит под капотом, заключается в том, что $(module_name).o является частью цепочки сборки для $(module_name).ko.Каждый исходный файл %.c компилируется в %.o.Если есть исходный файл с тем же базовым именем, что и у модуля, то же имя файла имеет две цели, что приводит к хаосу.В особом случае, когда существует один исходный файл, $(module_name).o должен быть идентичен $(source_file).o в любом случае, поэтому цепочка сборки получается правильной.

Если модуль имеет более одного исходного файла,Имя модуля должно отличаться от имени любого исходного файла.

Я переименовал foo.c в foo_main.c и все хорошо.

...