카테고리

asm (27) bootloader_x86_grub (1) C (92) compile (11) config (76) CPP (13) CSS (1) debugging (7) gimp (1) Go (1) html (1) Java (1) JavaScript (1) kernel (19) LibreOffice (3) Linux system progamming (21) MFC (1) opencv (4) OpenGL (1) PHP (1) Python (4) qemu (29) shell (3) socket (7) troubleshooting (2) ubuntu18.04 (2) windows (1)

2019/11/28

우분투 13.04 저정소 설정.

deb http://www.mirrorservice.org/sites/packages.linuxmint.com/packages/ olivia main upstream import

deb http://old-releases.ubuntu.com/ubuntu/  raring main restricted universe multiverse
deb http://old-releases.ubuntu.com/ubuntu/ raring-updates main restricted universe multiverse

deb http://old-releases.ubuntu.com/ubuntu/ raring-security main restricted universe multiverse
deb http://archive.canonical.com/ubuntu/ raring partner

2019/11/27

Nvidia 드라이버 및 CUDA 삭제

Ndivia driver
sudo apt-get remove --purge '^nvidia-.*'

CUDA
sudo apt-get --purge remove 'cuda*'
sudo apt-get autoremove --purge 'cuda*'

CUDA 파일 삭제
sudo rm -rf /usr/local/cuda
or
sudo rm -rf /usr/local/cuda-10.0

ubuntu 18.04 gcc 버전별 설치

GCC (GNU Compiler Collection)는 C, C ++, Objective-C, Fortran, Ada, Go 및 D 프로그래밍 언어를 위한 컴파일러 및 라이브러리의 모음이댜.

GNU 도구 및 Linux 커널을 포함한 많은 오픈 소스 프로젝트는 GCC로 컴파일된다.

Ubuntu 18.04에 GCC 컴파일러를 설치하는 데 필요한 단계를 보여준다.
배포판 안정 버전과 최신 버전의 GCC를 설치하는 방법들이다.

저장소 업데이트
sudo apt update
sudo apt install build-essential

맨페이지 설치.
sudo apt-get install manpages-dev

버전 확인.
gcc --version

다수의 GCC 버전 설치

저장소 등록
sudo apt install software-properties-common
sudo add-apt-repository ppa:ubuntu-toolchain-r/test

gcc 설치
sudo apt install gcc-7 g++-7 gcc-8 g++-8 gcc-9 g++-9

각 버전에 대한 우선순위 지정.
기본으로 설정하면 우선 순위가 가장 높다.

sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-9 90 --slave /usr/bin/g++ g++ /usr/bin/g++-9 --slave /usr/bin/gcov gcov /usr/bin/gcov-9
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-8 80 --slave /usr/bin/g++ g++ /usr/bin/g++-8 --slave /usr/bin/gcov gcov /usr/bin/gcov-8
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-7 70 --slave /usr/bin/g++ g++ /usr/bin/g++-7 --slave /usr/bin/gcov gcov /usr/bin/gcov-7

본 버전을 변경
sudo update-alternatives --config gcc

There are 3 choices for the alternative gcc (providing /usr/bin/gcc).

  Selection    Path            Priority   Status
------------------------------------------------------------
* 0            /usr/bin/gcc-9   90        auto mode
  1            /usr/bin/gcc-7   70        manual mode
  2            /usr/bin/gcc-8   80        manual mode
  3            /usr/bin/gcc-9   90        manual mode

Press <enter> to keep the current choice[*], or type selection number:

2019/11/26

ukuu, nvidia driver, cuda

ukud 커널 업데이트 모듈 드라이버 문제.
ubuntu 18.04 ukuu 커널 업데이트 dkms 문제

gcc 버전과 커널 헤더 정보 관계로 dkms 생성시 문제 발생.

콘솔 접근.
ssh 또는 ctrl + art + F1

윈도우 메니저 정지
$ /etc/init.d/lightdm stop

윈도우 메니저 삭제
$ sudo apt-get purge --remove lightdm

gcc 버전 설치
$ sudo apt-get install ppa-purge
$ sudo ppa-purge ppa:ubuntu-toolchain-r/test

