카테고리

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/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!'

크로스 컴파일러 제작.

GCC 크로스 컴파일러 만들기

build system : Linux
Host system : Linux
Target system : Linux

필수 패키지 설치
$ sudo apt-get install g++ make gawk

소스 코드 다운로드
http://ftp.kaist.ac.kr/gnu/binutils/
$ wget http://ftpmirror.gnu.org/binutils/binutils-2.24.tar.gz
$ wget http://ftpmirror.gnu.org/gcc/gcc-4.9.2/gcc-4.9.2.tar.gz
$ wget https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.17.2.tar.xz
$ wget http://ftpmirror.gnu.org/glibc/glibc-2.20.tar.xz
$ wget http://ftpmirror.gnu.org/mpfr/mpfr-3.1.2.tar.xz
$ wget http://ftpmirror.gnu.org/gmp/gmp-6.0.0a.tar.xz
$ wget http://ftpmirror.gnu.org/mpc/mpc-1.0.2.tar.gz
$ wget ftp://gcc.gnu.org/pub/gcc/infrastructure/isl-0.12.2.tar.bz2
$ wget ftp://gcc.gnu.org/pub/gcc/infrastructure/cloog-0.18.1.tar.gz

프로젝트 사이트 정의
Binutils: https://www.gnu.org/software/binutils/
GCC: https://gcc.gnu.org/
Linux kernel: https://www.kernel.org/
Glibc : https://www.gnu.org/software/libc/

크로스 컴파일 구성 방법
Host Programs: X64
C Cross-Compile: aarch64-linux-gcc Built from GCC
C++ Cross-Compiler: aarch64-linux-g++ built from GCC
CROSS-Assember Cross-Link: aarch64-linux-as, aarch64-linux-ld, built from Binutils

Target Programs & libraries : AArch64
a.out: sample program
Standard C++ Library: libstdc++.so built from GCC
Standard C Library : libc.so, built from Glibc
Linux Kernel

Glibc 과련 사이트
Newlib: https://sourceware.org/newlib/
Libgolss: http://ieee.uwaterloo.ca/coldfire/gcc-doc/docs/porting_1.html

빌드
압축 해제
$ for f in *.tar*; do tar xf $f; done

gcc 심볼링크 생성
gcc 의존성 때문에 심볼링크 설정 해주면 자동으로 의존성을 해결함.
https://gcc.gnu.org/install/download.html

$ cd gcc-4.9.2
$ ln -s ../mpfr-3.1.2 mpfr
$ ln -s ../gmp-6.0.0 gmp
$ ln -s ../mpc-1.0.2 mpc
$ ln -s ../isl-0.12.2 isl
$ ln -s ../cloog-0.18.1 cloog
$ cd ..

툴 체인 설치 위치 지정
$ sudo mkdir -p /opt/cross
$ sudo chown jeff /opt/cross

패스 지정.
$ export PATH=/opt/cross/bin:$PATH

1. 빌드
$ mkdir build-binutils
$ cd build-binutils
$ ../binutils-2.24/configure --prefix=/opt/cross --target=aarch64-linux --disable-multilib
$ make -j4
$ make install
$ cd ..

$ cd linux-3.17.2
$ make ARCH=arm64 INSTALL_HDR_PATH=/opt/cross/aarch64-linux headers_install
$ cd ..

$ mkdir -p build-gcc
$ cd build-gcc
$ ../gcc-4.9.2/configure --prefix=/opt/cross --target=aarch64-linux --enable-languages=c,c++ --disable-multilib
$ make -j4 all-gcc
$ make install-gcc
$ cd ..

--target=aarch64-linux 지정
--disable-multilib 64비트 명령어 세트 사용, 32 명령어 세트 사용하지 않음.

2. 리눅스 커널 헤더
/opt/cross/aarch64-linux/include 새로운 툴 체인을 사용하여 빌드, 시스템 호출 할 수 있게 환경 적용
$ cd linux-3.17.2
$ make ARCH=arm64 INSTALL_HDR_PATH=/opt/cross/aarch64-linux headers_install
$ cd ..

GCC components:
- C/C++ Compilers
-- aarch64-linux-gcc
-- aarch64-linux-g++ ----> Build Order
                           Glibc Components:
    Standard C Library Headers and Startup Files
stdio.h, stdlib.h pthread.h,...
crti.o crtn.o crtl.o/libc.so
                       <----+
Compile Support Library
- Libgcc.a/libgcc.so ------> Standard C Library:
                              libc.a/libc.so
                    <---------+
Standard C++ Library
libstdc++.a/libstdc++.so

3. C/C++ 컴파일

$ mkdir -p build-glibc
$ cd build-glibc
// 20180103 이 옵션 사용.
$ ../gcc-4.9.2/configure --prefix=/opt/cross --target=aarch64-linux --enable-languages=c,c++ --disable-multilib
$ make -j4 all-gcc
$ make install-gcc
$ cd ..

--target=aarch64-linux : 타켓 이름 지정(aarch64-linux)
--enable-languages=c,c++: Fortran, Go 또는 Java와 같은 GCC 제품군의 다른 컴파일러가 빌드되지 않도록한다.

