카테고리

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 보다 더욱 가벼운. 

qemu x11 설치

X11 패키지 모음 사이트
https://github.com/buildroot/buildroot/tree/2016.05/package/x11r7
https://github.com/buildroot/buildroot/tree/2018.02.x/package/x11r7
https://github.com/buildroot/buildroot/tree/2018.11.x/package/x11r7

시작 명령어.
startx 

qemu_x86_64_x11_defconfig
https://github.com/cirosantilli/buildroot-configs/blob/44b45b5c7f68e44abcda360a2b980f8301901a9a/qemu_x86_64_x11_defconfig

최소한의 X11 구성 파일
BR2_PACKAGE_XAPP_TWM=y
BR2_PACKAGE_XAPP_XCALC=y
BR2_PACKAGE_XAPP_XCLOCK=y
BR2_PACKAGE_XAPP_XEYES=y
BR2_PACKAGE_XAPP_XINIT=y
BR2_PACKAGE_XDRIVER_XF86_INPUT_KEYBOARD=y
BR2_PACKAGE_XDRIVER_XF86_INPUT_MOUSE=y
BR2_PACKAGE_XDRIVER_XF86_VIDEO_CIRRUS=y
BR2_PACKAGE_XDRIVER_XF86_VIDEO_FBDEV=y
BR2_PACKAGE_XDRIVER_XF86_VIDEO_VESA=y
BR2_PACKAGE_XORG7=y
BR2_PACKAGE_XSERVER_XORG_SERVER=y
BR2_PACKAGE_XTERM=y
BR2_TOOLCHAIN_BUILDROOT_CXX=y
BR2_TOOLCHAIN_BUILDROOT_WCHAR=y
BR2_USE_WCHAR=y

.config 추가 방법.
cat configs/qemu_x86_64_defconfig br_config_frag > .config
make olddefconfig

선택 옵션 발견: 
make menuconfig
커널 체크 박스 에서 검색 / 
xeyes에 대한 dependes 확인. 

두개의 서로 다른 인터페이스 패키지가 구현되는 상황. (X.Org 모듈과 KDrive 둘 다 X11 서버 구현하는 경우) 기본적으로 선택되지 않는 상황 때문에 어떻한 작업을 할 것인지에 대해 알고 있어야 한다. 

윈도우메니지먼트 참고: https://nautiluslee.blogspot.com/2019/01/x11-blackbox-qemu.html

동작 구현 
make BR2_JLEVEL=$(nproc)
qemu-system-x86_64 \
    -enable-kvm \
    -M pc \
    -m 512 \
    -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
startx

이미지 크기: 28M

startx 명령어 실행 후 /etc/X11/xinit/xinitrc 파일를 참고해 GUI 호출 

vi xinitrc 
twm &
xclock -geometry 50x50-1+1 &
xterm -geometry 80x50+494+51 &
xterm -geometry 80x20+494-0 &
exec xterm -geometry 80x66+0+0 -name login

윈도우 메니지먼트 시작됨. 

QEMU SSH 사용해 게스트 접근 방법.
-net nic,model=virtio \
-net user,hostfwd=tcp::5901-:5900

추가 후 게스트에서 startx 실행
x11vnc 

호스트 환경으로 넘어와: 
sudo apt-get install vinagre
vinagre localhost::5901

x로만 로그인 할 경우
대상 패키지 -> 그래픽 라이브러리 및 응용프로그램 -> 
X.Org X Window System : y 클릭 
X11R7 Application -> xconsole(xdm 기본 설정)
xdm

루트 로그인 할 수 없음.
xdm 로그: /var/log/sdm.log 

x 메니지먼트 호출 체인 방식 
/init (BysyBox 사용)
/etc/inittab 내용 :: sysinit:/etc/init.d/rcS
/etc/init.d/rcS
/etc/init.d/S99xdm
/usr/bin/xdm

x11 blackbox 윈도우메니지먼트 qemu 설치 테스트

일반 사용타 루트파일 시스템 다운로드
$ cd
$ git clone git://git.buildroot.net/buildroot
$ cd buildroot && make menuconf

커널 설정
Toolchain —>
[X] Enable large file (files > 2 GB) support
[X] Enable WCHAR support
[X] Enable C++ support

Package Selection for the target —>
Graphic libraries and applications (graphic/text) —>
[X] X.org X Window System, X11R7, release 7.5 —>
X Window System server type  —>
[X] Modular X.org

X11R7 Applications —>
[X] setxkbmap        // 선택 사항: us 이외의 다른 키보드 맵 지원
[X] twm
[X] xclock
[X] xinit
[X] xinput        // 선택 사항: 입력 장치 문제 찾기
[X] xkbcomp

X11R7 Drivers —>
[X] xf86-input-evdev
[X] xf86-input-keyboard
[X] xf86-input-mouse
[X] xf86-video-cirrus    // NOTE : qemu 그래픽 보드
[X] xf86-video-fbdev
[X] xf86-video-vesa

(호환성 드라이버 점검.)

[X] Liberation (Free fonts)
[X] xterm

Libraries –>
Text and terminal handling —>
[X] ncurses        // xterm 종속성 확인 , see http://lists.busybox.net/pipermail/buildroot/2011-March/041737.html

Hardware handling —>
[*] udev

Kernel —>
[X] Linux Kernel
Defconfig name : i386

Target filesystem options —>
[X] iso image (optional, only if you want to burn on a CD)
[X] initramfs for initial ramdisk of linux kernel
uncheck others

빌드
$ make

qemu 테스트
$ qemu -kernel output/images/bzImage -m 256

로그인
root/패스워드 없음)
x11  실행
# startx

TODO : qemu 마우스 커서 움직임 버그 존재(hal 패키지 설치)
USB 실제 컴퓨터 부팅시 마우스 잘 동작 함.
입력 장치 값: https://wiki.ubuntu.com/X/Config/Input

하드웨어 프레임 버퍼 활성화.
$ make linux-menuconfig

호환성 모두 포함
Device drivers —>
Graphics support —>
Support for frame buffer devices —>
Check everything

재 빌드 및 테스트
$ make && qemu -kernel output/images/bzImage -m 256

X11 시작
# startx

선택 사항
디버깅 xorg.conf 파일 수정
# X -configure
# mkdir -p /etc/X11
# cp xorg.conf.new /etc/X11/xorg.conf
# vi /etc/X11/xorg.conf

팁 : CTRL-ALT-BACKSPACE X를 죽이려면 xorg.conf 수정
vi xorg.conf
keyboard section :
Option  “XkbOptions” “terminate:ctrl_alt_bksp”

and add in a ServerFlags section :

Section “ServerFlags”
Option          “DontZap”       “false”
EndSection

</optional>

작은 윈도우 매니저머트 추가
$ make menuconfig

Package Selection for the target —>
Graphic libraries and applications (graphic/text) —>
[X] blackbox

참고: blackbox 기본 구성은 bitstream Vera 9 글꼴 사용. 글꼴이 추가되지 않으면 종료 됨.

재 빌드 테스트
$ make && qemu -kernel output/images/bzImage -m 256

바탕 화면 오른쪽 마우스 클릭 Blackbox 메뉴가 생성

rootfs 추가 준비
$ cd <your buildroot home>/output/target

선택 사항 busubox 용 키맵(여기서는 us keymap file, us.kmap) 만들고 복사한다.
$ sudo busybox dumpkmap >etc/us.kmap

부팅 시퀀서 수정
$ nano etc/init.d/rcS
loadkmap </etc/us.kmap

x윈도우 시작
startx

x 윈도우 시작 스크립트 수정
$ nano usr/lib/X11/xinit/xinitrc

주석 처리
#twm &
#xclock -geometry 50×50-1+1 &
#xterm -geometry 80×50+494+51 &
#xterm -geometry 80×20+494-0 &
#exec xterm -geometry 80×66+0+0 -name login

다음 추가
setxkbmap us
xterm &

# 윈도우 메니지먼트
exec blackbox

최종 테스트
$ cd <your buildroot home>
$ make && qemu -kernel output/images/bzImage -m 256

runlinux 커널 소스 해킹 및 디버깅 방법.

리눅스 실행
작업중인 커널을 다운로드하는 대신 기존 커널 소스를 재사용해 커널을 해킹한 후 개발 용으로 테스트 한다.

