![WSL 2에는 /lib/modules/가 없습니다.](https://linux55.com/image/175650/WSL%202%EC%97%90%EB%8A%94%20%2Flib%2Fmodules%2F%EA%B0%80%20%EC%97%86%EC%8A%B5%EB%8B%88%EB%8B%A4..png)
내 노트북의 Ubuntu 20에서 실행되는 hello world 커널 모듈의 소스 코드가 있습니다. 이제 Ubuntu 20과 WSL2에서 동일한 코드를 컴파일하려고 합니다. 이를 위해 나는 이것을 사용하고 있습니다 :
make -C /sys/modules/$(shell uname -r)/build M=$(PWD) modules
문제는 /lib/modules
그 자리가 비어 있다는 것이다. WSL2는 아무것도 가져오지 못하는 것 같습니다./lib/modules/4.19.104-microsoft-standard/build
나는 다음을 사용하여 제목을 얻으려고 노력합니다.
sudo apt search linux-headers-`uname -r`
Sorting... Done
Full Text Search... Done
하지만 모듈 폴더에는 아무것도 채워지지 않습니다.
폴더에 필요한 모든 모듈이 포함되도록 하려면 어떻게 해야 합니까?
[편집하다]
우리를 더 가깝게 해준 @HannahJ에게 감사드립니다.
내가 뭐하는 거지:
> sudo make -C /home/<user>/WSL2-Linux-Kernel M=$(pwd) modules
SL2-Linux-Kernel M=$(pwd) modules
make: Entering directory '/home/<user>/WSL2-Linux-Kernel'
CC [M] /home/<user>/containers-assembly-permissionsdemo/demo-2/lkm_example.o
Building modules, stage 2.
MODPOST 1 modules
CC /home/<user>/containers-assembly-permissionsdemo/demo-2/lkm_example.mod.o
LD [M] /home/<user>/containers-assembly-permissionsdemo/demo-2/lkm_example.ko
make: Leaving directory '/home/<user>/WSL2-Linux-Kernel'
드디어 lkm_example.ko
파일을 만들었습니다.
이후:
> sudo insmod lkm_example.ko
insmod: ERROR: could not insert module lkm_example.ko: Invalid module format
> dmesg
[200617.480635] lkm_example: no symbol version for module_layout
[200617.480656] lkm_example: loading out-of-tree module taints kernel.
[200617.481542] module: x86/modules: Skipping invalid relocation target, existing value is nonzero for type 1, loc 0000000074f1d70f, val ffffffffc0000158
> sudo modinfo lkm_example.ko
filename: /home/<user>/containers-assembly-permissionsdemo/demo-2/lkm_example.ko
version: 0.01
description: A simple example Linux module.
author: Carlos Garcia
license: GPL
srcversion: F8B272146BAA2381B6332DE
depends:
retpoline: Y
name: lkm_example
vermagic: 4.19.84-microsoft-standard+ SMP mod_unload modversions
이것은 내 Makefile입니다.
obj-m += lkm_example.o
all:
make -C /home/<usr>/WSL2-Linux-Kernel M=$(PWD) modules
clean:
make -C /home/<usr>/WSL2-Linux-Kernel M=$(PWD) clean
test:
# We put a — in front of the rmmod command to tell make to ignore
# an error in case the module isn’t loaded.
-sudo rmmod lkm_example
# Clear the kernel log without echo
sudo dmesg -C
# Insert the module
sudo insmod lkm_example.ko
# Display the kernel log
dmesg
unload:
sudo rm /dev/lkm_example
sudo rmmod lkm_example
[편집 2] 이것은 내 커널 모듈입니다.
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <linux/init_task.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Carlos Garcia");
MODULE_DESCRIPTION("A simple example Linux module.");
MODULE_VERSION("0.01");
/* Prototypes for device functions */
static int device_open(struct inode *, struct file *);
static int device_release(struct inode *, struct file *);
static ssize_t device_read(struct file *, char *, size_t, loff_t *);
static ssize_t device_write(struct file *, const char *, size_t, loff_t *);
static int major_num;
static int device_open_count = 0;
static char msg_buffer[MSG_BUFFER_LEN];
static char *msg_ptr;
/* This structure points to all of the device functions */
static struct file_operations file_ops = {
.read = device_read,
.write = device_write,
.open = device_open,
.release = device_release
};
/* When a process reads from our device, this gets called. */
static ssize_t device_read(struct file *flip, char *buffer, size_t len, loff_t *offset)
{
...
}
/* Called when a process tries to write to our device */
static ssize_t device_write(struct file *flip, const char *buffer, size_t len, loff_t *offset)
{
...
}
/* Called when a process opens our device */
static int device_open(struct inode *inode, struct file *file)
{
...
try_module_get(THIS_MODULE);
}
/* Called when a process closes our device */
static int device_release(struct inode *inode, struct file *file)
{
...
module_put(THIS_MODULE);
}
static int __init lkm_example_init(void)
{
...
major_num = register_chrdev(0, "lkm_example", &file_ops);
if (major_num < 0)
{
printk(KERN_ALERT "Could not register device: % d\n", major_num);
return major_num;
}
else
{
printk(KERN_INFO "lkm_example module loaded with device major number % d\n", major_num);
return 0;
}
}
static void __exit lkm_example_exit(void)
{
/* Remember — we have to clean up after ourselves. Unregister the character device. */
unregister_chrdev(major_num, DEVICE_NAME);
printk(KERN_INFO "Goodbye, World !\n");
}
/* Register module functions */
module_init(lkm_example_init);
module_exit(lkm_example_exit);
답변1
과제로 인해 이 작업을 수행해야 했기 때문에 여기서 솔루션을 공유해야겠다고 생각했습니다.
기본 WSL2 커널은 모듈 로드를 허용하지 않습니다. 자신의 커널 버전을 컴파일하고 사용해야 합니다.
WSL2에서 커널을 컴파일하고 사용하는 방법
우분투/WSL에서:
sudo apt install build-essential flex bison libssl-dev libelf-dev git dwarves git clone https://github.com/microsoft/WSL2-Linux-Kernel.git cd WSL2-Linux-Kernel cp Microsoft/config-wsl .config make -j $(expr $(nproc) - 1)
Windows에서
\\wsl$\<DISTRO>\home\<USER>\WSL2-Linux-Kernel\arch\x86\boot\bzimage
Windows 프로필에 복사합니다(%userprofile%
예C:\Users\<Windows_user>
: ).다음 내용으로 파일을 만듭니다
%userprofile%\.wslconfig
.[wsl2] kernel=C:\\Users\\WIN10_USER\\bzimage
참고: 이중 백슬래시(
\\
)가 필요합니다. 또한 잠재적인 오래된 오류를 방지하려면 어떤 줄에도 후행 공백을 남기지 않도록 하세요.PowerShell에서 다음을 실행합니다.
wsl --shutdown
WSL2 버전을 다시 시작하세요
모듈을 컴파일하는 방법
참고: Makefile에서 이러한 작업을 수행하거나 /home/$USER/
위치에 맞게 Makefile을 조정해야 합니다.
다음을 포함하는 파일을 만듭니다
Makefile
.obj-m:=lkm_example.o all: make -C $(shell pwd)/WSL2-Linux-Kernel M=$(shell pwd) modules clean: make -C $(shell pwd)/WSL2-Linux-Kernel M=$(shell pwd) clean
달리기
make
.wslconfig
파일 단계 소스여기.
답변2
Linux 버전 2용 Windows 하위 시스템은 컴파일된 모든 드라이버가 포함된 Microsoft의 사용자 지정 Linux 커널을 사용합니다. 모듈을 지원하지만 다음에서 얻을 수 있듯이 모듈이 포함되어 있지 않습니다.구성 파일. 따라서 /lib/modules
카탈로그를 보낼 이유가 없습니다 .
또한 WSL에 사용 가능한 대부분의 Linux 배포판에는 WSL 버전의 커널이 전혀 제공되지 않습니다. Microsoft가 자체 제품을 출시하기 때문에 이렇게 할 이유가 없습니다. 이러한 Linux 배포판은 Microsoft 커널용 빌드 패키지를 제공하지 않으며 이에 대한 책임은 Microsoft에서 제공하지 않으며 이러한 패키지에 대해 논의해야 합니다.
표준 도구를 사용하는 경우 모듈을 커널에 로드할 수 있지만 적절한 소스 트리에 대해 빌드해야 할 수도 있습니다. 위에 링크된 GitHub 저장소에서 적합한 버전을 찾으시거나 Microsoft에 연락하여 GPLv2에 따른 소스 코드를 요청해야 할 수도 있습니다. 요청 시 해당 소스 코드를 제공해야 합니다.
WSL은 사용자 정의 커널 모듈을 로드할 수 있도록 설계되지 않았으며, 완전한 Linux 환경이 아니라 사람들이 Windows에서 표준 Linux 애플리케이션을 개발하고 실행할 수 있도록 설계되었습니다. Linux 커널 개발을 수행하려면 전체 Linux 설치가 필요할 수 있습니다.
답변3
WSL2에서 모듈을 로드해야 하는 경우:
sudo -e /etc/modules-load.d/modules.conf
(또는 선호하는 편집기sudo
)- 로드하려는 커널 모듈의 이름을 모듈당 한 줄씩 추가합니다.
- WSL을 종료합니다.
- PowerShell 또는 CMD에서 실행합니다
wsl --shutdown
. - WSL을 다시 시작합니다. 모듈이 로드되어야 합니다.
WSL2 Ubuntu Focal에서 테스트되었습니다.
답변4
Yocto 빌드를 시도 중인데 Ubuntu 22.04에서는 기본적으로 잘 실행되지만 다음을 찾을 수 없기 때문에 WSL2에서는 실패합니다 /lib/modules/5.15.90.1-microsoft-standard-WSL2
.
murata-wireless/cyw-fmac - WSL2에서 빌드가 실패함
드디어 이걸 찾았어요해결책:
sudo apt-get install -y linux-headers-generic
ll /lib/modules
# Note the directory that has been installed here, e.g. `5.15.0-67-generic/
# Use "uname -r" or note the directory the build above failed to find, e.g. `/lib/modules/5.15.90.1-microsoft-standard-WSL2`
sudo ln -s /lib/modules/5.15.0-67-generic /lib/modules/5.15.90.1-microsoft-standard-WSL2
업데이트: WSL2 업데이트로 인해 디렉터리 이름이 변경될 수 있으므로 이 문제가 해결될 수 있습니다(예: 5.15.0-67-generic/에서 5.15.0-69-generic/). 이를 자동화하는 스크립트를 만들었습니다.
#!/bin/bash
set -e
WSL2_VERSION=$(uname -r)
echo "WSL2_VERSION = $WSL2_VERSION"
WSL2_LINK="/lib/modules/$WSL2_VERSION"
if [ -L "${WSL2_LINK}" ]; then
if [ -e "${WSL2_LINK}" ]; then
echo "Good link"
exit 0
else
echo "Broken link"
rm "${WSL2_LINK}"
fi
elif [ -e "${WSL2_LINK}" ]; then
echo "Not a link"
exit 1
else
echo "Missing"
fi
shopt -s nullglob
for filename in /lib/modules/*; do
echo "$filename"
if [ -z "$HEADERS_DIR" ]; then
HEADERS_DIR="$filename"
else
echo "HEADERS_DIR already set to $HEADERS_DIR, fail"
exit 1
fi
done
if [ -n "$HEADERS_DIR" ]; then
echo "Create symbolic link $WSL2_LINK => $HEADERS_DIR"
ln -s "$HEADERS_DIR" "$WSL2_LINK"
fi