gcc 버전 (우분투 18.04) :
$ gcc --version

ukuu 설치한 커널로 동작시 우분투 패키지 제공 버전으로 부팅
sudo vi /etc/default/grub
디포트 옵션 1
그리고 부팅 타임 3
$ sudo update-grub

기본 커널 복구
설치된 커널 확인
$ sudo ukuu --list-installed

ukuu 설치한 커널 삭제
$ sudo ukuu --remove v4.4.172

gpu 드라이버 설치
$ sudo ./NVIDIA-Linux-x86_64-410.93.run

grub 원상 복구

재부팅
$ reboot

윈도우 메니저 설치
$ sudo apt-get install lightdm

윈도우 메니저 시작
$ sudo /etc/init.d/loghtdm start


1. 우분투에서 제공하는 커널일 경우 자동설치.
드라이버 삭제.
sudo apt-get purge nvidia*

저장소 등록
sudo add-apt-repository ppa:graphics-drivers

등록한 저장소 패키지 업데이트
sudo apt-get update

드라이버 검색
ubuntu-drivers devices

설치.
sudo apt-get install nvidia-driver-415

2. 수동설치.

드라이버 확인.
ubuntu-drivers devices

소스 다운로드
https://www.nvidia.com/Download/index.aspx

실행 권한.
chmod +x NVIDIA-Linux-x86_64-410.73.run

컴파일러 설치.
sudo apt-get install gcc
sudo apt-get install make

모듈 블랙 디바이스 지정.
sudo bash -c "echo blacklist nouveau > /etc/modprobe.d/blacklist-nvidia-nouveau.conf"
sudo bash -c "echo options nouveau modeset=0 >> /etc/modprobe.d/blacklist-nvidia-nouveau.conf"

확인.
cat /etc/modprobe.d/blacklist-nvidia-nouveau.conf

init 램디스크 업데이트
sudo update-initramfs -u

재 부팅
sudo reboot

콘솔 창 이동
ctrl + alt + F2

그래픽 모드 비활성화.
sudo telinit 3

실행.
sudo bash NVIDIA-Linux-x86_64-410.73.run
sudo reboot

cuda 설치.
https://developer.nvidia.com/cuda-10.0-download-archive?target_os=Linux&target_arch=x86_64&target_distro=Ubuntu&target_version=1804&target_type=deblocal

$ sudo dpkg -i cuda-repo-ubuntu1804-10-0-local-10.0.130-410.48_1.0-1_amd64.deb
$ sudo apt-key add /var/cuda-repo-<version>/7fa2af80.pub
$ sudo apt-get update
$ sudo apt-get install cuda

시스템 경로 적용
$ gedit ~/.bashrc
export PATH=/usr/local/cuda-10.0/bin${PATH:+:${PATH}}
export LD_LIBRARY_PATH=/usr/local/cuda-10.0/lib64${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}

재부팅
$ reboot

드라이버 및 통신 확인.
$ cat /proc/driver/nvidia/version
$ nvcc -V

테스트
$ cd /usr/local/cuda-10.0/samples
$ sudo make
$ cd bin/x86_64/linux/release
$ ./deviceQuery

2019/02/11

우분투 시스템 프로그램 오류를 발견

colord-sane은 스캐너 관련 패키지삭제. 

$ sudo apt-get purge sane-utils
$ sudo apt-get purge colord
$ sudo apt-get autoremove

2019/01/31

uuku 최신 커널 설치 gcc 문제 복구 방법.

ubuntu 16.04 ukuu 커널 업데이트 dkms 문제

gcc 버전과 커널 헤더 정보 관계로 dkms 생성시 문제 발생.

콘솔 접근.
ssh 또는 ctrl + art + F1

윈도우 메니저 정지
$ /etc/init.d/lightdm stop

윈도우 메니저 삭제
$ sudo apt-get purge --remove lightdm

gcc 버전 설치
$ sudo apt-get install ppa-purge
$ sudo ppa-purge ppa:ubuntu-toolchain-r/test