최소한의 리눅스 이미지 사용.

설치
sudo apt-get install git qemu
sudo apt-get build-dep busybox linux-image-$(uname -r)
mkdir -p ~/bin
cd ~/bin
git clone --recursive https://github.com/cirosantilli/runlinux
echo 'PATH="$PATH:'$(pwd)'/runlinux"' >> ~/.bashrc
. ~/.bashrc

예제
git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
cd linux
git checkout v4.2
runlinux

처음 부팅시 시간이 걸린다.
부팅 되면 커널 소스를 해킹
runlinux

사용자 정의 구성 외부 트리 빌드:
export KBUILD_OUTPUT="$(pwd)/../build"
make menuconfig
runlinux

기존 구성 파이리이 없으면 KBUILD_OUTPUT, make defconfig 사용.
QEMU 추가 옵션 설정.
runlinux -- -bios ~/path/to/OVMF.fd

bios 대신 UEFI x64 사용시 다운로드.
https://sourceforge.net/projects/edk2/files/OVMF/OVMF-X64-r15214.zip

실 하드웨어 실행
빌드 디렉토리에 main.img 파일 생성:
runlinux -i

usb 장치 연결
sudo lsblk
sudo fdisk -l

usb 이미지 굽기
sudo dd if=main.img of=/dev/sdx

실제 컴퓨터 바이오스 부팅 시퀀서 USB 변경

이미지 동작 확인.
qemu-system-x86_64 -enable-kvm -hda main.img

선택사항
사용자 정의 initrd 생성
n
BysyBox 무시 한 후 사용자정의 루트파일 시스템 사용.
runlinux -n /path/to/my/directory/
runlinux -n /path/to/my/init

경로 설정:
- 디렉토리 압축
리눅스 부팅시 가장 먼저 /init 디렉토리를 찾아 실행함.
- init 파일을 사용하면 압축된 파일 시스템의 루트 이름이 바뀜.

initrd 참고: https://nautiluslee.blogspot.com/2019/01/init-hello-world.html

GDB 커널 디버깅:
../runlinux/runlinux -g

CONFIG_DEBUG_INFO 필요한 경우, 커널 옵션을 설정한 후 커널 다시 빌드.
QEMU를 실행 후 GDB 활성화.

디버깅 준비 예:
hbreak start_kernel
list
continue

init hello world 프로그램

init hello world 프로그램

init.S 추가
.global _start
_start:
    mov $1, %rax
    mov $1, %rdi
    mov $message, %rsi
    mov $message_len, %rdx
    syscall
    jmp .
    message: .ascii "FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR\n"
    .equ message_len, . - message

종료 시스템 호출 및 커널 패닉 사용할 수 없을 때:

mkdir d
as --64 -o init.o init.S # assemble
ld -o d/init init.o      # link
cd d
find . | cpio -o -H newc | gzip > ../rootfs.cpio.gz
ROOTFS_PATH="$(pwd)/../rootfs.cpio.gz"

hello world 정보를 가진 init 파일 시스템 생성.

커널 소스 다운로드
git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
cd linux
git checkout v4.9
make mrproper
make defconfig
make -j"$(nproc)"

QEMU 실행
qemu-system-x86_64 -kernel arch/x86/boot/bzImage -initrd "$ROOTFS_PATH"

메세지 확인
FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR

C 프로그램 사용.
#include <stdio.h>
#include <unistd.h>

int main() {
    printf("FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR\n");
    sleep(0xFFFFFFFF);
    return 0;
}

컴파일
gcc -static init.c -o init

usb 부팅 실 하드웨어 테스트
make isoimage FDINITRD="$ROOTFS_PATH"
sudo dd if=arch/x86/boot/image.iso of=/dev/sdX

GDB 커널 단계별 디버깅

GDB 단계별 디버깅

리눅스 커널 디버깅
./run -d

start_kernel 부트 시퀀스와 같은 심볼에서 직접 접근
./rungdb start_kernel

QEMU 정지, GDB 명령어 사용 활성화:
l
n
c

부팅 건너 뛰려면 다음 실행.
./rungdb

gdm 모드 정지 ctrl + c
QEMU 내부 스크립트 테스트
./count.sh

stdout 무한대 계산, GDB 다음과 같이 계산됨.
Ctrl + C
break sys_write
continue
continue
continue

커널 모듈 디버깅
./run -d
./rungdb

QEMU 모드 진입:
insmod /fops.ko

정지 CTRL + C
scanning for modules in ../kernel_module-1.0/
loading @0xffffffffa0000000: ../kernel_module-1.0//fops.ko

간단한 심볼
b fop_write
c

QEMU 모드 진입:
printf a >/sys/kernel/debug/lkmc_fops/f

GDB 브레이크 포인트 fop_write 지정
rmmod 하기 전 브레이크 포인트 해제, 그렇지 않으면 브레이크 포이트 정보 가지고 있음.

하드코어 방식의 디버깅, 별로 사용하지 않는 방식
insmod /fops.ko

cat /proc/modules
fops 2327 0 - Live 0xfffffffa00000000

모듈로드 정보 GDB 전달
Ctrl + C
add-symbol-file ../kernel_module-1.0/fops.ko 0xfffffffa00000000

커널 초기 디버그 부팅
./rungdb extract_kernel
./rungdb main

qemu 스냅 샷

스냅샷 생성
QEMU 원본 이미지를 참조하는 이미지 생성.
기존 이미지 스탭 샵을 만든 후 다음 버전의 스냅샷으로 작업을 진행하는 이미지 원리.

-b : 백업
qemu-img create -f qcow2 -b centos-cleaninstall.img snapshot.img

이전 버전 돌아가기
변경된 스탭 샷 이미지는 원래 상태로 되돌릴 수 없다.
대신 첫 번째 스냅 샷 이미지를 생성하고, 그 이미지 파일을 사용한다.

백업 파일 수정
$ qemu-img info snapshot.img

임시 스탭 샵.
qemu -hda centos-cleaninstall.img -snapshot

우분투 18.04 qemu 호스트/게스트 설정

우분투 18.04 qemu 호스트/게스트 설정

wget http://releases.ubuntu.com/18.04/ubuntu-18.04.1-desktop-amd64.iso
qemu-img create -f qcow2 ubuntu-18.04-desktop-amd64.img.qcow2 64G
qemu-system-x86_64 \
  -cdrom ubuntu-18.04-desktop-amd64.iso \
  -drive file=ubuntu-18.04-desktop-amd64.img.qcow2,format=qcow2 \
  -enable-kvm \
  -m 2G \
  -smp 2 \
  -vga virtio \
;

GUI 에서 우분투 설치

기본 버전 이미지 생성(초기 버전)
qemu-img create -f qcow2 -b ubuntu-18.04-desktop-amd64.img.qcow2 \
                            ubuntu-18.04-desktop-amd64.snapshot.qcow2

시스템 다시 시작.
qemu-system-x86_64 \
  -drive file=ubuntu-18.04-desktop-amd64.snapshot.qcow2,format=qcow2 \
  -enable-kvm \
  -m 2G \
  -smp 2 \
  -soundhw hda \
  -vga virtio \
;

설치부터 다시 할 경우 실행
qemu-img create -f qcow2 -b ubuntu-18.04-desktop-amd64.img.qcow2 \
                            ubuntu-18.04-desktop-amd64.snapshot.qcow2

스냅 샷은 원본 이미지 사이의 차이점만 저장하기 때문에 디스크 공간을 많이 차지하지 않음

해상도 설정 옵션
-vga virtio

전체 화면 사용
-full-screen
Ctrl + Alt + F

QEMU 기본 비활성화
-soundhw hda

부팅 시간 단축 및 부팅 메시지 표시
printf 'GRUB_TIMEOUT=1\nGRUB_CMDLINE_LINUX_DEFAULT=""\n' | sudo tee -a /etc/default/grub
sudo update-grub

접속
1. virt-manager에 spice-gtk 클라이언트가 내장됨.
vm 호스트에서 python-spice-client-gtk 설치.
virt-manager를 사용하여 다른 호스트에서 ssh를 통해 VM 호스트에 원격으로 연결하는 경우 해당 시스템에 python-spice-client-gtk도 설치해야함.