4. 표준 C 라이브러리 및 헤더
Glibc의 표준 C 라이브러리 헤더 opt/cross/aarch64-linux/include 설치한다.
라이브러리는 설치 경로 /opt/cross/aarch64-linux/lib.

$ mkdir -p build-glibc
$ cd build-glibc
$ ../glibc-2.20/configure --prefix=/opt/cross/aarch64-linux --build=$MACHTYPE --host=aarch64-linux --target=aarch64-linux --with-headers=/opt/cross/aarch64-linux/include --disable-multilib libc_cv_forced_unwind=yes
$ make install-bootstrap-headers=yes install-headers
$ make -j4 csu/subdir_lib
$ install csu/crt1.o csu/crti.o csu/crtn.o /opt/cross/aarch64-linux/lib
$ aarch64-linux-gcc -nostdlib -nostartfiles -shared -x c /dev/null -o /opt/cross/aarch64-linux/lib/libc.so
$ touch /opt/cross/aarch64-linux/include/gnu/stubs.h
$ cd ..

--prefix=/opt/cross/aarch64-linuxGlibc의 configure 스크립트에서 헤더와 라이브러리 설치 위지 설정
--build, --host및 --target시스템 유형
$MACHTYP 미리 정의 된 환결 변수
--build=$MACHTYP : 추가 도구 컴파일

5. 컴파일러 지원 라이브러리.
http://www.ifp.illinois.edu/~nakazato/tips/xgcc.html --> 이 구성에서 추가된 방식으로 진행.

$ cd build-gcc
$ make -j4 all-target-libgcc
$ make install-target-libgcc
$ cd ..

두 정적 라이브러리 libgcc.a, libgcc_eh.a 설치
/opt/cross/lib/gcc/aarch64-linux/4.9.2/.

공유 라이브러리 /opt/cross/aarch64-linux/lib64/libgcc_s.so 설치

6. 표준 C 라이브러리
/opt/cross/aarch64-linux/lib/lib.a
/opt/cross/aarch64-linux/lib/libc.so

$ cd build-glibc
$ make -j4
$ make install
$ cd ..

7. 표준 C++ 라이브러리
/opt/cross/aarch64-linux/lib64/libstdc++.a
/opt/cross/aarch64-linux/lib64/libstdc++.so

$ cd build-gcc
$ make -j4
$ make install
$ cd ..

Ubuntu 18.04 64 비트 GCC 8.2 버전 컴파일

GCC 빌드하기
Ubuntu 18.04 64 비트 GCC 8.2 버전 컴파일

업데이트
sudo apt-get update
sudo apt-get upgrade

코드 다운로드
cd ~
wget https://ftpmirror.gnu.org/gcc/gcc-8.2.0/gcc-8.2.0.tar.gz
tar xf gcc-8.2.0.tar.gz
cd gcc-8.2.0
contrib/download_prerequisites

환경 구성
cd ~
mkdir build && cd build
../gcc-8.2.0/configure -v --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --prefix=/usr/local/gcc-8.2 --enable-checking=release --enable-languages=c,c++,fortran --disable-multilib --program-suffix=-8.2

적용 -j 8 cpu 코어 확인
make -j 8

설치
sudo make install

실행 경로 추가
export export PATH=/usr/local/gcc-8.2/bin:$PATH
export LD_LIBRARY_PATH=/usr/local/gcc-8.2/lib64:$LD_LIBRARY_PATH

.bashrc 추가
cd ~
vi .bashrc
export export PATH=/usr/local/gcc-8.2/bin:$PATH
export LD_LIBRARY_PATH=/usr/local/gcc-8.2/lib64:$LD_LIBRARY_PATH

// C++14 일반화 된 람다(매개변수 유형 auto 사용)
// https://solarianprogrammer.com/2014/08/21/cpp-14-auto-tutorial/
#include <iostream>
int main() {
    std::cout << [](auto a, auto b) { return a + b; } (5, 6) << std::endl;
    std::cout << [](auto a, auto b) { return a + b; } (5.23, 6.45) << std::endl;
    return 0;
}

컴파일
g++-8.2 -Wall -pedantic test_lambda.cpp -o test_lambda
./test_lambda

static_assert 수정 예제 테스트
// https://solarianprogrammer.com/2014/08/21/cpp-14-auto-tutorial/
#include <type_traits>
#include <iostream>
struct A {
int foo;
};

struct B {
int foo = 0;
};

template <typename T>
void print(const T& a){
static_assert(std::is_pod<T>::value);
std::cout << a.foo << '\n';
}

int main() {
A x{1};
B y{2};
B z;

print<A>(x);
print<B>(y);
print<B>(z);

return 0;
}

컴파일
g++-8.2 -std=c++17 -Wall -pedantic test_assert.cpp -o test_assert
 test_assert.cpp: In instantiation of ‘void print(const T&) [with T = B]’:
 test_assert.cpp:24:15:   required from here
 test_assert.cpp:14:5: error: static assertion failed
     static_assert(std::is_pod<T>::value);
     ^~~~~~~~~~~~~