gcc 버전 (우분투 16.04) :
$ gcc --version
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609

ukuu 설치한 커널로 동작시 우분투 패키지 제공 버전으로 부팅
sudo vi /etc/default/grub
디포트 옵션 1
그리고 부팅 타임 3
$ sudo update-grub

기본 커널 복구
설치된 커널 확인
$ sudo ukuu --list-installed

ukuu 설치한 커널 삭제
$ sudo ukuu --remove v4.4.172

gpu 드라이버 설치
$ sudo ./NVIDIA-Linux-x86_64-410.93.run

grub 원상 복구

재부팅
$ reboot

윈도우 메니저 설치
$ sudo apt-get install lightdm

윈도우 메니저 시작
$ sudo /etc/init.d/loghtdm start

2019/01/30

ukuu 커널업데이트 gpu 드라이버 재 설정

모니터 지원 주파수 문제.

관련 리눅스 드라이 다운로드
NVIDIA-Linux-x86_64-410.93.run

윈도우 메니저 중지
/etc/init.d/lightdm stop

ctrl + alt 2 콘솔모드 집입
기존 드라이버 삭제
sudo apt-get --purge remove nvidia*

윈도우 메니저 삭제
sudo apt-get purge remove lightdm

nouveau 오프소스 드라이버 전부 삭제.
sudo apt-get purge --remove xserver-xorg-video-nouveau bumblebee xserver-xorg-video-nouveau-hwe-16.04 xserver-xorg-video-nouveau-hwe-16.04-dbg nouveau-firmware

관련 패키지 자동 삭제
sudo apt autoremove
reboot

드라이버 설치
sudo ./NVIDIA-Linux-x86_64-410.93.run

윈도우 메니저 설치
sudo apt-get install /etc/init.d/lightdm

윈도우 메니저 실행
/etc/init.d/lightdm start

우분투 UKUU 패키지 지원 커널 업데이트

우분투 커널 업데이트

커널 버전 확인
uname -r

우분트 설치 버전 확인
lsb_release -a

UKUU 설치
Ubuntu Kernel Update Utility

sudo add-apt-repository ppa:teejee2008/ppa
sudo apt-get update
sudo apt-get install ukuu

크래픽 환경 커널 업데이트
윈도우 키 -> uuku 선택

커널 버전 목록 확인
사용할 커널 버전 선택 후 install

reboot

CLI 커널 업데이트
커널 목록 확인
ukuu --list

xhost 접근 비 활성화.
xhost +
access control disabled, clients can connect from any host

설치
sudo ukuu install --v커널버전
example
sudo ukuu install --v4.20.5

재부팅
sudo reboot

커널 버전 확인
uname -r

2019/01/20

ABI 어플리케이션 바이너리 인터페이스

어플리케이선 바이너리 인터페이스(ABI Application Binary Interface) 
어셈블리와 OS 레벨에서의 작동 방식을 아는 경우 특정 ABI를 준수. 
ABI는 매개 변수가 전달되는 방식, 반환 값이 배치되는 방식 등을 관리함. 많은 플랫폼에서 선택할 수있는 ABI는 단 하나뿐. 
응용 프로그램과 운영체제, 응용 프로그램과 라이브러리 사이에 필요한 저 수준 인터페이스를 정의한다 응용 프로그램운영체제 라이브러리.

API보다 ABI가 저수준(binary) 라이브러리. 
API는 소스 코드에서 사용되고 ABI는 바이너리에서 호환된다.
아키텍처(x86, amd64, arm) 운영체제마다 조금씩 차이가 있음.
윈도우즈 계열 운영 체제(xp, windows7) 실행 파일 ABI를 지원 하기 때문.
함수 호출 규약 정의 함. 

외부 라이브러리를 사용할 때 중요 
- 만약 A라는 라이브러리를 사용하고 있을 때 업데이트된 A 라이브러리가 배포
- 외부 라이브러리가 업데이트 됐다고 전체 프로젝트를 다시 컴파일 하는 것을 방지 
- 만약 업데이트된 라이브러리도 같은 ABI를 지원할 경우 프로그램은 동작 함 
- 서로 다른 버전의 두 라이브러리가 같은 ABI를 가지고 있을 때 “binary- compatible 동일한 인터페이스를 가진다.

