कर्नेल को फिर से लोड किए बिना एक लोड करने योग्य कर्नेल मॉड्यूल को कैसे संकलित करें


20

मैंने रास्पबेरी पाई पर (और के लिए) कर्नेल मॉड्यूल को संकलित करने के तरीके के बारे में काफी कुछ पढ़ा है, लेकिन मैं अभी भी यह पता लगाने में सक्षम नहीं हूं कि यह काम क्यों नहीं कर रहा है। मैं मॉड्यूल का निर्माण करने में सक्षम रहा हूं, लेकिन Invalid module formatजब मैं insmodपरिणाम की कोशिश करता हूं तो यह रिपोर्ट करता है। यहाँ प्रक्रिया है जिसका मैंने अनुसरण किया है। पहले, रूट के तहत /rootमैंने निम्नलिखित शेल स्क्रिप्ट निष्पादित की:

getKernel.sh

#! /usr/bin/bash
FIRMWARE_HASH=$(zgrep "* firmware as of" /usr/share/doc/raspberrypi-bootloader/changelog.Debian.gz | head -1 | awk '{ print $5 }')
KERNEL_HASH=$(wget https://raw.githubusercontent.com/raspberrypi/firmware/$FIRMWARE_HASH/extra/git_hash -O -)
git clone https://github.com/raspberrypi/linux 
cd linux
git checkout $KERNEL_HASH
wget https://raw.githubusercontent.com/raspberrypi/firmware/$FIRMWARE_HASH/extra/Module.symvers 
zcat /proc/config.gz >.config
make oldconfig
make modules_prepare
ln -s /root/linux /lib/modules/$(uname -r)/build 

पहली कुछ पंक्तियाँ http://lostindetails.com/blog/post/Compiling-a-kernel-module-for-the-raspberry-pi-2 से हैं

बाकी मैंने इस प्रक्रिया को और अधिक स्वचालित करने के लिए लिखा था। एक बार जब यह सब सफलतापूर्वक हो जाता है, तो मेरे पास स्रोत है जो चलने वाले कर्नेल, मिलान के लिए कॉन्फ़िगरेशन और एक सिम्लिंक से बिल्कुल मेल खाना चाहिए। जीथब वेब स्थान से कुछ रीडायरेक्ट थे (जाहिरा तौर पर अब यह https://raw.githubusercontent.com/ ) है, लेकिन वास्तविक वास्तविक त्रुटियां हैं।

तब मैं डिफ़ॉल्ट piउपयोगकर्ता बन जाता हूं और एक निर्देशिका में जिसका नाम है /home/pi/projects/lkmमेरे पास एक बहुत ही सरल खिलौना मॉड्यूल के लिए यह स्रोत कोड है:

नमस्ते सी

#include <linux/init.h>  
#include <linux/kernel.h> 
#include <linux/module.h>

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Do-nothing test driver");
MODULE_VERSION("0.1");

static int __init hello_init(void){
   printk(KERN_INFO "Hello, world.\n");
   return 0;
}

static void __exit hello_exit(void){
   printk(KERN_INFO "Goodbye, world.\n");
}

module_init(hello_init);
module_exit(hello_exit);

अंत में, मैं इस मेकफाइल के साथ मॉड्यूल का निर्माण करता हूं

makefile

MODSRC=/home/pi/projects/lkm
obj-m+=hello.o

all:
    make -C /lib/modules/$(shell uname -r)/build M=${MODSRC} modules

clean:
    make -C /lib/modules/$(shell uname -r)/build M=${MODSRC} clean

अंत में, मैं मॉड्यूल को लोड करने का प्रयास करता हूं:

sudo insmod hello.ko

हालांकि, परिणाम निराशाजनक है:

insmod: ERROR: मॉड्यूल को सम्मिलित नहीं कर सका। हैलो: अमान्य मॉड्यूल प्रारूप

संभवतः प्रासंगिक विवरण

मैं वर्तमान में jessieएक रास्पबेरी Pi2 पर रास्पियन के नवीनतम संस्करण का उपयोग कर रहा हूं ।

$ uname --kernel-release --kernel-version
4.1.13-v7+ #826 SMP PREEMPT Fri Nov 13 20:19:03 GMT 2015
$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/arm-linux-gnueabihf/4.9/lto-wrapper
Target: arm-linux-gnueabihf
Configured with: ../src/configure -v --with-pkgversion='Raspbian 4.9.2-10' --with-bugurl=file:///usr/share/doc/gcc-4.9/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.9 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.9 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-libitm --disable-libquadmath --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.9-armhf/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.9-armhf --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.9-armhf --with-arch-directory=arm --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-sjlj-exceptions --with-arch=armv6 --with-fpu=vfp --with-float=hard --enable-checking=release --build=arm-linux-gnueabihf --host=arm-linux-gnueabihf --target=arm-linux-gnueabihf
Thread model: posix
gcc version 4.9.2 (Raspbian 4.9.2-10) 

दुर्भाग्य से, मुझे यकीन नहीं है कि इसे आगे कैसे ठीक किया जाए या इसे ठीक किया जाए। कोई सुराग?


मैंने अपने सभी निष्कर्षों और अनुभवों को एक स्क्रिप्ट में संकलित किया है, देखें github.com/x29a/kernel/blob/master/rpi/prepare.sh और संबंधित ब्लॉगपोस्ट blog.chris007.de/…
x2929

जवाबों:


23

सबसे पहले, सुनिश्चित करें कि आप उचित कर्नेल हेडर का उपयोग करते हैं। मुझे लगता है कि आपके कर्नेल हेडर और स्रोत कोड आपके द्वारा चलाए जा रहे कर्नेल से अधिक अपडेट हैं।

apt-get update && apt-get upgradeमॉड्यूल को फिर से स्थापित करने की कोशिश करें । यदि समस्या बनी रहती है, तो जाँच लें कि आपके कर्नेल हेडर आपके वर्तमान कर्नेल से मेल खाते हैं, फिर से पुन: स्थापित करें और फिर इंस्टॉल करने का प्रयास करें।


नोट: मैं जेसी का उपयोग कर रहा हूं।

अद्यतन करें: इन्हें रूट के रूप में चलाएँ।

# The usual update routine
apt-get update -y
apt-get upgrade -y

# Update the kernel!
rpi-update

आपको रिबूट करने की आवश्यकता हो सकती है। उसके बाद, नीचे दिए गए कमांड के साथ आगे बढ़ें, फिर भी रूट अकाउंट का उपयोग करें।

# Get rpi-source
sudo wget https://raw.githubusercontent.com/notro/rpi-source/master/rpi-source -O /usr/bin/rpi-source

# Make it executable
sudo chmod +x /usr/bin/rpi-source

# Tell the update mechanism that this is the latest version of the script
/usr/bin/rpi-source -q --tag-update

# Get the kernel files thingies.
rpi-source

यदि rpi-sourceकोई GCC त्रुटि (एक संस्करण बेमेल के बारे में कुछ) फेंकता है, तो यह तब तक ठीक है जब तक आपका वर्तमान GCC संस्करण अधिक है । के rpi-source --skip-gccबजाय भागोrpi-source

फिर, अपने हैलो वर्ल्ड उदाहरण के साथ आगे बढ़ें। फोल्डर बनाएं और cdउसमें। फिर, फ़ाइलें बनाएँ।

mkdir hello
cd hello

फ़ाइलें:

नमस्ते सी

#include <linux/module.h>
#include <linux/kernel.h>

int hello_init(void)
{
    pr_alert("Hello World :)\n");
    return 0;
}
void hello_exit(void)
{
    pr_alert("Goodbye World!\n");
}
module_init(hello_init);
module_exit(hello_exit);

मेकफाइल (केस-संवेदी?)

obj-m := hello.o

अब जब आपके पास आपकी फाइलें हैं, तो आप आगे बढ़ सकते हैं और सामान्य हैलो वर्ल्ड बिल्ड कमांड चला सकते हैं:

make -C /lib/modules/$(uname -r)/build M=$(pwd) modules
insmod hello.ko

अब आपको जांच करनी चाहिए dmesg। अंतिम पंक्ति को Hello World :)लाल रंग में हाइलाइट किया गया प्रिंट होना चाहिए ।

यदि आप करते हैं, बधाई। आपने अभी कर्नेल मॉड्यूल बनाया और स्थापित किया है।

अब इसका उपयोग करके हटा दें rmmod hellodmesgअब Goodbye World!लाल रंग में हाइलाइट होना चाहिए ।

स्रोत: 1 2 3


जब आप कहते हैं कि "जाँच लें कि आपके कर्नेल हेडर आपके वर्तमान कर्नेल से मेल खाते हैं" तो आप वास्तव में कैसे मतलब है कि मुझे ऐसा करना चाहिए?
एडवर्ड

@ एडवर्ड अपडेट किया गया।
PNDA

@ एडवर्ड टेक ध्यान दें कि यह हैलो वर्ल्ड उदाहरण है। मैंने आपका मॉड्यूल बनाया, लेकिन मुझे एहसास हुआ कि यह वही है। अंतर केवल इतना है कि आपके कोड में लाल हाइलाइट नहीं है।
PNDA

@Edward आपके मामले में, मुझे लगता है कि जब तक rpi-sourceभाग पर्याप्त नहीं है तब तक निर्देशों का पालन करें । आप उस बिंदु से अपना निर्माण करने की कोशिश कर सकते हैं।
पीएनडीए

5

यहाँ बहुत सरल संस्करण है, जेसी और स्ट्रेच पर परीक्षण किया गया है ।

sudo apt-get install raspberrypi-kernel-headers

और तब जब आपकी फाइलें जागी हों:

make -C /lib/modules/$(uname -r)/build M=$(pwd) modules

उदाहरण

helloनिर्देशिका बनाएँ , अंदर जाएँ और निम्न फ़ाइलें बनाएँ: hello.cऔर Makefile

मैं सलाह देते हैं अपने सामान्य उपयोगकर्ता, के रूप में काम नहीं जड़ , केवल insmod, rmmodहै, और make modules_installआदेशों जड़ अनुमति की आवश्यकता है, और आवश्यक sudoनिम्न कमांड में दिखाया गया है।


hello.c (अपरिवर्तित, आपकी फ़ाइल)

#include <linux/init.h>  
#include <linux/kernel.h> 
#include <linux/module.h>

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Do-nothing test driver");
MODULE_VERSION("0.1");

static int __init hello_init(void){
   printk(KERN_INFO "Hello, world.\n");
   return 0;
}

static void __exit hello_exit(void){
   printk(KERN_INFO "Goodbye, world.\n");
}

module_init(hello_init);
module_exit(hello_exit);

मेकफाइल (परिवर्तित)

obj-m+=hello.o

all:
    make -C /lib/modules/$(shell uname -r)/build M=$(pwd) modules

clean:
    make -C /lib/modules/$(shell uname -r)/build M=$(pwd) clean

modules_install: all
    $(MAKE) -C $(KERNEL_SRC) M=$(SRC) modules_install
    $(DEPMOD)   

प्रयोग

  • बिल्ड: make(मेकफाइल के समान निर्देशिका में)
  • परीक्षा
    • मॉड्यूल के साथ डालें sudo insmod hello.ko
    • Hello World :)के आउटपुट में खोजेंdmesg
    • साथ मॉड्यूल निकालें sudo rmmod hello
    • Goodbye, world.के आउटपुट का पता लगाएंdmesg
  • स्थापित करें, जब आपका मॉड्यूल काम कर रहा हो, sudo make modules_installतो उस मॉड्यूल को स्थापित करें जहां वह है, इसलिए modprobeकाम करेगा।