Fortran 프로그래머라면 gfortran-8.2와 병행 하여 다음과 같은 Fortran 2008 기능 중 일부를 사용할 수 있음.

integer,parameter::mm=100000
real::a(mm), b(mm)
real::fact=0.5

! initialize the arrays
! ...

do concurrent (i = 1 : mm)
a(i) = a(i) + b(i)
enddo

end

컴파일 테스트
gfortran-8.2 test_concurrent_do.f90 -o test_concurrent_do
./test_concurrent_do

전처리기

전처리기
#define 전 처리기 지시문으로 프로그램에서 상수 값을 정의하는데 사용된다.

#pragma -> 컴파일 옵션 조절 키워드.
#pragma pack -> 메모리 패킹(펜딩) 처리.
#pragma once -> 헤더 중복 방지.

지시문 구문
#define macro_name value

기본 사용 예
#include<stdio.h>
#define PI 3.14 // 3.14 PI 정의
void main()
{
int r;
float area;

printf("Enter radius : ");
scanf("%d",&r);

area = PI * r * r;

printf("\nArea of circle is : %f",area);
}

Output :

Enter radius : 5
Area of circle is : 78.5

기본 사용 예
#include<stdio.h>
#define SIZE 5 // 5를 SIZE
void main()
{
int arr[SIZE];


for(int i=0;i<SIZE;i++)
{
printf("Enter any number : ");
scanf("%d",&arr[i]);
}

for(i=0;i<SIZE;i++)
printf("%d, ",arr[i]);

}

Output :

Enter any number : 78
Enter any number : 45
Enter any number : 12
Enter any number : 89
Enter any number : 56

78, 45, 12, 89, 56,

기본 사용 예
#include<stdio.h>
#define SQUARE(x)       x*x // 가로 * 세로 = 넓이, 함수와 사용시 연산자 우선 순위 확인
void main()
{
int num;


printf("Enter any number : ");
scanf("%d",&num);

printf("\nThe square is : %d",SQUARE(num));

}

Output :
Enter any number : 5
The square is : 25

#include 전 처리기 지시문의 구문
#include "filename.h"
or
#include <filename.h>

# if- # else- # endif 전처리 지시문

조건이 true이면 #if와 #else 사이에 제공된 명령문이 실행.
조건이 거짓이면 #else와 #endif 사이에 주어진 명령문이 실행

#if(condition)
- - - - - - - - - -
- - - - - - - - - -
#else
- - - - - - - - - -
- - - - - - - - - -
#endif

# if- # else- # endif 전처리 지시문의 예
#include<stdio.h>
#define MAX 45
void main()
{
#if MAX > 40
printf("Yes, MAX is greater then 40.");
#else
printf("No, MAX is not greater then 40.");
#endif
}

Output :
Yes, MAX is Greater then 40.


#elif 전 처리기 지시문
여러 조건을 검사하는 데 사용
첫 번째 조건이 만족스럽지 않으면 컴파일러는 #else 블록으로 건너 뛰고 다른 조건이 참인지 여부 등을 확인

# if- # elif- # else- # endif 전 처리기 지시문의 구문
#if(condition)
- - - - - - - - - -
- - - - - - - - - -
#elif(condition)
- - - - - - - - - -
- - - - - - - - - -
#elif(condition)
- - - - - - - - - -
- - - - - - - - - -
#else
- - - - - - - - - -
- - - - - - - - - -
#endif

# if- # elif- # else- # endif 전처리 지시문의 예
#include<stdio.h>
#define MKS 65
void main()
{

#if MKS>=78
printf("\nGrade A");

#elif MKS>=50
printf("\nGrade B");

#elif MKS>=25
printf("\nGrade C");

#else
printf("\nGrade D");

#endif

}

Output :

Grade B

#ifdef 전처리 지시문
매크로 이름이 이전에 정의되었는지 여부를 확인하는 데 사용
정의 된 경우 #ifdef와 #else 사이에 제공된 명령문이 실행

#ifdef 전 처리기 지시문의 구문
#ifdef macro-name
- - - - - - - - - -
- - - - - - - - - -
#else
- - - - - - - - - -
- - - - - - - - - -
#endif

#ifdef 전 처리기 지시문의 예
#include<stdio.h>
#define MKS 65
void main()
{

#ifdef MONTH
printf("\nMONTH is defined.");

#else
printf("\nMONTH is not defined.");

#endif

}

Output :
MONTH is not defined.

#ifndef 전처리 지시문
매크로 이름이 이전에 정의되었는지 여부를 확인하는 데 사용되며 정의되지 않은 경우 #ifndef와 #else 사이에 제공된 명령문이 실행

#ifndef 전처리 지시문의 구문
#ifndef macro-name
- - - - - - - - - -
- - - - - - - - - -
#else
- - - - - - - - - -
- - - - - - - - - -
#endif

#ifndef 전 처리기 지시문의 예
#include<stdio.h>
#define MKS 65
void main()
{
#ifndef MAX
printf("\nMAX is not defined.");

#else
printf("\nMAX is defined.");

#endif
}

Output :
MAX is not defined.

