카테고리

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/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" \
;