ABI가 바뀌면 재 컴파일 필요
ABI는 변경 되었지만 API는 그대로인 경우(“source compatible”)
동작 보장을 못함, ABI 변경시 재 컴파일 하는게 정석

ABI를 변경하지 않으려면? 
- ABI 변경 되지 않도록 유지 해야함. 
- 함수 인터페이스 변경 금지 
- 리턴 타입, 매개변수 숫자나 타입 등등 
- 자료형 정의, 구조체 정의, 상수 정의 등변경 금지 
- 새로운 함수, 자료형 추가 가능.

ABI 제공 방법
- ABI 강제적 제공 할 필요 없음.
- 개발자가 어셈블리로 코딩한다면 ABI 제공할 필요가 있음 
- ABI는 특정 언어에 의존적이지 않음. 
- C, PASCAL, CPP 컴파일 되면 같은 ABI 사용 할 수 있음.

ABI는 calling convention(호출 규격). 
- ABI 호환성을 유지 한 다면 라이브러리 유지/보수가 편함 
- ABI 호환성을 유지 방법, 추가 외에 기존의 라이브러리 값 변경 금지 
- ABI 호환성이 깨졌을 경우는 재 컴파일 필요.





툴체인 형식 arm-elf , arm-none-eabi

운영체제 동작.
arm-elf toolchain은 elf 형식 실행을 지원하는 일부 OS 용 obj 코드를 생성합니다 (예 : Linux ABI). OS가 프로그램 실행을 제어합니다.

펌웨어에서 동작. 
arm-none-eabi toolchain은 마이크로 컨트롤러 또는 마이크로 프로세서 (베어 메탈의 경우 EABI 임베디드 ABI)에 대한 obj 코드를 생성합니다. 이 코드는 MC의 클린 플래시에 다운로드되고 MC의 코어는 전원이 켜진 후 실행됩니다. OS 없음, 확장 명령 세트, 공유 모듈 연결 가능성 없음.

2019/01/12

vmware 가상 머신을 사용 커널 디버깅 환경 구축

vmware 가상 머신을 사용 디버깅.
커널을 가상 직렬 포트를 통해 디버그 진행.

가상 시리얼 포트 설정
vmware 설정 파일 vmx 파일을 열어 다음을 추가

serial1.present = "TRUE"
serial1.yieldOnMsrRead = "TRUE"
serial1.fileType = "pipe"
serial1.fileName = "/tmp/com_ubuntu1510" ---> 현재 1510 을 사용

ttyS0 또는 ttyS1?
다른 가상 하드웨어가 있을 수 있음.(ttyS0).

호스트 설정
터미널을 열고 소켓으로 리다이렉션 명령어 입력.
socat -d -d /tmp/com_ubuntu1510 tcp-listen:9999

새로운 터미널을 열고 텔넷으로 접근
telnet 127.0.0.1 9999

명령어 전달 테스트
echo whatever > /dev/ttyS0

텔넷 접속 콘솔에 whatever 표시 확인. 만약 메세지가 전달이 안될 경우 ttyS1로 변경해 다시 시도.

게스트:KGDB 설치
리눅스 커널이 KGDB를 지원하는 확인.

$ grep KGDB /boot/config-$(uname -r)
CONFIG_SERIAL_KGDB_NMI=y
CONFIG_HAVE_ARCH_KGDB=y
CONFIG_KGDB=y                         <---
CONFIG_KGDB_SERIAL_CONSOLE=y          <---
# CONFIG_KGDB_TESTS is not set
CONFIG_KGDB_LOW_LEVEL_TRAP=y
CONFIG_KGDB_KDB=y

커널 확인 후 커널 커맨드 라인 kgdboc=ttyS0,115200 kgdbwait 추가

커널 명령어 인자 확인 : https://www.kernel.org/doc/Documentation/kernel-parameters.txt
kgdboc=ttyS0,115200 - 콘솔, 시리얼 포트 ttyS0 및 전송 속도 1152000 kgdb 설정
kgdbwait - 기본 커널 중지 후 커널 디버그 모드로 시작