#line 전처리 지시문
#line 전처리 지시문은 사전 정의 된 매크로 이름 __LINE__ 및 __FILE__의 기본값을 덮어 쓰는 데 사용
defalut으로 __LINE__은 현재 줄 번호를 표시하고 __FILE__은 현재 파일 이름을 표시

#line 전 처리기 지시어 1의 예 :
#include<stdio.h>
void main()
{
printf("\nLine number %d",__LINE__);
printf("\nFile name %s",__FILE__);
}

Output :
Line number : 4
File name : LineDemo.c

#line 전 처리기 지시어 2의 예 :
#include<stdio.h>
#line 25 Demo.c
void main()
{
printf("\nLine number %d",__LINE__);
printf("\nFile name %s",__FILE__);
}

Output :
Line number : 25
File name : Demo.c

#error 전 처리기 지시문
컴파일러가 컴파일을 중지하고 치명적인 오류를 발생하게 함.

#error 전 처리기 지시어 1의 예 :
#include<stdio.h>
void main()
{
#ifndef MAX
printf("\nMAX is not defined.");        //Statement   1
#else
printf("\nMAX is defined.");            //Statement   2
#endif
printf("\nEnd of program.");            //Statement   3
}

Output :

MAX is not defined.
End of program.

#error 전처리 지시어 2의 예 :
#include<stdio.h>
void main()
{
#ifndef MAX
#error MAX is not defined.               //Statement   1
#else
printf("\nMAX is defined.");               //Statement   2
#endif

printf("\nEnd of program.");                    //Statement   3
}
예제 1과 2의 유일한 차이는 문장 하나다.
예제 1에서 문장 1은 메시지를 표시하고 나머지 코드를 계속 컴파일합니다.
예제 2에서, 문장 1은 컴파일러에게 치명적인 에러를 주게하고 나머지 코드의 컴파일을 중단합니다.

파입 입출력

파일 입출력
모든 프로그램은 실행시 메모리에 올라간다.
주 메모리는 휘발성이므로 프로그램이 종료되면 데이터가 사라지게 된다.
만얀 동일한 데이터가 필요하면 디스크에 파일을 저장해 손실을 막는다

C에서 지원하는 파일 형식:
- 텍스트 파: 사람이 확인 읽을 수 있는 내용.(아스키, 유니코드)
- 이진 파일: 사람이 직관적으로 확인 할 수 없는 내용.

파일 포인터
FILE * fp;

파일 접근 방법.
fp = fopen(char *filename,char *mode);

void main()
{
FILE *fp;

fp = fopen("file1.txt","r");      //Statement   1

if(fp == NULL)
{
printf("\nCan't open file or file doesn't exist.");
exit(0);
}
}


int fclose( FILE* );
void main()
{
FILE *fp;

fp = fopen("file1.txt","r");

if(fp == NULL)
{
printf("\nCan't open file or file doesn't exist.");
exit(0);
}
- - - - - - - - - -
- - - - - - - - - -
fclose(fp);
}

파일 시스템

하드디시크 구성(트랙, 섹터)

Track * Sector = 2차원 배열

File
사용자 모드 추상화
사용자 모드와 커너 모드의 디바이스 통신은 모두 파일로 이루어짐.
파일을 얼마나 잘 사용하는야에 따라 시스템 프로그램 고수와 하수로 나뉘어 진다.

자료구죠 키워드 정리.

나열 방법 -> 탐색 및 검색을 잘 하게 하는 알고리즘 구조

선형: 연결 리스트, stack, queue, dequeu
비선형: Tree

stack
push: pop == 입력 방향, 출력방향이 하나임. 입출구가 하나인 박스공간.

Queue: 줄서기
Push:Pop == 단방향

Dequeu: 상호작용
Push:Pop == 양방향
a) 선택 정렬
->선택 정렬은 비교는 많지만, 교환은 적은 알고리즘이다.
 장점: 정렬된 상태를 역순으로 정렬시 효율적이다.
 단점: 정렬된 데이터에 소수의 데이터 추가시 이를 다시 정렬하기 위해서는 최악이다.

$ cat ages.txt
Bob 12
Jane 48
Mark 3
Tashi 54

$ sort -k2 -n ages.txt
Mark 3
Bob 12
Jane 48
Tashi 54

sort -n -k 7 /path/to/input
find . -type f -iname "pattern*" -ls |sort -n -k 7
find . -type f -iname "pattern*" -ls |sort -r -n -k 7

-r -정렬 결과를 반대.
-n -숫자 정렬
-k 7 -POS1에서 키 시작 즉, 7 번에서 정렬 키 시작
-s 정렬 안정화

b) 버블 정렬
시간복잡도: O(N^2)

->데이터를 하나씩 비교할 수 있어서 정밀하게 비교 가능하나 비교횟수가 많아지므로
성능면에서 좋은 방법이 아니다. 첫번째 원소부터 마지막 원소까지 비교가 끝나면 가장 큰 원소를 마지막 자리로 정렬한다.

# Bash 배열 정렬
# Bubble 정렬 사용
 
# 정적 배열 입력
arr = (10 8 20 100 12)
 