2. virt-manager 시작

3. 가상화 컴퓨터 시작

4. 가상화 컴퓨터 전원 ON

5. ssh 게스트 연결, 게스트에서 spice-vdagent 설치하고 spice-vdagentd 시작 되었는 지 확인

6. 가상환경 하드웨어 세부 정보 표시

7. Display VNC 선택하고 VNC를 Spice 변경한 후 수락해 채널 추가

8. Cirrus(기본값)에서 QXL 비디오 모델 변경

9. virt-manager 다시 시작하고 가상 시스템 전원을 켠다.

x 값 없을때 해결방법(단 호스트환경에서 VM으로 ssh 접근 할 수 있다는 전제 조건)
~$ssh user@host
~$ssh user@guest

설치
프로젝트 사이트: https://www.spice-space.org/download.html

sudo apt install spice-vdagent

설정 방법.
https://wiki.archlinux.org/index.php/QEMU#SPICE
https://www.linux-kvm.org/page/SPICE

시도,
-spice port=5930,disable-ticketing+ remote-viewer spice://127.0.0.1:5930, 그리고 spice-vdagent 게스트 설치, 성공하지 못함.

근본 원인은 QEMU devs 안정적 구현하지 않음, QEMU 개발 방법은 비대화 형 개발에 더 중점을 둔다.

참고:
 호스트 3D 가속. SPICE 및 QXL을 glxgears사용하는 경우 1k FPS를 제공하고 일반 SDL과 동리 함.
 호스트에서 __GL_SYNC_TO_VBLANK=0 vblank_mode=0 glxgears20k FPS를 제공하므로 그래픽이 가속되지 않은 것으로 보임.

pdf 파일 편집

설치:
sudo apt-get install libreoffice
libreoffice my.pdf

페이지 삭제
페이지 순서 변경
기존 텍스트 필드
새 텍스트 필드 추가 
텍스트 필드가 아닌 객체 편집(머리글, 바닥글, 행)
채울 수있는 PDF 양식 생성(양식 * 도구 모음 사용 및 "PDF 양식 만들기" 선택)

일부 PDF 형식 지원 문제점 있음.

node.js 버전별 관리 프로젝트

프로젝트 사이트
https://github.com/creationix/nvm

다운로드
curl https://raw.githubusercontent.com/creationix/nvm/master/install.sh | sh
source ~/.nvm/nvm.sh
nvm install --lts
nvm use --lts
npm install --global vaca
vaca

bashrc 추가.
f="$HOME/.nvm/nvm.sh"
if [ -r "$f" ]; then
  . "$f" &>'/dev/null'
  nvm use --lts &>'/dev/null'
fi

장점:
sudo 없이 Node 버전 사용
가능한 바이너리 파일을 설치

버전별 전환 방법
nvm install 0.9.0
nvm install 0.9.9

nvm use 0.9.0
node --version
#v0.9.0

nvm use 0.9.9
node --version
#v0.9.9

wifi tui 대화형 설정.

콘솔 환경에서 대화형 방식으로 인터넷 설정.
shell> nmtui

debootstrap_x86 qemu 자동 설치 스크립트

#!/usr/bin/env bash

set -eux

suite=xenial

debootstrap_dir=$suite
img_file=${suite}.ext4.img
kernel=/vmlinuz
initrd=/initrd.img

sudo apt install -y \
  debootstrap \
  qemu-system-x86 \
;

if [ ! -d "$debootstrap_dir" ]; then
  # Create debootstrap directory.
  sudo debootstrap \
    "$suite" \
    "$debootstrap_dir" \
    http://archive.ubuntu.com/ubuntu \
  ;

  # Set root password.
  echo 'root:root' | sudo chroot "$debootstrap_dir" chpasswd

  # Remount root filesystem as rw.
  cat << EOF | sudo tee "$debootstrap_dir/etc/fstab"
/dev/sda / ext4 errors=remount-ro,acl 0 1
EOF

  # Automaticaly start networking.
  # Otherwise network commands fail with:
  #     Temporary failure in name resolution
  # https://gist.github.com/corvax19/6230283#gistcomment-1940694
  cat << EOF | sudo tee "$debootstrap_dir/etc/systemd/system/dhclient.service"
[Unit]
Description=DHCP Client
Documentation=man:dhclient(8)
Wants=network.target
Before=network.target
[Service]
Type=forking
PIDFile=/var/run/dhclient.pid
ExecStart=/sbin/dhclient -4 -q
[Install]
WantedBy=multi-user.target
EOF

  sudo ln -sf /etc/systemd/system/dhclient.service \
    "${debootstrap_dir}/etc/systemd/system/multi-user.target.wants/dhclient.service"
fi

if [ ! -f "$img_file" ]; then
  # Create disk image
  dd if=/dev/null of="$img_file" bs=1M seek=2048
  mkfs.ext4 "$img_file"
  mnt_dir="${suite}_mnt"
  mkdir "$mnt_dir"
  sudo mount -t ext4 "$img_file" "$mnt_dir"
  sudo cp -r "$debootstrap_dir/." "$mnt_dir"
  sudo umount "$mnt_dir"
  rmdir "$mnt_dir"
fi

sudo qemu-system-x86_64 \
  -append 'console=ttyS0 root=/dev/sda' \
  -drive "file=${img_file},format=raw" \
  -enable-kvm \
  -nographic \
  -serial mon:stdio \
  -m 2G \
  -kernel "$kernel" \
  -initrd "$initrd" \
;

2019/01/04

debootstrap arm64 qemu 설치

debootstrap arm64
1)
-- foreign 패키지 다운로드.
-- chroot 사용
-- --second-stage + QEMU 사용자 모드 에물레이션 사용.(binfmt_misc)

2) 커널 vfs 패닉
[    0.773665] Please append a correct "root=" boot option; here are the available partitions:
[    0.774033] Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)
파일 시스템 지원 확인.

CONFIG_VIRTIO_BLK=y

initrd에서 모듈이 로드되어야 하기 때문에 ISO 이미지를 사용해서 동작 시켜야 할 듯 함.

다른 유형의 파일시스템 유형을 사용하려고 시도했지만 커널 지원 문제가 있어, 커널 컴파일을 해야함.
-drive if= -M virt

데비안 계열 우분투 패키지 커널을 사용할 때 arm64 커널 빌드 명령어.
처음 빌드 시
export ARCH=arm64
export $(dpkg-architecture -aarm64); export CROSS_COMPILE=aarch64-linux-gnu-

fakeroot debian/rules clean
debian/rules build
fakeroot debian/rules binary

두번째 이상 빌드시.
rm debian/stamps/stamp-build*
debian/rules build
fakeroot debian/rules binary

커널 설정 옵션에서 개발자 모드를 활성화.
Ubuntu devs, CONFIG y

인터넷 동작 문제.
systemctl status dhclient.service
cat f

자동 설치 스크립트
#!/usr/bin/env bash

# https://askubuntu.com/questions/281763/is-there-any-prebuilt-qemu-ubuntu-image32bit-online/1081171#1081171

set -eux

debootstrap_dir=debootstrap
root_filesystem=debootstrap.ext2.qcow2

sudo apt-get install \
  gcc-aarch64-linux-gnu \
  debootstrap \
  libguestfs-tools \
  qemu-system-aarch64 \
  qemu-user-static \
;

if [ ! -d "$debootstrap_dir" ]; then
  sudo debootstrap \
    --arch arm64 \
    --foreign \
    bionic \
    "$debootstrap_dir" \
    http://ports.ubuntu.com/ubuntu-ports \
  ;
  sudo mkdir -p "${debootstrap_dir}/usr/bin"
  sudo cp "$(which qemu-aarch64-static)" "${debootstrap_dir}/usr/bin"
  sudo chroot "$debootstrap_dir" /debootstrap/debootstrap --second-stage
  sudo rm -f "$root_filesystem"
fi

linux_image="$(printf "${debootstrap_dir}/boot/vmlinuz-"*)"

if [ ! -f "$root_filesystem" ]; then
  # Set root password.
  echo 'root:root' | sudo chroot "$debootstrap_dir" chpasswd

  # Remount root filesystem as rw.
  cat << EOF | sudo tee "${debootstrap_dir}/etc/fstab"