부트로더 설정
/etc/grub.d/40-custom

# /etc/grub.d/40-custom, copied from /boot/grub/grub.cfg
menuentry 'UbuntuKGDB' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-simple-4492a93c-91e2-4979-b5b9-71e32901511c' {
insmod gzio
insmod part_msdos
insmod ext2
set root='hd0,msdos1'
search --no-floppy --fs-uuid --set=root 4492a93c-91e2-4979-b5b9-71e32901511c
linux /boot/vmlinuz-4.2.0-14-generic root=UUID=4492a93c-91e2-4979-b5b9-71e32901511c ro find_preseed=/preseed.cfg auto noprompt priority=critical locale=en_US kgdboc=ttyS0,115200 kgdbwait
initrd /boot/initrd.img-4.2.0-14-generic
}

/etc/default/grub
2줄 주석 처리
#GRUB_HIDDEN_TIMEOUT=10
#GRUB_HIDDEN_TIMEOUT_QUIET=false

grub 적용
update-grub

디버깅할 커널 항목으로 재부팅 후 kgdb 연결 대기 상태 환경 구성.

호스트
sysrq 디버거 사용 비활성화

echo 0 > /proc/sys/kernel/sysrq
# Or with command,
# sysctl kernel.sysrq = 0
# And to survive reboot,
# echo 'kernel.sysrq = 0' >> /etc/sysctl.conf

게스트 활성화
echo 1 > /proc/sys/kernel/sysrq

커널 브레이크 포인터 지정 및 추적
커널 디버그 정보 확인 https://nautiluslee.blogspot.com/2019/01/blog-post_12.html
gdb debuginfo/usr/lib/debug/boot/vmlinux-4.2.0-14-generic
(gdb) set substitute-path /build/linux-xyuzCP/linux-4.2.0 /home/hfu/debuginfo/linux-source-4.2.0/linux-source-4.2.0
(gdb) target remote localhost:9999
(gdb) c

게스트
디버그 진입
# press Alt+SysRq+g
# OR
echo g > /proc/sysreq-trigger


커널 모듈 디버그
gcc 옵션 중 -g 를 사용해 빌드 후 로드 modprobe vmhgfs

_dir=/sys/module/vmhgfs/sections
cmd="add-symbol-file ~/vmhgfs.ko $(cat $_dir/.text) -s .bss $(cat $_dir/.bss) -s .data $(cat $_dir/.data)"
echo "$cmd" > add_vmhgfs_symbol.gdb

심볼 파일 로드 gdb 스크립트 호스트 복사 디버그 시작
(gdb) source add_vmhgfs_symbol.gdb
(gdb) break HgfsSendRequest

추가 정보
1. module_init 디버깅 방법
이 부분을 확인 하다 보면 jtga 디버거도 결국 vmware workstation 솔루션을 사용.

2. sysRq
실행중인 커널 사용해 디버거로 분석.

리눅스 배포판 커널 디버그정보 패키지 검색 방법.

리눅스 배포판 커널 디버그정보 패키지 검색 방법.

리눅스 코어 분석은 해당 커널의 디버그정보 패키지를 찾는 것이다. 메모리에서 커널 버전을 추출 할 때 첫 번째 해야 할 일은 커널 릴리스 하는 것이며, 소스 및 심볼 정보가 있는 디버그 패키지를 찾는게 가장 먼저 선행 되어야 하기 때문에 디버깅 정보가 담긴 패키지를 찾는다.

요즘 가장 많이 사용되는 배포한 ubuntu, RHEL, SLES에 대한 패키지를 찾는 방법을 정리 해 놓는다.

우분투 릴리즈 목록: https://wiki.ubuntu.com/Releases
우분투 릴리즈 및 커널 버전 목록: https://en.wikipedia.org/wiki/Ubuntu_version_history#Table_of_versions
디버깅 정보 저장소: http://ddebs.ubuntu.com/pool/main/l/linux/