1
'रास्पबेरी-कर्नेल' पैकेज के माध्यम से स्थापित गुठली के लिए बहुत अच्छी तरह से काम करता है। इसके विपरीत 'pandalion98' द्वारा जारी विवरण 'रपी-अपडेट' के माध्यम से स्थापित गुठली को संदर्भित करता है। दोनों विधियाँ परस्पर अनन्य हैं?
स्पार्क

1
मुझे लगता है कि यह एक वैध जवाब है क्योंकि ओपी (एडवर्ड) के बारे में कभी बात नहीं की गई थी rpi-update, rpi-updateपंडालियन98 के जवाब में सुझाव दिया गया था
pim

@sparkie पोस्टिंग के समय, कर्नेल अभी भी रास्पियन की aptरिपॉजिटरी में एकीकृत नहीं था , अगर मैं गलत नहीं हूँ। कर्नेल को अद्यतन करने का अर्थ है Hexxeh की rpi-updateस्क्रिप्ट को चलाना । इन दिनों, अद्यतन raspberrypi-kernelया चल रहा rpi-updateहै एक ही बात बहुत ज्यादा है।
पीएनडीए

के रूप में raspberrypi-kernel-headers, यह आमतौर पर बेमेल कर्नेल हेडर स्थापित करता है, अनुभव से (हेडर कर्नेल की तुलना में एक नया संस्करण है), इसलिए मैंने "मैनुअल" जाने का विकल्प चुना।
पीएनडीए

'रास्पबेरी-कर्नेल' और 'आरपीआई-अपडेट' के बीच कुछ अंतर प्रतीत होता है: एक का परिणाम '4.9.66+' और दूसरे का इस समय '4.9.59+' में होता है। इसलिए मुझे लगता है कि हमें अभी भी दोनों निर्माण प्रक्रियाओं को अलग से संभालना है
स्पार्कली

2

में getKernel.shफ़ाइल जोड़ने

sudo modprobe configs

से पहले

zcat /proc/config.gz >.config

(अब डिफ़ॉल्ट rpi छवि /proc/config.gz में मौजूद नहीं है)

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.