/dev/sda / ext4 errors=remount-ro,acl 0 1
EOF

  # https://askubuntu.com/questions/1045278/ubuntu-server-18-04-temporary-failure-in-name-resolution/1080902#1080902
  cat << EOF | sudo tee "${debootstrap_dir}/etc/systemd/system/dhclient.service"
[Unit]
Description=DHCP Client
Documentation=man:dhclient(8)
Wants=network.target
Before=network.target
[Service]
Type=forking
PIDFile=/var/run/dhclient.pid
ExecStart=/sbin/dhclient -4 -q
[Install]
WantedBy=multi-user.target
EOF
  sudo ln -sf "${debootstrap_dir}/etc/systemd/system/dhclient.service" \
    "${debootstrap_dir}/etc/systemd/system/multi-user.target.wants/dhclient.service"

  # https://bugs.launchpad.net/ubuntu/+source/linux/+bug/759725
  sudo chmod +r "${linux_image}"

  # Generate image file from debootstrap directory.
  # Leave 1Gb extra empty space in the image.
  sudo virt-make-fs \
    --format qcow2 \
    --size +1G \
    --type ext2 \
    "$debootstrap_dir" \
    "$root_filesystem" \
  ;
  sudo chmod 666 "$root_filesystem"
fi

# 커널 컴파일.
linux_image="$(pwd)/linux/debian/build/build-generic/arch/arm64/boot/Image"
if [ ! -f "$linux_image" ]; then
  #git clone --branch Ubuntu-4.15.0-20.21 --depth 1 git://kernel.ubuntu.com/ubuntu/ubuntu-bionic.git linux
  cd linux
  cat << EOF | patch -p1
diff --git a/debian.master/config/config.common.ubuntu b/debian.master/config/config.common.ubuntu
index 5ff32cb997e9..8a190d3a0299 100644
--- a/debian.master/config/config.common.ubuntu
+++ b/debian.master/config/config.common.ubuntu
@@ -10153,7 +10153,7 @@ CONFIG_VIDEO_ZORAN_ZR36060=m
 CONFIG_VIPERBOARD_ADC=m
 CONFIG_VIRTIO=y
 CONFIG_VIRTIO_BALLOON=y
-CONFIG_VIRTIO_BLK=m
+CONFIG_VIRTIO_BLK=y
 CONFIG_VIRTIO_BLK_SCSI=y
 CONFIG_VIRTIO_CONSOLE=y
 CONFIG_VIRTIO_INPUT=m
EOF
  export ARCH=arm64
  export $(dpkg-architecture -aarm64)
  export CROSS_COMPILE=aarch64-linux-gnu-
  fakeroot debian/rules clean
  debian/rules updateconfigs
  fakeroot debian/rules DEB_BUILD_OPTIONS=parallel=`nproc` build-generic
  cd -
fi

#linux_image=/home/ciro/bak/git/linux-kernel-module-cheat/out/linux/default/aarch64/arch/arm64/boot/Image
#linux_image=/home/ciro/bak/git/linux-kernel-module-cheat/submodules/linux/debian/build/build-generic/arch/arm64/boot/Image
qemu-system-aarch64 \
  -append 'console=ttyAMA0 root=/dev/vda rootfstype=ext2' \
  -device rtl8139,netdev=net0 \
  -drive "file=${root_filesystem},format=qcow2" \
  -kernel "${linux_image}" \
  -m 2G \
  -netdev user,id=net0 \
  -serial mon:stdio \
  -M virt,highmem=off \
  -cpu cortex-a57 \
  -nographic \
;

Linux 커널 exec의 시스템 호출 ELF 방식에서 스크립트 언어 #! 인식 shebang 지정.

Linux 커널 exec의 시스템 호출 #! 인식 shebang 지정.
#! 사람이 읽기 편하도록 구성한다는 의미(스크립트 언어)

./something

리눅스 커널 소스
linux/fs/binfmt_script.c

if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!'))
바이트를 읽은  후 비교.

참이면 커널에서 파싱.
경로 /usr/bin/env python 첫 번째 인수 사용하여 또 다른 exec 호출 생성.
/usr/bin/env python /path/to/script.py

#주석 문자 사용하는 모든 스크립팅 언어에서 동작 함.

무한 루프도 만들 수 있음.
printf '#!/a\n' | sudo tee /a
sudo chmod +x /a
/a

bash 오류 인식
-bash: /a: /a: bad interpreter: Too many levels of symbolic links

ELF 실행 파일
linux/fs/binfmt_elf.c
magic.elfmag[EI_MAG0] = ELFMAG0;
바이트 검사. 7f 45 4c 46, 사람이 읽을 수 있으나 이해 하려면 시간이 걸림.
EFL 형식의 파일을 읽고, 메모리에 정확하게 넣고, 새로운 프로세스 시작.

debootstrap이란?

debootstrap이란?

x86 시스템에서 임베디드 ARM 또는 PowerPC 시스템용 데비안/우분투를 설치를 의미, 조금더 큰 의미에서는 네트워 부팅도 여기에 속 할 수 있음, 요즘 클라우드 컴퓨팅 환경 구성이 과도기를 지나 완성도를 높이는 단계로 진입한 듯 함.

1. .deb 패키지 파일을 다운로드 받아 압축해제.
2. qemu-user-static 에물레이트 하기 위해 모든 패키지 구성 스크립트 실행

간단한 사용 예제.
우분투 18.04
sudo apt-get install \
  debootstrap \
  qemu-user-static \
;
debootstrap_dir=debootstrap
sudo debootstrap \
  --arch arm64 \
  --foreign \
  bionic \
  "$debootstrap_dir" \
  http://ports.ubuntu.com/ubuntu-ports \
;
sudo mkdir -p "${debootstrap_dir}/usr/bin"
sudo cp "$(which qemu-aarch64-static)" "${debootstrap_dir}/usr/bin"
sudo chroot "$debootstrap_dir" /debootstrap/debootstrap --second-stage
sudo rm -f "$root_filesystem"

리눅스 커널 컴파일 init/main.c 부팅시 메세지 출력

init/main.c

커널 소스 다운로드
git clone git://kernel.ubuntu.com/ubuntu/ubuntu-bionic.git
cd ubuntu-bionic

# 작업할 커널 소스버전 변경.
git checkout Ubuntu-4.15.0-20.21
fakeroot debian/rules clean
debian/rules updateconfigs
fakeroot debian/rules build-generic
linux_image="$(pwd)/debian/build/build-generic/arch/x86_64/boot/bzImage"

커널 정보 추출 확인.
https://nautiluslee.blogspot.com/2019/01/config.html

패치 적용
diff --git a/init/main.c b/init/main.c
index b8b121c17ff1..542229349efc 100644
--- a/init/main.c
+++ b/init/main.c
@@ -516,6 +516,8 @@ asmlinkage __visible void __init start_kernel(void)
        char *command_line;
        char *after_dashes;

+ pr_info("I'VE Hae Nam Korea Linux Love man!!!");
+
        set_task_stack_end_magic(&init_task);
        smp_setup_processor_id();
        debug_objects_early_init();

빌드
fakeroot debian/rules build-generic

부팅 메시지 출력
I'VE Hae Nam Korea Linux Love man