패키지 이름
kernel: linux-image
symbol: linux-image-*-dbgsym
source: linux-source

패키지 추출 명령어.
ar -x linux-image-3.2.0-41-generic-dbgsym_3.2.0-41.66_amd64.ddeb

데비안
디버깅 정보 추가
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=365349
예: https://packages.debian.org/jessie/linux-image-3.16.0-4-amd64-dbg

레드햇

레드햇 엔터프라이즈 릴리자 정버: https://access.redhat.com/articles/3078
CentOS 디버그 패키지는 Redhat과 호환
패키지 저장소: http://vault.centos.org/
디버깅 저장소: http://debuginfo.centos.org/

패키지 이름
kernel: kernel
source: kernel-debuginfo-common
symbol: kernel-debuginfo

패키지 추출
rpm2cpio kernel-2.6.32-573.el6.x86_64.rpm | cpio -idmv

오라클 UEK(Unbreakable Enterprise kernel)

패키지 저장소 : http://public-yum.oracle.com/repo/OracleLinux/ ---> 저장소가 자꾸 변경됨, 구글 검색
디버깅 저장소 : https://oss.oracle.com/ol6/debuginfo/

CentOS 추가 리소스_정장소_디버그정보: https://wiki.centos.org/AdditionalResources/Repositories/DebugInfo
페도라 패키징 디버그 정보: https://fedoraproject.org/wiki/Packaging:Debuginfo

SLES 커널 릴리즈: https://wiki.microfocus.com/index.php/Kernel_versions
SLES 디버깅 정보: https://www.novell.com/support/#3074997

zypper search -s 'kernel-default'
zypper install --download-only --oldpackage kernel-default-debuginfo-3.0.101-0.15.1
# debuginfo package needs the kernel binary in SLES
zypper install --download-only --oldpackage kernel-default-base-3.0.101-0.15.1
# find the rpm in /var/cache/zypp/packages

SLES 저장소를 찾지 못한 상태.

2019/01/11

메모리 동작 관련

기존 DDR3 PCL3 1.5V 메모리 동작 안함. 
DDR3 PCL3L 1.35V 메모리 변경 해야 함. 

타뮤즈 호환성 문제점이 있음, 블루스크린 100대 했을 경우 50대 정도가 나온다고 함. 
만약 타뮤즈 메모리를 사용한 다면 PC3L 사용, 클럭 문제가 발생해 블루 스크린 나올 확률이 있음. 


Makefile 디버깅 심볼 테이블 생성 빌드 

Makefile 디버깅 심볼 테이블 생성 빌드

vi Makefile
obj-m += mmaptest.o
MY_CFLAGS += -g -DDEBUG
ccflags-y += ${MY_CFLAGS}
CC += ${MY_CFLAGS}

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

debug:
        make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
        EXTRA_CFLAGS="$(MY_CFLAGS)"
clean: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

디버깅 테이블 확인 명령어
readelf -S mmaptest.ko | grep debug

2019/01/10

네트워크 테스트 보드

http://www.jetwayipc.com/

랜포트 2개: G03-IMB1900-F
http://www.jetwayipc.com/product/imb-1900-2l/

랜포트 2개: G03-NF9U-F
http://www.jetwayipc.com/product/nf9u-series/

랜포트 6개: G03-NF692-F
http://www.jetwayipc.com/product/jnf692-series/

랜포트 8개: G03-NF592-F
http://www.jetwayipc.com/product/nf592-q170/

ubuntu 12.04 server 에서 zentyal 3.0 설치

sudo apt-get install -y python-software-properties && sudo add-apt-repository ppa:zentyal/3.0 && sudo apt-get update

sudo apt-get install zentyal

vmware Tools install

vmware 운영체제 설치
메뉴에서 vm -> vmware Tools 이동

디렉토리 생성.
sudo mkdir /mnt/cdrom

마운트
sudo mount /dev/cdrom /mnt/cdrom 또는 sudo mount /dev/sr0 /mnt/cdrom