echo "Array in original order"
echo ${arr[*]}
 
# 버블 정렬 수행 
for ((i = 0; i<5; i++))
do
     
    for((j = i; j<5-i-1; j++))
    do
     
        if ((${arr[j]} > ${arr[$((j+1))]}))
        then
            # swap
            temp = ${arr[$j]}
            arr[$j] = ${arr[$((j+1))]} 
            arr[$((j+1))] = $temp
        fi
    done
done
 
echo "Array in sorted order :"
echo ${arr[*]}

출력 :
Array in sorted order :
8 10 12 20 100

c) 퀵정렬 >
시간복잡도
최악- O(N^2)
평균- O(NlogN)

->캐시라는 지역적 특성에 의해 실제적으로 NlogN보다 좋은 성능을 보여 가장 많이 사용하는 정렬이다. 단점으로는 안정성이없다. 안정성이 없다는 것은 정렬되기 이전의 데이터 동일한 데이터끼리의 순서를 정렬 후에도 유지하고 있는가이다.

d) 삽입정렬 >
시간복잡도 : O(N^2)

버블정렬이 조금 비효율적인 면이 있기에 비교횟수를 효율적으로 줄이기 위해 고안된 삽입정렬이다. 버블정렬은 비교대상의 메모리 값이 정렬되어 있음에도 불구하고 비교연산을 하는 부분이 있는데 삽입정렬은 비교적 비교횟수를 줄이고 , 정렬된 값은 한번도 교환이 일어나지 않고 N-1의 비교만 일어난다.


e) 쉘 정렬 >
시간복잡도: O(N^1.25)

삽입정렬의 개념을 확대하여 일반화한 정렬방법이다. 알고리즘이 간단하여 간단히 구현할 수 있다. 수행능력도 삽입정렬보다 우수하다. 멀리있는 레코드들 끼리 비교 및 교환 될 수 있으므로, 어떤 데이터가 제 위치에서 멀리 떨어져 있다면 여러 번의 교환이 발생하는 버블정렬의 단점을 해결 할 수 있다.

f) 병합 정렬>
시간복잡도: O(NlogN)

작은 단위부터 정렬해서 정렬된 단위들을  계속 병합해가면서 정렬하는 방식이다. 알고리즘 중에 가장 간단하고 쉽게 떠올릴 수 있는 방법이다. 안정성이 있으며 상당히 좋은 성능을 나타낸다. 큰 결점은 데이터 크기만한 메모리가 더 필요하다는 것이다.

g) 버킷정렬>
버킷정렬은 정렬대상의 키들을 일정한 범위로 구분해 버킷(통)에 넣고 그 버킷을 각각 정렬하는 방법이다.

특징: 키가 어떤 범위내에서 키값이 확률적으로 균등하게 분포되어 있을 때 적용하면 효과가 좋다.
  실행시간: 버켓에 넣는 시간 O(n)+정렬시간

사용하기 좋은 예: "Person 객체를 담은 아주 큰 배열이 있다고 하자. 이 배열에 담긴 객체들을 나이순으로 정렬하라"
  여기서 두 힌트를 얻을 수 있다.
1. 큰 배열이므로 효율성이 중요하다.
2. 나이에 따라 정렬하는 것이므로, 그 값의 범위가 좁게 제한되어 있음을 이용할 수 있다.

정렬 알고리즘들을 살펴보면, 아마 버킷정렬 또는 기수 정렬이 가장 적합하리라는 것을 눈치 챌 수 있을 것이다. 버킷을 작게 만들 수 있고(각 버킷에 1년)O(n)으 실행시간을 달성할 수 있다. 그렇다면 값의 범위가 작을 때 사용하기 좋은 정렬?

공용체 union

 공용체
자료형 모음 하나에 대한, 각기 다른 해석이 가능한 자료형
융통성이 좋음, 즉 생각을 많이 해야함.

구조는 모든 멤버에 대해 서로 다른 메모리 위치를 할당 함.
union은 모든 메모에 대해 고통 메모리 위치 할당.

union union-name
{
datatype var1;
datatype var2;
- - - - - - - - - -
- - - - - - - - - -
datatype varN;
};

멤버 저근 객체 생성 구문
union union-name obj;

객체 생성 및 공영체 멤버 접근 예
vi objet_union_acess.c

#include<stdio.h>

union Employee
{
int Id;
char Name[25];
int Age;
long Salary;
};

void main()
{

union Employee E;

printf("\nEnter Employee Id : ");
scanf("%d",&E.Id);

printf("\nEnter Employee Name : ");
scanf("%s",&E.Name);

printf("\nEnter Employee Age : ");
scanf("%d",&E.Age);

printf("\nEnter Employee Salary : ");
scanf("%ld",&E.Salary);

printf("\n\nEmployee Id : %d",E.Id);
printf("\nEmployee Name : %s",E.Name);
printf("\nEmployee Age : %d",E.Age);
printf("\nEmployee Salary : %ld",E.Salary);


}

Output :

Enter Employee Id : 1
Enter Employee Name : Kumar
Enter Employee Age : 29
Enter Employee Salary : 45000

