Não foi possível carregar o módulo: discorda da versão do símbolo module_layout

12

Seguindo este tutorial para escrever meu primeiro driver.

O Makefile é:

# Makefile – makefile of our first driver

# if KERNELRELEASE is defined, we've been invoked from the
# kernel build system and can use its language.
ifneq (${KERNELRELEASE},)
    obj-m := ofd.o
# Otherwise we were called directly from the command line.
# Invoke the kernel build system.
else
    KERNEL_SOURCE := /usr/src/linux 3.8
    PWD := $(shell pwd)
default:
    ${MAKE} -C ${KERNEL_SOURCE} SUBDIRS=${PWD} modules

clean:
    ${MAKE} -C ${KERNEL_SOURCE} SUBDIRS=${PWD} clean
endif

E o código do driver é:

* ofd.c – Our First Driver code */
#include <linux/module.h>
#include <linux/version.h>
#include <linux/kernel.h>

static int __init ofd_init(void) /* Constructor */
{
    printk(KERN_INFO "Namaskar: ofd registered");
    return 0;
}

static void __exit ofd_exit(void) /* Destructor */
{
    printk(KERN_INFO "Alvida: ofd unregistered");
}

module_init(ofd_init);
module_exit(ofd_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Anil Kumar Pugalia <email_at_sarika-pugs_dot_com>");
MODULE_DESCRIPTION("Our First Driver");

Não há erro durante o make. Mas quando uso, insmod ofd.konão consigo carregá-lo. No dmesgque diz:

discorda da versão do símbolo module_layout

  • uname -r retorna '3.8.0-38-generic' e a fonte do kernel também 3.8.
  • modprobe -f ofd.ko também falha

Além disso:

#56~precise1-Ubuntu SMP Thu Mar 13 16:23:47 UTC 2014
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 12.04.4 LTS
Release:    12.04
Codename:   precise

O que está acontecendo?

user2799508
fonte
Alguns comentários óbvios. Primeiro, a fonte do kernel é exatamente igual à do Ubuntu? Você deve usar a fonte do kernel do Ubuntu correspondente exatamente ao seu kernel. O upstream provavelmente não funcionará, pois as distribuições corrigem seus kernels. Segundo, se você pode compilar com os cabeçalhos do kernel, não precisa da fonte do kernel. Os cabeçalhos também devem estar disponíveis como um pacote binário. Você também pode dar uma olhada no Debian Kernel Handbook , que contém informações instrutivas sobre kernels etc. no Debian, que também se aplica ao Ubuntu.
Faheem Mitha

Respostas:

13

O kernel do Linux contém estruturas de dados cujo layout varia não apenas de versão para versão, mas também dependendo das opções de compilação. Como conseqüência, ao compilar um módulo do kernel, você precisa ter não apenas os arquivos de cabeçalho da fonte do kernel, mas também alguns arquivos de cabeçalho que são gerados durante a compilação do kernel. Apenas descompactar a fonte do kernel não é suficiente.

Com os kernels criados com o CONFIG_MODVERSIONS, o número da versão pode ser diferente, mas o layout das estruturas de dados deve ser o mesmo. Esta opção é ativada nos kernels do Ubuntu. Com essa opção, além dos cabeçalhos, os módulos precisam ser compilados no Module.symversarquivo apropriado . O Ubuntu, como a maioria das distribuições, inclui esse arquivo no mesmo pacote que os cabeçalhos do kernel resultantes da compilação. O pacote de cabeçalho do kernel do Ubuntu é chamado , por exemplo .linux-headers-VERSION-VARIANTlinux-headers-3.8.0-38-generic

Com os kernels criados sem o CONFIG_MODVERSIONS(que pode ser o caso se você compilou seu próprio kernel), a verificação ao carregar um módulo é uma verificação simples da versão. Você pode pegar a fonte do kernel descompactado, copiar o .configque foi usado durante a compilação do kernel em execução e executar make modules_prepare. A responsabilidade é sua verificar se qualquer patch que você fez no kernel não afeta a compatibilidade binária.

Gilles 'SO- parar de ser mau'
fonte