ls /mnt/cdrom
tar xzvf /mnt/cdrom/VMwareTools-x.x.x-xxxx.tar.gz -C /tmp/
cd /tmp/vmware-tools-distrib/
sudo ./vmware-install.pl -d

sudo reboot


2019/01/05

buildroot 패키지를 사용해 리눅스 드라이버 모듈 추가.

buildroot 패키지를 사용해 리눅스 드라이버 모듈 추가.
외부 QEMU 커널 모듈 테스트

소스 트리 구조:
buildroot/: Buildroot 파일 시스템 사용.
kernel_module/: 외부 모듈 패키지 테스트
 config.in
 external.mk
 Makefile
 hello.c : 간단한 모듈 테스트 파일

1) 커널 모듈 환경 설정 파일
kernel_module/Config.in:
config BR2_PACKAGE_KERNEL_MODULE
        bool "kernel_module"
        depends on BR2_LINUX_KERNEL
        help
                Linux Kernel Module Cheat.

2) 외부 커널 모듈 선언
kernel_module/external.mk:
KERNEL_MODULE_VERSION = 1.0
KERNEL_MODULE_SITE = $(BR2_EXTERNAL_KERNEL_MODULE_PATH)
KERNEL_MODULE_SITE_METHOD = local
$(eval $(kernel-module))
$(eval $(generic-package))