Employee Id : -20536
Employee Name : ?$?$  ?
Employee Age : -20536
Employee Salary : 45000

멤버 손상 값 확인.

변수 사용 예제.
vi variab_union.c
#include<stdio.h>

union Employee
{
int Id;
char Name[25];
int Age;
long Salary;
};

void main()
{

union Employee E;

printf("\nEnter Employee Id : ");
scanf("%d",&E.Id);
printf("Employee Id : %d",E.Id);

printf("\n\nEnter Employee Name : ");
scanf("%s",&E.Name);
printf("Employee Name : %s",E.Name);

printf("\n\nEnter Employee Age : ");
scanf("%d",&E.Age);
printf("Employee Age : %d",E.Age);

printf("\n\nEnter Employee Salary : ");
scanf("%ld",&E.Salary);
printf("Employee Salary : %ld",E.Salary);

}

Output :
Enter Employee Id : 1
Employee Id : 1

Enter Employee Name : Kumar
Employee Name : Kumar

Enter Employee Age : 29
Employee Age : 29

Enter Employee Salary : 45000
Employee Salary : 45000

각 멤버가 한 번에 사용되기 때문에 모든 멤버에 대한 내용이 출력된다.

공용체 크기 비교
vi union_cmp.c

#include<stdio.h>

struct Employee1
{
int Id;
char Name[25];
long Salary;
};

union Employee2
{
int Id;
char Name[25];
long Salary;
};

void main()
{

printf("\nSize of Employee1 is : %d",sizeof(Employee1));
printf("\nSize of Employee2 is : %d",sizeof(Employee2));

}

Output :

Size of Employee1 is : 31

비트필드 bit field

비트필드
1byte (8bit) 구주체
메모리 절략 주로 임베디드 사용. 스위치 ON OFF

struct struct-name
{
datatype var1 : size of bits;
datatype var2 : size of bits;
- - - - - - - - - -
- - - - - - - - - -
datatype varN : size of bits;
};

#include<stdio.h>

              struct info1
              {
                     int num;
              };

              struct info2
              {
                     int num : 1;
              };

              void main()
              {

                 struct info1 f1;
                 struct info2 f2;


                 printf("\n\n\tSize of info1 is : %d",sizeof(info1));
                 printf("\n\n\tSize of info2 is : %d",sizeof(info2));

              }

   Output :

              Size of info1 is : 2
              Size of info2 is : 1

구조체 VS 배열

구조체 : 동일하지 않은 자료형 모음
배열 : 동일한 자료형의 모음

struct userdata ---> record
{
 member1 ---> field
 member2
}

변수 일 때 접근
 변수.멤버이름

포인터 일 때 접근
*주소 -> 멤버이름

자기 참조 구조체
-링크드 리스트 자료구조(추가, 삭제, 검색)
 Node ->node -> node : 연결 리스트

typedef struct _A{
 char szName[16];
 char szPhone[16];
 struct _A *pNext;
}A;


calling convention in c 함수 호출 규약

함수 호출 규약

https://ko.wikipedia.org/wiki/X86_%ED%98%B8%EC%B6%9C_%EA%B7%9C%EC%95%BD

보안결합 buffer overflow

buffer overflow -> buffer overrun

buffer overrun 공격
SFP -> 스택 프레임 포인터
return -> 호출 반환 주소

참고: https://nautiluslee.blogspot.com/2018/12/blog-post_31.html

함수 포인터

1. 재귀 호출

A(){
A();
}
재귀호출 == 반복문 + Stack 
  caller == callee

A()함수 ()호츨자의 피연산자 A는 함수 이름이다. 함수 이름은 메모리 주소이다. 함수 이름의 주소 체계는 프로시저 형식의 주소가 부여된다.

동일한 함수가 동일한 이름의 함수를 호출 하면은 스텍 크기가 증가한다. 

스텍또한 자료 구조이므로, 그 구조에 따른 형틀을 가지고 있으며, 그 용어를 stack frame라 한다. 

stack frame은 논리 구조의 자료 구조이다. 
스택의 논리 구조를 구현 할 필요는 없다. 누군가 이미 그 구조를 만들어 놓아기 때문이다. 
스택 프레임 자료에다가 반복문을 추가해 사용하게 된다면, 그게 바로 재귀 호출이 된다. 

스택 자료 구조의 특징 
스택이 증가하면 메모리 주소는 감소한다. 
순간 메모리 사용량 증가. 
연산량이 많아 느림 
파일시스템(폴더)나 트리구 형태의 자료에서 사용된다

재귀함수 분석 
디버그 모드 컴파일 
브레이크 포인트 설정
한줄단위 추적 ---> 메모리 맵에 흐름 확인

STDOUT 값 전달.

function factorial {
    (( $1 )) &&
    echo $(( $1 * $( factorial $(( $1 - 1 )) ) )) ||
    echo 1
}
factorial 5

function factorial {
    (( $1 )) || return 1
    factorial $(( $1 - 1 ))
    return $(( $1 * $? ))
}

factorial 5
echo $?