Kernel: arch/x86/boot/bzImage is ready  (#3)

우분투 커널 .config 환경 설정 부분 확인 및 추출 방법.

우분투 커널 .config 파일 관련

우분투 git 커널 저장소

debian/config 커널 트리 메타 데이터 git 저장소
https://kernel.ubuntu.com/git/ubuntu/ubuntu-bionic.git/

우분투 18.04 linux-image-4.15.0-36-generici 커널 패키지에 대한 태크 정보는 Ubuntu-4.15.0-36.39.

config 파일 저장소
https://kernel.ubuntu.com/git/ubuntu/ubuntu-bionic.git/tree/debian.master/config?h=Ubuntu-4.15.0-36.39

config.common.ubuntu, config.common.amd64, config.flavour.generic 병합 linux-image-4.15.0-36-generic 커널 패키지가 나옴.

병합하는 스크립트
https://kernel.ubuntu.com/git/ubuntu/ubuntu-bionic.git/tree/debian/scripts/misc/kernelconfig?h=Ubuntu-4.15.0-36.39

# Merge configs
# We merge config.common.ubuntu + config.common.<arch> +
# config.flavour.<flavour>

아키텍쳐 별 구성 파일.
https://kernel.ubuntu.com/git/ubuntu/ubuntu-bionic.git/tree/debian.master/config/annotations?h=Ubuntu-4.15.0-36.39

환경 설정없이 컴파일
git clone git://kernel.ubuntu.com/ubuntu/ubuntu-bionic.git linux
cd linux
git checkout Ubuntu-4.15.0-36.39
fakeroot debian/rules clean
debian/rules updateconfigs
fakeroot debian/rules build-generic

현재 커널 설정 내용과 차이점 비교.
diff debian/build/build-generic/.config /boot/config-4.15.0-36-generic

.deb 파일 구성
최종 커널 환경 설정 값
/boot/config-4.15.0-36-generic

커널 이미지
/boot/vmlinuz-4.15.0-36-generic

패키지 버전 확인
dpkg -S /boot/config-4.15.0-36-generic

패키지 파일은 다음 내용을 제공 함.
linux-modules-4.15.0-36-generic: /boot/config-4.15.0-36-generic

패키지 정보 목록 확인
https://packages.ubuntu.com/bionic-updates/linux-modules-4.15.0-36-generic

환경 구성 파일 추출
mkdir config
cd config
wget http://mirrors.kernel.org/ubuntu/pool/main/l/linux/linux-modules-4.15.0-36-generic_4.15.0-36.39_amd64.deb
ar x linux-modules-4.15.0-36-generic_4.15.0-36.39_amd64.deb
tar -xvf data.tar.xz
cat ./boot/config-4.15.0-36-generic

debootstrap amd64 전체 이미지 파일 구성 qemu

debootstrap amd64
모든 패키지 다운로드 구성
#!/usr/bin/env bash
# https://askubuntu.com/questions/281763/is-there-any-prebuilt-qemu-ubuntu-image32bit-online/1081171#1081171

set -eux

debootstrap_dir=debootstrap
root_filesystem=debootstrap.ext2.qcow2

sudo apt-get install \
  debootstrap \
  libguestfs-tools \
  qemu-system-x86 \
;

if [ ! -d "$debootstrap_dir" ]; then
  # Create 디렉토리 생성.
  # - linux-image-generic: /boot 사용할 커널 이미지 다운로드
  # - network-manager: 부팅시 네트워크 사용
  sudo debootstrap \
    --include linux-image-generic \
    bionic \
    "$debootstrap_dir" \
    http://archive.ubuntu.com/ubuntu \
  ;
  sudo rm -f "$root_filesystem"
fi

linux_image="$(printf "${debootstrap_dir}/boot/vmlinuz-"*)"

if [ ! -f "$root_filesystem" ]; then
  # Set root password.
  echo 'root:root' | sudo chroot "$debootstrap_dir"  chpasswd

  # 루투 파일시스템 rw 모드로 마운팅.
  cat << EOF | sudo tee "${debootstrap_dir}/etc/fstab"
/dev/sda / ext4 errors=remount-ro,acl 0 1
EOF

  # 네트워크 시작.
  # 네트워크 명령어 입력 실패시 :
  #    일시적 실패....
  # https://askubuntu.com/questions/1045278/ubuntu-server-18-04-temporary-failure-in-name-resolution/1080902#1080902
  cat << EOF | sudo tee "$debootstrap_dir/etc/systemd/system/dhclient.service"
[Unit]
Description=DHCP Client
Documentation=man:dhclient(8)
Wants=network.target
Before=network.target
[Service]
Type=forking
PIDFile=/var/run/dhclient.pid
ExecStart=/sbin/dhclient -4 -q
[Install]
WantedBy=multi-user.target
EOF
  sudo ln -sf "$debootstrap_dir/etc/systemd/system/dhclient.service" \
    "${debootstrap_dir}/etc/systemd/system/multi-user.target.wants/dhclient.service"

  # https://bugs.launchpad.net/ubuntu/+source/linux/+bug/759725
  sudo chmod +r "${linux_image}"

  # debootstrap 디렉토리에 이미지 파일 생성.
  # 1Gb 공간 남겨둔.
  sudo virt-make-fs \
    --format qcow2 \
    --size +1G \
    --type ext2 \
    "$debootstrap_dir" \
    "$root_filesystem" \
  ;
  sudo chmod 666 "$root_filesystem"
fi

qemu-system-x86_64 \
  -append 'console=ttyS0 root=/dev/sda' \
  -drive "file=${root_filesystem},format=qcow2" \
  -enable-kvm \
  -serial mon:stdio \
  -m 2G \
  -kernel "${linux_image}" \
  -device rtl8139,netdev=net0 \
  -netdev user,id=net0 \
;

login: root
pw: root

인터넷 동작 확인
wget그리고 curl기본적으로 설치되지 않기 때문에 다음 명령어로 인터넷 동작 확인
ping 또한 qemu에서 기본적으로 동작 하지 않음.

printf 'GET / HTTP/1.1\r\nHost: example.com\r\n\r\n' | nc example.com 80
apt-get update
apt-get install hello
hello

UEFI Cloud image arm64

UEFI Cloud image arm64
sudo apt-get install qemu-efi

자동 스크립트
vi uefi_cloud_image.sh

#!/usr/bin/env bash
set -eux

#sudo apt-get install cloud-image-utils qemu-system-arm qemu-efi

# 이미지 다운로드.
img=ubuntu-18.04-server-cloudimg-arm64.img
if [ ! -f "$img" ]; then
  wget "https://cloud-images.ubuntu.com/releases/18.04/release/${img}"
  qemu-img resize "$img" +60G
fi

# 암호 설정.
user_data=user-data.img
if [ ! -f "$user_data" ]; then
  cat >user-data <<EOF
#cloud-config
password: totoro
chpasswd: { expire: False }
ssh_pwauth: True
EOF
  cloud-localds "$user_data" user-data

  # EFI 사용:
  # https://wiki.ubuntu.com/ARM64/QEMU
  dd if=/dev/zero of=flash0.img bs=1M count=64
  dd if=/usr/share/qemu-efi/QEMU_EFI.fd of=flash0.img conv=notrunc
  dd if=/dev/zero of=flash1.img bs=1M count=64
fi

qemu-system-aarch64 \
  -M virt \
  -cpu cortex-a57 \
  -device rtl8139,netdev=net0 \
  -m 4096 \
  -netdev user,id=net0 \
  -nographic \
  -smp 4 \
  -drive "if=none,file=${img},id=hd0" \
  -device virtio-blk-device,drive=hd0 \
  -drive "file=${user_data},format=raw" \
  -pflash flash0.img \
  -pflash flash1.img \
;

login: ubuntu 
pw:totoro

ubuntu wayland manager qemu kvm 활성화

Unable to init server: Could not connect: Connection refused 

사용자 추가(sudo GUI + terminal)
xhost -si:localuser:root

$ xhost +si:localuser:root

GL에서 GPU 장치 선택

GL에서 GPU 장치 선택

OpenGL 자체가 렌더링 API임.
GLX, WGL, EGL과 같은 윈도우 시스템 바인딩 API는 수 많은 세월에 거쳐 만들어짐.
멀티 GPU 시스템이 찾기 어려웠던 시대...

멀티 GPU API는 제조사 마다 다르지만 MESA 솔루션의 DRI_PRIME를 통해 발전함.

DRI_PRIME란?
초창기의 DRI_PRIME는 2개의 GPU에서 동작 하도록 정의한 환경 변수.
응용 프로그램 호출하기 전에 1로 설정하면 GL 스택이 X서버로 쿼리하고 시스템에 있는 다른 GPU를 사용.

이러한 방법으르로 초기에 발전 함.
- 시스템에 GPU가 3개 이상 있을때?
- x 서버가 없는 시스템일 때?
- 응용 프로그램 개발시 사용할 GPU를 어떻게 선택해 사용할 것인가?

사용자 ID_PATH_TAG가 udev에서 제공 한대로 DRI_PRIME 장치를 나열하여 선택할 수 있다.
EGL의 확장 가능구조 덕분에 EGLDevice 계열의 확장을 통해 해결할 수 있음.

EGLDevice 입력
EGL_EXT_device_base 확장 측면에서 구현된 EGL_EXT_device_enumeration 및 EGL_EXT_device_query.

EGLDevice는 장치고유 속성을 나열해 질문하는 수단 인 EGLDevice의 개념 정의.
또 다른 두 개의 확장 EGL_EXT_device_drm 및 EGL_MESA_device_software은

각각의 하드웨어 DRM 장치 노드 및 소프트웨어와 백업 장치 정의
- 메사로 사용해 GL 구현.

사용 사례
확장 세트를 사용하려면 어떤 장치를 사용할지 명시 적으로 선택한다

그래픽 서버/윈도우 메이지먼트는 전력 소모가 적은 장치로 렌더링한다.
webGL 신뢰할 수 없는 장치로 분류 할 수 있고, 시간 기준으로 GPU 작업을 처리한다.

구현 상태

EGL_EXT_device_base- 구현 모두 EGL_EXT_device_enumeration와EGL_EXT_device_query
EGL_EXT_device_drm
EGL_MESA_device_software
EGL_EXT_platform_device

Cloud image amd64

1. Cloud image amd64
데스크탑 시스템 설치없이 직접 부팅 할 수있는 이미지임.
이게 가능한 이유는 https://help.ubuntu.com/community/CloudInit
여기 사이트에 설명 되어 있음.

즉 init 개념을 -> Cloudint 개념을 추가해 부팅 시퀀서를 만듬.

이미지 생성 스크립트
vi upstream.sh
#!/usr/bin/env bash

sudo apt-get install cloud-image-utils qemu qemu-system qemu-system-x86

# qcow2 형식.
img=ubuntu-18.04-server-cloudimg-amd64.img
if [ ! -f "$img" ]; then
  wget "https://cloud-images.ubuntu.com/releases/18.04/release/${img}"

  # sparse resize: 추가 공간을 사용하지 않고 나중 크기 변경 허용.
  # https://superuser.com/questions/1022019/how-to-increase-size-of-an-ubuntu-cloud-image
  qemu-img resize "$img" +128G
fi

user_data=user-data.img
if [ ! -f "$user_data" ]; then
  # 암호.
  # https://serverfault.com/questions/920117/how-do-i-set-a-password-on-an-ubuntu-cloud-image
  # https://askubuntu.com/questions/507345/how-to-set-a-password-for-ubuntu-cloud-images-ie-not-use-ssh
  cat >user-data <<EOF
#cloud-config
password: totoro
chpasswd: { expire: False }
ssh_pwauth: True
EOF
  cloud-localds "$user_data" user-data
fi

qemu-system-x86_64 \
  -drive "file=${img},format=qcow2" \
  -drive "file=${user_data},format=raw" \
  -device rtl8139,netdev=net0 \
  -enable-kvm \
  -m 2G \
  -netdev user,id=net0 \
  -serial mon:stdio \
  -smp 2 \
  -vga virtio \
;
:wq

QEMU 시작 후 부트 메뉴가 나타나면, 엔터 입력.

부트 메시지
error: no such device: root.

Press any key to continue...

특정 시간이 지나면 자동 부팅 됨.

사용자 이름: ubuntu
암호: totoro

인터넷 동작 확인.

callback test

/*
 * Callback.c - 연결 목록 콜백 구현
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct NODE {
struct NODE *link;
int data;
}Node;

Node **create_sll(const int);
void insert_data(Node **);
void show_list(Node **);
void sort_list(Node **);

int compare_ints(void const *, void const *); /* 프로토타입 함수 */
Node *search_list(Node *, void const *, int(void const *, void const *)); /* 프로토타입 */

int main(void){
int (*compare)(void const *, void const *) = compare_ints;

int value, val2find;
int nodes; /* 노트 카운트 */
Node **rootp; /* 루투 위치 */
Node *desired_node;

puts("\n**Program creates Singly Linked List**");
puts("**And allows users to perform various operations on the"
"list**\n");
puts("User, specify number of nodes in the list, in range 1"
" through some positive no.");
scanf("%d", &nodes);

rootp = create_sll(nodes);

printf("Les's insert %d integers in the list...\n", nodes);
insert_data(rootp);

puts("**Les's show up the list**");
show_list(rootp);

puts("Let's sort the list, in ascending order...");
sort_list(rootp);
puts("Let's show up the list**");
show_list(rootp);

puts("**Let's use Callback() function**");
printf("User, enter an integer you want to see into the "
"Singly Linked List...\n");
scanf("%d", &val2find);

/* 콜밸 함수 호출 */
desired_node = search_list(*rootp, &val2find, compare);

if(desired_node != NULL)
puts("Desired value is found.");
else
puts("Desired value NOT found.");
return 0;
}

Node *search_list(Node *node, void const *value, int compare(void const *, void const *)){
while(node != NULL){
if(compare(&node->data, value) == 0)
break;
node = node->link;
}

return node;
}

int compare_ints(void const *p2nv, void const *p2v){
if(*(int *)p2nv == *(int *)p2v)
return 0;
else
return 1;
}

Node **create_sll(const int nodes){
int i;
Node *current;
static Node *root;
Node **rootp = &root;

root = (Node *)malloc(nodes * sizeof(Node));

if(root == NULL){
puts("Error: Not Enough Memory!");
exit(1);
} else {
current = root;

for(i = 1; i <= nodes; i++){
if(i == nodes) {
current->link = NULL;
} else {
current->link = current + 1;
current++;
}
}
printf("List with %d nodes created successfully!\n", nodes);
puts("");
}
return rootp;
}

void insert_data(Node **linkp){
Node *next = *linkp;
Node *current;

do {
current = next;
scanf("%d", &(current->data));
next = current->link;
}while(current->link != NULL);
puts("");
}

void show_list(Node **linkp){
Node *next = *linkp;
Node *current;

do{
current = next;
printf("%d", current->data);
next = current->link;
}while(current->link != NULL);
puts("\n");
}

void sort_list(Node **linkp){
int temp;
Node *current = *linkp;
Node *next = current->link;

while(current->link != NULL){
while(next != NULL){
if(current->data > next->data){
temp = next->data;
next->data = current->data;
current->data = temp;
}
next = next->link;
}
current = current->link;
next = current->link;
}
}
/*
 * ./callback

**Program creates Singly Linked List**
**And allows users to perform various operations on thelist**

User, specify number of nodes in the list, in range 1 through some positive no.
5
List with 5 nodes created successfully!

Les's insert 5 integers in the list...
32
53
1
08
0556

**Les's show up the list**
325318556

Let's sort the list, in ascending order...
Let's show up the list**
183253556

**Let's use Callback() function**
User, enter an integer you want to see into the Singly Linked List...
53
Desired value is found */

2019/01/03

odroid sdcard ubuntu 설치

Ubuntu SD 카드 설치

파티션 정보 확인
fdisk -l

sd card( mmcblk0) 마운트 해제
umount /dev/sdx1

체크썸으로 img 파일 확인
md5sum odroidu2_20130104-linaro-ubuntu-desktop-uSDeMMC.img.xz
해쉬값 odroidu2_20130104-linaro-ubuntu-desktop-uSDeMMC.img.xz

압축 해제
xz -d odroidu2_20130104-linaro-ubuntu-desktop-uSDeMMC.img.xz

루트 파일 시스템 복사
sudo dd if=odroidu2_20130104-linaro-ubuntu-desktop-uSDeMMC.img of=/dev/sdx bs=4M

리눅스 vmware image 다운로드 사이트

개발 환경 구축시 집적 설치 하는 것도 좋지만, 빠르게 진행시... 걍 다운로드 받아 개발 환경 구축 하는게 정신 건강에 좋다.

http://www.trendsigma.net/vmware/

루트파일 시스템 이미지 업데이트 방법

루트 파일 시스템 업데이트
이미지용 루트 파일 시스템과, SD 카드의 루트 파일 시스템 구성 방법이 다름.
SD 카드는 전체적 내용이 있으며, 이미지는 부팅에 관한 구성만 있다.

이러한 구성 요소를 이해 하면, 윈도우 메니지먼트를 변경해 gui를 변경 할 수 있다.

부팅:
u-boot 환경 변수 동작
환경 변수에 따른 커널 로드.
커널 initrd -> init 루트 파일 시스템 로드.

rootfs:
배포판 구성 패키지 방법.

루트 파일 시스템 이미지 사용 업데이트 방법
cd /media
# 체크썸 파일
sudo wget http://odroid.us/odroid/odroidu2/ubuntu/odroidu2_20130104-linaro-lbuntu-desktop-1-rootfs.tgz.md5sum
# 루트파일 다운로드
sudo wget http://odroid.us/odroid/odroidu2/ubuntu/odroidu2_20130104-linaro-lbuntu-desktop-1-rootfs.tgz
# 압축 파일 체크
md5sum -c odroidu2_20130104-linaro-lbuntu-desktop-1-rootfs.tgz.md5sum

SD 카드 이동
cd /media/rootfs

SD 카드 내용 삭제
/media/rootfs# sudo rm -rf *

다운로드 받은 파일. 압축해제
sudo tar -xvzf ../odroidu2_20130104-linaro-lbuntu-desktop-1-rootfs.tgz
cd ..
sync

마운트 해제
sudo umount /dev/sdX2

루트 파일 시스템 백업
SD Card 루트 파일 시스템 백업

SD 카드를 호스트에 마운트.
cd /media/rootfs
tar -cvzf ../my-backup-rootfs.tgz
sync

cd ../
umount /media/rootfs

sdcard 루트 파일 시스템 추출
sudo apt-get install parted

루트 파일 시스템 이미지 파일 정보 확인.(개발 또는 사용할 이미지 이름 사용)

parted -s 개발용_odroid_보드-uSDeMMC.img unit B print
1      1572864B   35127295B    33554432B    primary  fat16
2      35127296B  5874122751B  5838995456B  primary  ext4

fat16 : dos 파일 시스템
ext4 : 리눅스 파일 시스템

파티션 시작 정보 확인.
두 번째 ext4 offwet 주소 35127296 시작 확인
mkdir mnt
sudo mount -o loop,ro,offset=35127296 개발용_odroid_보드-uSDeMMC.img mnt

파일 압축
cd mnt
sudo tar -cvzf ../rootfs.tgz .
cd ..
sudo umount mnt

odroid qemu ubuntu 18.04 sdcard 동작

참고: https://nautiluslee.blogspot.com/2019/01/ubuntu-1804-odroid-qemu.html

우분투 실행
SD Card 루트 파일 시스템 백업
SD 카드를 호스트에 마운트.

cd /media/rootfs

tar -cvzf ../my-backup-rootfs.tgz
sync

cd ../
umount rootfs

sdcard 루트 파일 시스템 추출
sudo apt-get install parted
루트 파일 시스템 이미지 파일 정보 확인.(개발 또는 사용할 이미지 이름 사용)

parted -s 개발용_odroid_보드-uSDeMMC.img unit B print

1      1572864B   35127295B    33554432B    primary  fat16
2      35127296B  5874122751B  5838995456B  primary  ext4

fat16 : dos 파일 시스템
ext4 : 리눅스 파일 시스템

파티션 시작 정보 확인.
두 번째 ext4 offwet 주소 35127296 시작 확인

mkdir mnt
sudo mount -o loop,ro,offset=35127296 개발용_odroid_보드-uSDeMMC.img mnt

파일 압축
cd mnt
sudo tar -cvzf ../rootfs.tgz .
cd ..
sudo umount mnt

mv rootfs.tgz rootfs-ubuntu.ext4

부팅 시작 스크립트
#! /bin/sh
# filename launch-ubuntu
ROOTFS=rootfs-ubuntu.ext4
NETWORK="-net nic,vlan=0 -net tap,vlan=0,ifname=tap0,script=no"
#NETWORK="-net nic -net user"
KERNEL="-kernel zImage "

qemu-system-arm -append "root=/dev/mmcblk0 rw physmap.enabled=0 console=ttyAMA0" -M vexpress-a9 $KERNEL -sd $ROOTFS  $NETWORK -serial stdio

실행
./launch-ubuntu

# UNCONFIGURED FSTAB FOR BASE SYSTEM

UUID=e139ce78-9841-40fe-8823-96a304a09859 / ext4  errors=remount-ro,noatime 0 1
/dev/mmcblk0p1 /media/boot vfat defaults 0 1

To:
# UNCONFIGURED FSTAB FOR BASE SYSTEM

/dev/mmcblk0 / ext4  errors=remount-ro,noatime 0 1

qemu-system-arm 명령어를 사용해 그래픽 모드 활성화

ubuntu 18.04 odroid qemu 테스트 개발 환경 구축

패키지 업데이트 및 필요한 패키지 설치
apt-get update
sudo apt-get install libpixman-1-dev zlib1g-dev libglib2.0-dev shtool build-essential

테스트할 파일 다운로드
작업 디렉토리 생성
mkdir odroidu2
cd odroidu2/

다운로드 및 압축해제.
wget http://odroid.us/odroid/users/osterluk/qemu-example/qemu-example.tgz
tar -xvf qemu-example.tgz

압출파일 설명
launch : 호스트 환경 네트워크 인터페이스 공유해 전체 네트워킹 지원을 스크립트
launch-no-bridge : 가상 LAN 루트파일 시스템 동작.
launch-ubuntu : ext4 SD 카드 이미지 추출
rootfs-buildroot.ext2 : rootfs.tar.gz에서 변환된 ext2 루트 파일 시스템 파티션
rootfs.tar.gz : 루트파일 시스템
vexpress_defconfig : 튜토리얼 사용되는 커널 zImage
vexpress_odroid_qemu_defconfig : 튜토리얼에서 사용 zImage
zImage : linux-3.2 커널 소스에서 vexpress-a9 머신 용으로 빌드 된 커널.

qemu 설치.
sudo apt install qemu-system-arm

qemu 버전 확인.
qemu-system-arm --version
QEMU emulator version 2.12.0 (Debian 1:2.12+dfsg-3ubuntu4+ppa1)
Copyright (c) 2003-2017 Fabrice Bellard and the QEMU Project developers

cortex-9 지원 여부 확인
qemu-system-arm -cpu ? | grep cortex-a9

cpu 유형 확인.
qemu-system-arm -M ? | grep vexpress-a9

최신 버전 설치
sudo apt-get install qemu

현재 우분투 18.04 재공하는 패키지에서는 cotex-a9 지원 없음.
qemu 컴파일
sudo apt-get install libpixman-1-dev zlib1g-dev libglib2.0-dev shtool build-essential

소스 다운로드
cd $HOME
mkdir qemu-build
cd qemu-build

wget http://wiki.qemu-project.org/download/qemu-3.0.0.tar.bz2
tar -xvf qemu-3.0.0.tar

cd $HOME/qemu-build/qemu-3.0.0
./configure --prefix=/usr/local --static --disable-kvm --target-list=arm-linux-user
make
sudo make install

설치 경로 확인
which qemu-arm

정적 파일이름 변경
sudo mv /usr/local/bin/qemu-arm /usr/local/bin/qemu-arm-static

동적 컴파일
cd $HOME/qemu-build/qemu-3.0.0
./configure --enable-system --prefix=/usr/local --disable-kvm --target-list=arm-linux-user
make
sudo make install

버전 확인
qemu-system-arm --version
QEMU emulator version 2.12.0 (Debian 1:2.12+dfsg-3ubuntu4+ppa1)
Copyright (c) 2003-2017 Fabrice Bellard and the QEMU Project developers

cpu 지원 확인
qemu-system-arm -M ? | grep vexpress
vexpress-a15         ARM Versatile Express for Cortex-A15
vexpress-a9          ARM Versatile Express for Cortex-A9

busybox 루트 파일 시스템 생성
cd $HOME/odroidu2
qemu-img create rootfs-buildroot.ext2 200M

ext2 파일 시스템 생성
sudo mkfs.ext2 rootfs-buildroot.ext2

mke2fs 1.44.1 (24-Mar-2018)
Discarding device blocks: done                           
Creating filesystem with 204800 1k blocks and 51200 inodes
Filesystem UUID: 36a430ea-6396-4ac8-be2e-33cea4ecf301
Superblock backups stored on blocks:
8193, 24577, 40961, 57345, 73729

Allocating group tables: done                           
Writing inode tables: done                           
Writing superblocks and filesystem accounting information: done

루트 파일 시스템 마운트
mkdir mnt
sudo mount -o loop rootfs-buildroot.ext2 mnt

루트 파일 시스템 압축해제
cd mnt
sudo tar -xvzf ../rootfs.tar.gz
ls
bin  dev  etc  home  lib  linuxrc  lost+found  media  mnt  opt  proc  root  run  sbin  sys  tmp  usr  var

마운트 해제
cd ../
sudo umount ./mnt

네트워 브리지 설정
cat launch-no-bridge

#! /bin/sh
# filename: launch-no-bridge
# Set environment variables to make it easier to change
export ROOTFS=rootfs-buildroot.ext2
export NETWORK="-net nic -net user"
export KERNEL="-kernel zImage "

qemu-system-arm -append "root=/dev/mmcblk0 rw physmap.enabled=0 console=ttyAMA0" -M vexpress-a9 $KERNEL -sd $ROOTFS  $NETWORK -nographic

부팅 로그인: root
./launch-no-bridge
Welcome to Buildroot
odroidu2-1 login: root
#

ubuntu 18.04 vmware 15.0 pro install

wget -O ~/vmware.bin https://www.vmware.com/go/getworkstation-linux

sudo apt install build-essential
sudo bash ~/vmware.bin

cd key는 구매 또는 검색으로 찾아야 할 듯 함.

크로스 컴파일 테스트

 테스트
$ aarch64-linux-g++ -v
Using built-in specs.
COLLECT_GCC=aarch64-linux-g++
COLLECT_LTO_WRAPPER=/opt/cross/libexec/gcc/aarch64-linux/4.9.2/lto-wrapper
Target: aarch64-linux
Configured with: ../gcc-4.9.2/configure --prefix=/opt/cross --target=aarch64-linux --enable-languages=c,c++ --disable-multilib
Thread model: posix
gcc version 4.9.2 (GCC)

$ aarch64-linux-g++ -std=c++14 test.cpp
$ aarch64-linux-objdump -d a.out
...
0000000000400830 <main>:
  400830:       a9be7bfd        stp     x29, x30, [sp,#-32]!
  400834:       910003fd        mov     x29, sp
  400838:       910063a2        add     x2, x29, #0x18
  40083c:       9000

크로스 컴파일러 제작 스크립트.

변경 이력
TARGET=aarch64-elf
USE_NEWLIB=1
CONFIGURATION_OPTIONS="--disable-multilib --disable-threads"

자동 스크립트
#! /bin/bash
set -e
trap 'previous_command=$this_command; this_command=$BASH_COMMAND' DEBUG
trap 'echo FAILED COMMAND: $previous_command' EXIT

#-------------------------------------------------------------------------------------------
# 이 스크립트는 GCC 크로스 컴파일러의 패키지 다운로드, 구성, 빌드.
#-------------------------------------------------------------------------------------------

INSTALL_PATH=/opt/cross
TARGET=aarch64-linux
USE_NEWLIB=0
LINUX_ARCH=arm64
CONFIGURATION_OPTIONS="--disable-multilib" # --disable-threads --disable-shared
PARALLEL_MAKE=-j4
BINUTILS_VERSION=binutils-2.24
GCC_VERSION=gcc-4.9.2
LINUX_KERNEL_VERSION=linux-3.17.2
GLIBC_VERSION=glibc-2.20
MPFR_VERSION=mpfr-3.1.2
GMP_VERSION=gmp-6.0.0a
MPC_VERSION=mpc-1.0.2
ISL_VERSION=isl-0.12.2
CLOOG_VERSION=cloog-0.18.1
export PATH=$INSTALL_PATH/bin:$PATH

# 패키지 다운로드
export http_proxy=$HTTP_PROXY https_proxy=$HTTP_PROXY ftp_proxy=$HTTP_PROXY
wget -nc https://ftp.gnu.org/gnu/binutils/$BINUTILS_VERSION.tar.gz
wget -nc https://ftp.gnu.org/gnu/gcc/$GCC_VERSION/$GCC_VERSION.tar.gz
if [ $USE_NEWLIB -ne 0 ]; then
    wget -nc -O newlib-master.zip https://github.com/bminor/newlib/archive/master.zip || true
    unzip -qo newlib-master.zip
else
    wget -nc https://www.kernel.org/pub/linux/kernel/v3.x/$LINUX_KERNEL_VERSION.tar.xz
    wget -nc https://ftp.gnu.org/gnu/glibc/$GLIBC_VERSION.tar.xz
fi
wget -nc https://ftp.gnu.org/gnu/mpfr/$MPFR_VERSION.tar.xz
wget -nc https://ftp.gnu.org/gnu/gmp/$GMP_VERSION.tar.xz
wget -nc https://ftp.gnu.org/gnu/mpc/$MPC_VERSION.tar.gz
wget -nc ftp://gcc.gnu.org/pub/gcc/infrastructure/$ISL_VERSION.tar.bz2
wget -nc ftp://gcc.gnu.org/pub/gcc/infrastructure/$CLOOG_VERSION.tar.gz

# 압축해제
for f in *.tar*; do tar xfk $f; done

# 심볼링크
cd $GCC_VERSION
ln -sf `ls -1d ../mpfr-*/` mpfr
ln -sf `ls -1d ../gmp-*/` gmp
ln -sf `ls -1d ../mpc-*/` mpc
ln -sf `ls -1d ../isl-*/` isl
ln -sf `ls -1d ../cloog-*/` cloog
cd ..

# Step 1. 구성 환경 설정 적용
mkdir -p build-binutils
cd build-binutils
../$BINUTILS_VERSION/configure --prefix=$INSTALL_PATH --target=$TARGET $CONFIGURATION_OPTIONS
make $PARALLEL_MAKE
make install
cd ..

# Step 2. 커널 헤더
if [ $USE_NEWLIB -eq 0 ]; then
    cd $LINUX_KERNEL_VERSION
    make ARCH=$LINUX_ARCH INSTALL_HDR_PATH=$INSTALL_PATH/$TARGET headers_install
    cd ..
fi

# Step 3. C/C++ 컴파일러
mkdir -p build-gcc
cd build-gcc
if [ $USE_NEWLIB -ne 0 ]; then
    NEWLIB_OPTION=--with-newlib
fi
../$GCC_VERSION/configure --prefix=$INSTALL_PATH --target=$TARGET --enable-languages=c,c++ $CONFIGURATION_OPTIONS $NEWLIB_OPTION
make $PARALLEL_MAKE all-gcc
make install-gcc
cd ..

if [ $USE_NEWLIB -ne 0 ]; then
    # Steps 4-6: Newlib
    mkdir -p build-newlib
    cd build-newlib
    ../newlib-master/configure --prefix=$INSTALL_PATH --target=$TARGET $CONFIGURATION_OPTIONS
    make $PARALLEL_MAKE
    make install
    cd ..
else
    # Step 4. C 스텐다드 헤더 및 라이브러리
    mkdir -p build-glibc
    cd build-glibc
    ../$GLIBC_VERSION/configure --prefix=$INSTALL_PATH/$TARGET --build=$MACHTYPE --host=$TARGET --target=$TARGET --with-headers=$INSTALL_PATH/$TARGET/include $CONFIGURATION_OPTIONS libc_cv_forced_unwind=yes
    make install-bootstrap-headers=yes install-headers
    make $PARALLEL_MAKE csu/subdir_lib
    install csu/crt1.o csu/crti.o csu/crtn.o $INSTALL_PATH/$TARGET/lib
    $TARGET-gcc -nostdlib -nostartfiles -shared -x c /dev/null -o $INSTALL_PATH/$TARGET/lib/libc.so
    touch $INSTALL_PATH/$TARGET/include/gnu/stubs.h
    cd ..

    # Step 5. 컴파일러 지원 라이브러리
    cd build-gcc
    make $PARALLEL_MAKE all-target-libgcc
    make install-target-libgcc
    cd ..

    # Step 6. Glibc
    cd build-glibc
    make $PARALLEL_MAKE
    make install
    cd ..
fi

# Step 7. C++ 라이브러리 GCC
cd build-gcc
make $PARALLEL_MAKE all
make install
cd ..

trap - EXIT
echo 'Success!'