3) 빌드 환경 구성
kernel_module/Makefile:
obj-m += $(addsuffix .o, $(notdir $(basename $(wildcard $(BR2_EXTERNAL_KERNEL_MODULE_PATH)/*.c))))
ccflags-y := -DDEBUG -g -std=gnu99 -Wno-declaration-after-statement

.PHONY: all clean

all:
    $(MAKE) -C '$(LINUX_DIR)' M='$(PWD)' modules

clean:
    $(MAKE) -C '$(LINUX_DIR)' M='$(PWD)' clean

4) 테스트할 모듈 코드 작성
kernel_module/hello.c:
#include <linux/module.h>
#include <linux/kernel.h>

MODULE_LICENSE("GPL");

static int myinit(void)
{
    printk(KERN_INFO "hello init\n");
    return 0;
}

static void myexit(void)
{
    printk(KERN_INFO "hello exit\n");
}

module_init(myinit)
module_exit(myexit)

테스트
cd buildroot
make BR2_EXTERNAL="$(pwd)/../kernel_module" qemu_x86_64_defconfig
echo 'BR2_PACKAGE_KERNEL_MODULE=y' >> .config
make BR2_JLEVEL="$(($(nproc) - 2))" all
qemu-system-x86_64 -M pc -kernel output/images/bzImage -drive file=output/images/rootfs.ext2,if=virtio,format=raw -append root=/dev/vda -net nic,model=virtio -net user

QEMU 접근 테스트
root
modprobe hello
modprobe -r hello

커널 dmesg 명령어로 메세지 확인
hello init
hello exit

커널 등록 흐름 키워드 정리, $(eval $(kernel-module)) external.mk 환경 변수를 통해 모든 것이 설정된다.
저 두개의 환경변수를 보고 modprobe가 /lib/modules/*/extra/hello.ko 포함 할 수 있다.
modprobe dep 명령어는 modules.dep에 대한 정보를 보고 모듈간 종속성을 확인한다.

종속 참고: https://nautiluslee.blogspot.com/2019/01/blog-post_5.html

시작시 모듈 자동 등록
BR2_ROOTFS_OVERLAY="../rootfs_overlay"
rootfs_overlay/etc/init.d/S99modules
modprobe

커널 모듈 종속성 관련

리눅스 커널 모듈 종속성 예제.

테스트 모듈 파일 1
dep.c

#include <linux/delay.h> /* usleep_range */
#include <linux/kernel.h>
#include <linux/kthread.h>
#include <linux/module.h>

MODULE_LICENSE("GPL");

int lkmc_dep = 0;
EXPORT_SYMBOL(lkmc_dep);
static struct task_struct *kthread;

static int work_func(void *data)
{
    while (!kthread_should_stop()) {
        printk(KERN_INFO "%d\n", lkmc_dep);
        usleep_range(1000000, 1000001);
    }
    return 0;
}

static int myinit(void)
{
    kthread = kthread_create(work_func, NULL, "mykthread");
    wake_up_process(kthread);
    return 0;
}

static void myexit(void)
{
    kthread_stop(kthread);
}

module_init(myinit)
module_exit(myexit)

테스트 모듈 파일 2
dep2.c
#include <linux/delay.h> /* usleep_range */
#include <linux/kernel.h>
#include <linux/kthread.h>
#include <linux/module.h>

MODULE_LICENSE("GPL");

extern int lkmc_dep;
static struct task_struct *kthread;

static int work_func(void *data)
{
    while (!kthread_should_stop()) {
        usleep_range(1000000, 1000001);
        lkmc_dep++;
    }
    return 0;
}

static int myinit(void)
{
    kthread = kthread_create(work_func, NULL, "mykthread");
    wake_up_process(kthread);
    return 0;
}

static void myexit(void)
{
    kthread_stop(kthread);
}

module_init(myinit)
module_exit(myexit)

컴파일
Makefile:

obj-m += $(addsuffix .o, $(notdir $(basename $(wildcard $(BR2_EXTERNAL_KERNEL_MODULE_PATH)/*.c))))
ccflags-y := -DDEBUG -g -std=gnu99 -Wno-declaration-after-statement

.PHONY: all clean

all:
$(MAKE) -C '$(LINUX_DIR)' M='$(PWD)' modules

clean:
$(MAKE) -C '$(LINUX_DIR)' M='$(PWD)' clean

모듈 로딩
insmod dep.ko
insmod dep2.ko

/lib/module/*/depmod의존성 정보를 가지고 있으므로 depmod 구성 하고 있기 때문에 두 가지 모도 로드할 수 있음.
modprobe dep

비 정적 변수 확인
CONFIG_KALLSYMS_ALL = y 확인
grep lkmc_dep /proc/kallsyms

이 파일은 커널에 다음과 같이 정이된다.
const_debug unsigned int sysctl_sched_nr_migrate = 32;

busybox qemu 설치

rootfs 단일 실행 파일 

최소 단일 루트 파일 시스템 init은 여기 참고 https://nautiluslee.blogspot.com/2019/01/init-hello-world.html

리눅스 가장 작은 라이브 이미지 파일 다운로드 후 qemu 설치 
프로젝트 사이트 : https://github.com/ivandavidov/minimal

- 커널 및 비지박스 다운로드
- 다운로드 받은 파일 컴파일
- 8MB 부팅 가능한 ISO 파일 생성

ISO 이미지 파일은 BysyBox 지원하는 쉘과 연동하게 한다.
QEMU를 사용해 부팅 테스트.
커널 소스 디렉토리에서 실행 되도록 커널 수정 

git clone https://github.com/ivandavidov/minimal
cd minimal/src
./build_minimal_linux_live.sh
# QEMU 설치.
# minimal_linux_live.iso 생성.
./qemu64.sh

루트파일 시스템 빌드
Makefile 스크립트로 프로젝트 관리: 
- gcc 크로스 컴파일 툴체인
- 커널 컴파일
- 부트로더 컴파일
- rootfs 생성
- GTK와 같은 복잡한 내용을 포함하여 소스 트리에서 수많은 의존성 패키지 다운로드.

git clone git://git.buildroot.net/buildroot
cd buildroot
git checkout 2016.05
make qemu_x86_defconfig
# -jN 대신, `BR2_JLEVEL=2`를 사용.
BR2_JLEVEL=2 make
# cat board/qemu/x86_64/readme.txt
qemu-system-x86_64 -M pc -kernel output/images/bzImage -drive file=output/images/rootfs.ext2,if=virtio,format=raw -append root=/dev/vda -net nic,model=virtio -net user
# BusyBox 쉘 동작.

X11 추가 하고 참고: 
https://nautiluslee.blogspot.com/2019/01/x11-blackbox-qemu.html

5MB인 임베디드용 패키지 https://github.com/gliderlabs/docker-alpine
busybox 보다 더욱 가벼운.