vi test.sh
#!/bin/bash
factorial()
{
    if [[ $1 -le 1 ]]
    then
        echo 1
    else
        last=$(factorial $[$1-1])
        echo $(($1 * last))
    fi
}
factorial 5

cp(recursive)은 디렉토리의 내용을 복사하고, 하위 디렉토리가 있는 경우(재귀 적으로)복사한다.

2. 함수 포인터 
callback 함수 사용.

함수의 이름은 곳 주소이다.

케릭터 포인터를 인수로 받아 int 형으로 반환하는 함수 포인터
int testfun(char*); 
int *(pTest(char*); // 캐릭터 포인터를 인수 값으로 받는다.

pTest = testfun();

동작구조 
sort 정렬
텍스트로된 파일의 행단위 정렬을 할때 사용하는 명령어이다. 
복잡한 워드문서등의 편집이 아닌 간단한 텍스트문서를 대상으로 정렬 작업을 할때 주로 사용되는 명령어이다.
이 명령어는 주로 특정 DB나 프로그램, 또는 쉘프로그램등의 입력값으로 사용되는 데이터를 직접 정렬하려고 할때 사용된다.

sort [-옵션] [-o 저장될 파일명] 정렬할 파일명 [병합할 파일명]

기본 정렬 : 맨 앞 글자 알파벳 오름 차순 정렬
ls -al | sort

-r 옵션
-r은 내림차순 정렬이다.
ls -al | sort -r

-k숫자 옵션
-k는 줄의 맨 앞 문자가 아닌 공백을 기준으로 n번째 문자를 기준으로 정렬하는 것이다.
ls -al | sort -k9

-g 옵션
-g은 알파벳 순이 아닌 숫자 크기 순으로 정렬하는 것이다. -k와 결합하여 적용해서 크기순으로 정렬
ls -al | sort -k5 -g

-u 옵션
비교하는 값이 동일할 경우 제거하는 옵션
ls -al | sort -k5 -g -u

크기 역순으로 정렬하기
이제 위에서 다룬 모든 옵션을 사용하여 크기 역순으로 중복을 제거하면서 파일을 정렬
ls -al | sort -k5 -g -u -r

Sort는 명령어 결과 혹은 문서 내용을 정렬
cat data.txt
5
3
2
7

sort data.txt
2
3
5
7

cat data2.txt
a 4 
c 5
f 1
z 2

두번 째 열 기준 정렬
sort + 1 data2.txt

f 1
z 2
a 4
c 5

sort/uniq 를 같이 사용해 정렬한 후 충복된 내용의 행이 연속적으로 있으면 하나만 나기고 삭제. 

wget 하위 디렉토리 다운로드

wget 파일 다운로드

하위 디렉토리 다운로드
wget -m -p -E -k -K -np {URL Address}

하위 디렉토리
wget -r

링크 파일
wget -r -l 1
html에 링크된 파일들을 가져온다.
-r 옵션은 --recursive 이고 -l  은 반복할 레벨을 뜻한다. (즉 링크를 추적할수 있는 방법론 1으므로 한번 링크 추적)

다른 이름 저장
wget -O 새로운이름 http://l-ht.com


-np: 링크된 파일 중 상위 디렉토리는 제외 (no-parent)
-A html.htm : html.htm 형식의 파일만
-L : 상대주소를 이용한 링크
-q : 메세지 출력 금지
-nv: 메세지 요약 출력

-nd : no directoris, 로컬에 다운받을때 디렉토리를 생성하지 않으며 모든 파일을 같은 디렉토리 넣는다.

-t 1: retries, 링크된 주소로 서버를 찾기 못할때 재 전송 할 횟수를 지정한다.

-H : 다른 호스트의 재귀적 탐색을 원할 경우 span-host를 의미한다.

index.html 만 가지고 오기
wget -r -l 0 -L -np -A index.html -nv URL

wget -A mpg,mpeg,avi,asf -r -H -l 2 -nd -t 1 http://usrl.com

ftp로그인 다운로드 방법
wget -f ftp://아이디:votmdnjem@아이피주소및 파일 위치

wget을 이용한 사이트 응답시간 체크
다음과 같은 2가지 사항에 대해서 체크한다면, 웹서비스에 대한 기본적인 품질 체크 가능.

    페이지 응답체크
    페이지 응답시간

Submit Process
여기에 덧붙여서 Submit Process까지 체크한다면, 더 나은 품질 모니터링 환경을 만들 수 있다.

어떤 웹서비스가 제대로 작동하는지 확인하고 싶을 경우, POST(:12) 혹은 GET(:12)으로 연결된 몇개의 페이지를 연결해서 검사해야할 필요가 있다. 예를 들어서 로그인을 위해서 OpenID(:12)를 사용한다고 가정해보자.

기존의 로그인 방식이라면, 로그인관련 데이터가 로컬에 있으니, 로그인데이터를 관리하는 DB시스템이 제대로 살아있는지만 확인할 수 있으면 된다. 그러나 OpenID와 같은 경우에는 로컬 DB를 이용하는게 아닌, 로그인 서비스를 이용하는 방식이기 때문에 실제 Submit을 해서 다음 페이지로 넘어가는지를 확인해 주어야 한다.

Submit 프로세스를 체크하기 위해서는 HTTP(:12)와 POST(:12), GET(:12)을 이용한 데이터 전달방식 그리고 cookie(:12)에 대해서 알고 있어야 할것이다. 여기에서는 그냥 wget(1)을 이용해서 간단하게 처리하는 방법에 대해서 알아본다.

# wget --load-cookies=cookies.txt --save-cookies=cookies.txt \
--post-data 'uname=myid&pass=mypass&op=login' \
'http://www.domain.com/auth.php'  -O /dev/null

아주 간단하다. --post-data 옵션을 이용하면, 해당 페이지에 POST 데이터를 넘길 수 있다. POST 데이터를 받은 웹서버는 인증과정을 거친 후, 그 결과를 Cookie로 클라이언트에 전달하고, 이후의 인증 세션유지는 cookie 값의 교환으로 이루어지게 된다. --save-cookies 옵션을 이용하면, 서버로 부터 넘어온 cookie 값을 파일에 저장할 수가 있다. 이제 --load-cookies 옵션을 이용해서 해당 웹페이지를 호출할 때, 쿠키도 같이 보내면 된다.

위의 명령을 쉘스크립트(:12) 형태로 만들어서 주기적으로 실행하고, 그 결과를 분석하는 걸로, 간단하게 Submit Process에 대한 체크를 할 수 있다. C(:12) 언어가 마음에 든다면, fork(:12) & exec(:12)를 이용한 실행코드를 만들어 낼 수도 있을 것이다. 위의 경우는 요청한 페이지정보를 /dev/null 로 보내고 있는데, 로그인 결과까지를 확인하고 싶다면, 입력받은 페이지를 스트링매칭 시키는 방법으로 분석해야 할 것이다.

응답시간
응답시간 역시 wget을 이용해서 간단하게 해결할 수 있다. 더불어 -p옵션을 사용한다면, 해당 페이지에 링크되어 있는 이미지, 사운드, CSS(:12) 데이터들의 로딩시간까지 함께 체크할 수 있다.



# wget -p http://www.domain.com/index.php > /dev/null

재귀함수 두 숫자 gcd

#include <stdio.h>
int hcf(int n1, int n2);

int main(void){
int n1, n2;
printf("Enter two positive integers: ");
scanf("%d %d", &n1, &n2);

printf("G.C.D of %d and %d is %d.", n1, n2, hcf(n1,n2));
return 0;
}

int hcf(int n1, int n2){
if (n2 != 0)
return hcf(n2, n1%n2);
else
return n1;
}

/*
Enter two positive integers: 365
60
G.C.D of 365 and 60 is 5. */

재귀함수 자연수 합

#include <stdio.h>
int sum(int n);

int main(void){
int number, result;

printf("Enter a positive interget: ");
scanf("%d", &number);

result = sum(number);

printf("sum = %d", result);
return 0;
}

int sum(int num){
if (num != 0 )
return num + sum(num-1); // sum() 자기 자신 호출
else
return num;
}

/*
Enter a positive integer:3
sum = 6
*/

재귀 호출

재귀 호출

A(){
A();
}
재귀호출 == 반복문 + Stack
  caller == callee

A()함수 ()호츨자의 피연산자 A는 함수 이름이다. 함수 이름은 메모리 주소이다. 함수 이름의 주소 체계는 프로시저 형식의 주소가 부여된다.

동일한 함수가 동일한 이름의 함수를 호출 하면은 스텍 크기가 증가한다.

스텍또한 자료 구조이므로, 그 구조에 따른 형틀을 가지고 있으며, 그 용어를 stack frame라 한다.

stack frame은 논리 구조의 자료 구조이다.
스택의 논리 구조를 구현 할 필요는 없다. 누군가 이미 그 구조를 만들어 놓아기 때문이다.
스택 프레임 자료에다가 반복문을 추가해 사용하게 된다면, 그게 바로 재귀 호출이 된다.

스택 자료 구조의 특징
스택이 증가하면 메모리 주소는 감소한다.
순간 메모리 사용량 증가.
연산량이 많아 느림
파일시스템(폴더)나 트리구 형태의 자료에서 사용된다

재귀함수 분석
디버그 모드 컴파일
브레이크 포인트 설정
한줄단위 추적 ---> 메모리 맵에 흐름 확인

STDOUT 값 전달.

function factorial {
    (( $1 )) &&
    echo $(( $1 * $( factorial $(( $1 - 1 )) ) )) ||
    echo 1
}
factorial 5

function factorial {
    (( $1 )) || return 1
    factorial $(( $1 - 1 ))
    return $(( $1 * $? ))
}

factorial 5
echo $?

vi test.sh
#!/bin/bash
factorial()
{
    if [[ $1 -le 1 ]]
    then
        echo 1
    else
        last=$(factorial $[$1-1])
        echo $(($1 * last))
    fi
}
factorial 5

cp(recursive)은 디렉토리의 내용을 복사하고, 하위 디렉토리가 있는 경우(재귀 적으로)복사한다.