[태그:] 임베디드 리눅스

  • 4장 process 로그 확인

    책 “디버깅을 통해.. 리눅스 커널” 148 페이지 예제를 실행했다. 잘 따라 해야 한다. trace 를 죽이고 살리는 과정에 오타로 살짝 헷갈렸다. 책은 /sys/kernel/debug/tracing/trace를 복사하는 script를 만들었다. 디버그 메세지를 보려면 이벤트 발생 후 바로 복사해야지, 타이핑한다고 늦게 하면 이전 기록을 시스템이 지워버린다. trace 파일을 지울 수 없다. 초기화 하려면 tracing_on에 0을 다시 써줘야 한다. 아래와 같은 기록을 뽑아 냈다. 다 적을 수 없어, 중요한 부분만 추출했다. 생각이 맞는지 모르겠다.

    5825  => sys_clone+0x18/0x3c
    5826  => ret_fast_syscall+0x0/0x28
    5827  => 0xbed826b0
    5828             bash-1921  [002] .... 32848.024289: _do_fork+0x14/0x41c <-sys_clone+0x34/0x3c
    5829             bash-1921  [002] .... 32848.024299: <stack trace>
    5830  => _do_fork+0x18/0x41c
    5831  => sys_clone+0x34/0x3c
    5832  => ret_fast_syscall+0x0/0x28
    5833  => 0xbed826b0
    5834           <idle>-0     [000] dns. 32848.024300: sched_wakeup: comm=kworker/u8:3 pid=2958 prio=120 target_cpu=000
    5835             bash-1921  [002] .... 32848.024301: copy_process.part.0+0x14/0x1ac4 <-_do_fork+0xc4/0x41c
    5836           <idle>-0     [000] d... 32848.024307: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=kworker/u8:3 next_pid=2958 next_prio=120
    5837             bash-1921  [002] .... 32848.024310: <stack trace>
    5838  => copy_process.part.0+0x18/0x1ac4
    5839  => _do_fork+0xc4/0x41c
    5840  => sys_clone+0x34/0x3c
    5841  => ret_fast_syscall+0x0/0x28
    5842  => 0xbed826b0
    5843     kworker/u8:3-2958  [000] d... 32848.024324: sched_switch: prev_comm=kworker/u8:3 prev_pid=2958 prev_prio=120 prev_state=I ==> next_comm=swapper/0 next_pid=0 next_prio=120
    5844             bash-1921  [002] .... 32848.024940: sched_process_fork: comm=bash pid=1921 child_comm=bash child_pid=3043
    5845           <idle>-0     [003] d... 32848.024981: sched_switch: prev_comm=swapper/3 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=bash next_pid=3043 next_prio=120
    5846    raspbian_proc-3043  [003] d... 32848.025568: sched_switch: prev_comm=bash prev_pid=3043 prev_prio=120 prev_state=S ==> next_comm=swapper/3 next_pid=0 next_prio=120
    5847           <idle>-0     [003] dnh. 32848.025595: sched_wakeup: comm=bash pid=3043 prio=120 target_cpu=003
    5848           <idle>-0     [003] d... 32848.025608: sched_switch: prev_comm=swapper/3 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=bash next_pid=3043 next_prio=120
    5849             bash-1921  [002] d... 32848.025727: sched_switch: prev_comm=bash prev_pid=1921 prev_prio=120 prev_state=S ==> next_comm=swapper/2 next_pid=0 next_prio=120
    5850           <idle>-0     [000] dnh. 32848.026664: sched_wakeup: comm=irq/36-mmc1 pid=82 prio=49 target_cpu=000
    5851           <idle>-0     [000] d... 32848.026684: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=irq/36-mmc1 next_pid=82 next_prio=49
    5852      irq/36-mmc1-82    [000] d.s. 32848.026720: sched_wakeup: comm=irq/36-mmc1 pid=82 prio=49 target_cpu=000
    5853      irq/36-mmc1-82    [000] d.s. 32848.026763: sched_wakeup: comm=irq/36-mmc1 pid=82 prio=49 target_cpu=000
    5854      irq/36-mmc1-82    [000] d.s. 32848.026806: sched_wakeup: comm=irq/36-mmc1 pid=82 prio=49 target_cpu=000
    5855      irq/36-mmc1-82    [000] d... 32848.026823: sched_wakeup: comm=kworker/u8:3 pid=2958 prio=120 target_cpu=000
    5856      irq/36-mmc1-82    [000] d... 32848.026840: sched_switch: prev_comm=irq/36-mmc1 prev_pid=82 prev_prio=49 prev_state=S ==> next_comm=kworker/u8:3 next_pid=2958 next_prio=120
    5857     kworker/u8:3-2958  [000] d.s. 32848.026900: sched_wakeup: comm=kworker/u8:3 pid=2958 prio=120 target_cpu=000
    5858     kworker/u8:3-2958  [000] d.s. 32848.026946: sched_wakeup: comm=kworker/u8:3 pid=2958 prio=120 target_cpu=000
    ...
    8445     kworker/u8:0-2918  [001] d... 32866.110752: sched_switch: prev_comm=kworker/u8:0 prev_pid=2918 prev_prio=120 prev_state=I ==> next_comm=bash next_pid=3013 next_prio=120
    8446             bash-3013  [001] d... 32866.110848: signal_generate: sig=9 errno=0 code=0 comm=raspbian_proc pid=3043 grp=1 res=0
    8447           <idle>-0     [003] dnh. 32866.110856: sched_wakeup: comm=raspbian_proc pid=3043 prio=120 target_cpu=003
    8448           <idle>-0     [003] d... 32866.110870: sched_switch: prev_comm=swapper/3 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=raspbian_proc next_pid=3043 next_prio=120
    8449    raspbian_proc-3043  [003] d... 32866.110880: signal_deliver: sig=9 errno=0 code=0 sa_handler=0 sa_flags=0
    8450    raspbian_proc-3043  [003] .... 32866.110883: do_exit+0x14/0xbd4 <-do_group_exit+0x50/0xe8
    8451    raspbian_proc-3043  [003] .... 32866.110909: <stack trace>
    8452  => do_exit+0x18/0xbd4
    8453  => do_group_exit+0x50/0xe8
    8454  => get_signal+0x160/0x85c
    8455  => do_signal+0x360/0x4a4
    8456  => do_work_pending+0xd4/0xec
    8457  => slow_work_pending+0xc/0x20
    8458  => 0xb6e1969c
    8459    raspbian_proc-3043  [003] .... 32866.111230: sched_process_exit: comm=raspbian_proc pid=3043 prio=120
    8460    raspbian_proc-3043  [003] d... 32866.111296: signal_generate: sig=17 errno=0 code=2 comm=bash pid=1921 grp=1 res=0
    8461           <idle>-0     [002] dnh. 32866.111311: sched_wakeup: comm=bash pid=1921 prio=120 target_cpu=002
    8462             bash-3013  [001] dn.. 32866.111313: sched_wakeup: comm=kworker/u8:0 pid=2918 prio=120 target_cpu=001
    8463           <idle>-0     [002] d... 32866.111327: sched_switch: prev_comm=swapper/2 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=bash next_pid=1921 next_prio=120
    8464    raspbian_proc-3043  [003] d... 32866.111330: sched_switch: prev_comm=raspbian_proc prev_pid=3043 prev_prio=120 prev_state=Z ==> next_comm=kworker/u8:0 next_pid=2918 next_prio=120
    8465           <idle>-0     [000] dnh. 32866.111359: sched_wakeup: comm=sshd pid=3010 prio=120 target_cpu=000
    8466             bash-3013  [001] d... 32866.111362: sched_switch: prev_comm=bash prev_pid=3013 prev_prio=120 prev_state=S ==> next_comm=swapper/1 next_pid=0 next_prio=120
    8467     kworker/u8:0-2918  [003] d... 32866.111364: sched_switch: prev_comm=kworker/u8:0 prev_pid=2918 prev_prio=120 prev_state=I ==> next_comm=swapper/3 next_pid=0 next_prio=120
    8468           <idle>-0     [000] d... 32866.111374: sched_switch: prev_comm=swapper/0 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=sshd next_pid=3010 next_prio=120
    8469           <idle>-0     [003] dnh. 32866.111531: sched_wakeup: comm=kworker/u8:0 pid=2918 prio=120 target_cpu=003
    8470           <idle>-0     [003] d... 32866.111539: sched_switch: prev_comm=swapper/3 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=kworker/u8:0 next_pid=2918 next_prio=120
    8471             sshd-3010  [000] d... 32866.111572: sched_switch: prev_comm=sshd prev_pid=3010 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120
    
    • bash pid는 1921이다.
    • 5844행에서 child_pid 3043으로 자식 프로세스를 만들었다.
    • 5846행에서 raspbian_proce를 볼 수 있다.
    • 이 전에 5836행에서 다음 프로세스 id 2958을 가지고 거꾸로 sys_clone -> _do-fork -> copy_process를 실행했다.
    • 5836 행에서 next pid 2958(5857행)로 넘어가야 하는데 fork 하느라 다음 행을 실행했다.

    Linux process states

    As in every Unix flavour, in Linux a process can be in a number of states. It’s easiest to observe it in tools like ps or top: it’s usually in the column named S. The documentation of ps describes the possible values:

    PROCESS STATE CODES
       R  running or runnable (on run queue)
       D  uninterruptible sleep (usually IO)
       S  interruptible sleep (waiting for an event to complete)
       Z  defunct/zombie, terminated but not reaped by its parent
       T  stopped, either by a job control signal or because
          it is being traced
       [...]
    

    A process starts its life in an R “running” state and finishes after its parent reaps it from the Z “zombie” state.

    • 8449행에서 signo 9번을 받았다.
    • 시그널 9번을 받아 시그널 17 발생 시켰다.
    • slow_work_pending -> do_work_pending -> do_signal -> get_signal -> do_group_exit -> do_exit 순으로 실행한다.
  • raspberry pi4 커널 컴파일

    삼국지도 다 끝났고, 남는 시간에 리눅스 커널을 배워 보기로 했다. 시간 남을 땐 이게 효과가 확실하지. 전에 샀던 “디버깅을 통해 배우는 리눅스 커널의 구조와 원리”를 따라 해보기로 했다. 커널이 리눅스 심장과 같아 꼭 배울 필요는 없지만, 알면 편하게 살 수 있다. 리눅스 역시 과거 서버를 벗어나 arm에 로딩되어 여러 임베디드 리눅스로 사용되고 있다. 라즈베리 파이 역시 미친 가격으로 집에서 누구나 쉽게 구할 수 있다. 지금 IoT가 뜨고 있는데 안 배울 이유가 없다.

    책에 나온 커널이 버전 4.19다. 2021. 5월 업데이트를 하면 커널 5.10을 사용한다. 일단 커널을 4.19 버전으로 강제로 맞춰야 한다.

    pi@raspberrypi:~ $ uname -a
    Linux raspberrypi 5.10.17-v7l+ #1414 SMP Fri Apr 30 13:20:47 BST 2021 armv7l GNU/Linux

    책 53 페이지에 나온대로 따라했다. 15년전에 비하면 정말 편해졌다. 그 때 컴파일 옵션이 너무 많아 하드웨어 지식이 없어 무엇을 선택할 지 몰랐다.

    #https://www.raspberrypi.org/documentation/linux/kernel/building.md
    
    #필요 모듈 설치.
    sudo apt install git bc bison flex libssl-dev make
    
    git clone --depth=1 --branch rpi-4.19.y https://github.com/raspberrypi/linux
    
    cd linux
    #KERNEL=kernel7
    KERNEL=kernel7l
    #make bcm2709_defconfig
    make bcm2711_defconfig

    책은 make bcm2709_defconfig로 컴파일 옵션을 설정했다. 아무 생각없이 따라하다 보면 usb를 하나도 인식하지 못하는 현상을 겪는다.

    pi@raspberrypi:~ $ lsusb
    pi@raspberrypi:~ $

    이거 때문에 한동안 고민했다. make menu로 usb를 설정하는 옵션을 찾아 켜주면 될 듯 한데, 내가 많이 몰라 다른 옵션을 어떻게 설정할지 판단 못하겠다. 옵션 하나 켜겠다고 그 짓을 해야되나… usb가 막혀 키보드도 연결되지 않고, usb 메모리, 카메라 등 아무것도 연결되지 않았다. usb 4포트가 모두 불량인 줄 알고 환불할 뻔 했다.

    pi@raspberrypi:~ $ cat /proc/cpuinfo
    processor	: 0
    model name	: ARMv7 Processor rev 3 (v7l)
    BogoMIPS	: 270.00
    Features	: half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm crc32 
    CPU implementer	: 0x41
    CPU architecture: 7
    CPU variant	: 0x0
    CPU part	: 0xd08
    CPU revision	: 3
    
    processor	: 1
    model name	: ARMv7 Processor rev 3 (v7l)
    BogoMIPS	: 270.00
    Features	: half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm crc32 
    CPU implementer	: 0x41
    CPU architecture: 7
    CPU variant	: 0x0
    CPU part	: 0xd08
    CPU revision	: 3
    
    processor	: 2
    model name	: ARMv7 Processor rev 3 (v7l)
    BogoMIPS	: 270.00
    Features	: half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm crc32 
    CPU implementer	: 0x41
    CPU architecture: 7
    CPU variant	: 0x0
    CPU part	: 0xd08
    CPU revision	: 3
    
    processor	: 3
    model name	: ARMv7 Processor rev 3 (v7l)
    BogoMIPS	: 270.00
    Features	: half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm crc32 
    CPU implementer	: 0x41
    CPU architecture: 7
    CPU variant	: 0x0
    CPU part	: 0xd08
    CPU revision	: 3
    
    Hardware	: BCM2711
    Revision	: b03114
    Serial		: 100000003d82cd51
    Model		: Raspberry Pi 4 Model B Rev 1.4
    

    책에 없지만, 웹 사이트와 여기 보드 정보를 보면 bcm2711을 사용했다. 이 옵션이 맞다. 이게 customized 제품과 대량 생산품 차이다. 이 옵션을 개인이 일일히 다 넣어주려면 힘들겠다. 표준화된 하드웨어를 사용함이 훨씬 낫다. 아무리 많이 판대도 raspberry pi 만큼 팔릴 수 있을 지 모르겠다. 단가에서 경쟁하기 어렵다고 본다.

    make -j4 zImage modules dtbs
    sudo make modules_install
    sudo cp arch/arm/boot/dts/*.dtb /boot/
    sudo cp arch/arm/boot/dts/overlays/*.dtb* /boot/overlays/
    sudo cp arch/arm/boot/dts/overlays/README /boot/overlays/
    sudo cp arch/arm/boot/zImage /boot/$KERNEL.img

    나머지를 실행한다. boot 디렉토리 파일을 덮어쓰기 전에 기존 파일을 꼭 백업해야 한다. 그냥 날려 버리면 나처럼 다시 이미지를 구워야 한다.

    pi@raspberrypi:~ $ lsusb
    Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
    Bus 001 Device 002: ID 2109:3431 VIA Labs, Inc. Hub
    Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
    pi@raspberrypi:~ $ uname -a
    Linux raspberrypi 4.19.127-v7l+ #2 SMP Thu May 13 15:17:29 BST 2021 armv7l GNU/Linux

    1.5시간 컴파일 후 정상적으로 부팅했음을 확인했다.

    cross compile을 하기로 했다. 1.5 시간이 10분으로 줄어드는 마법을 보았다. https://www.raspberrypi.org/documentation/linux/kernel/building.md 사이트에 가면 cross compile 하는 방법이 나와 있다. 그대로 따라하면 된다.

    /boot 디렉토리 내용을 통째로 날렸는데, 그러면 안된다. start.elf 파일이 없다고 부팅되지 않는다.

    pi@raspberrypi:/boot $ ls -l
    total 27721
    -rwxr-xr-x 1 root root   24270 May 15  2021 bcm2708-rpi-b-plus.dtb
    -rwxr-xr-x 1 root root   24007 May 15  2021 bcm2708-rpi-b.dtb
    -rwxr-xr-x 1 root root   23788 May 15  2021 bcm2708-rpi-cm.dtb
    -rwxr-xr-x 1 root root   24448 May 15  2021 bcm2708-rpi-zero-w.dtb
    -rwxr-xr-x 1 root root   23712 May 15  2021 bcm2708-rpi-zero.dtb
    -rwxr-xr-x 1 root root   25334 May 15  2021 bcm2709-rpi-2-b.dtb
    -rwxr-xr-x 1 root root   25483 May 15  2021 bcm2710-rpi-2-b.dtb
    -rwxr-xr-x 1 root root   27143 May 15  2021 bcm2710-rpi-3-b-plus.dtb
    -rwxr-xr-x 1 root root   26524 May 15  2021 bcm2710-rpi-3-b.dtb
    -rwxr-xr-x 1 root root   25338 May 15  2021 bcm2710-rpi-cm3.dtb
    -rwxr-xr-x 1 root root   41185 May 15  2021 bcm2711-rpi-4-b.dtb
    -rwxr-xr-x 1 root root   18695 May 15  2021 bcm2835-rpi-a-plus.dtb
    -rwxr-xr-x 1 root root   18579 May 15  2021 bcm2835-rpi-a.dtb
    -rwxr-xr-x 1 root root   18982 May 15  2021 bcm2835-rpi-b-plus.dtb
    -rwxr-xr-x 1 root root   18858 May 15  2021 bcm2835-rpi-b-rev2.dtb
    -rwxr-xr-x 1 root root   18725 May 15  2021 bcm2835-rpi-b.dtb
    -rwxr-xr-x 1 root root   18690 May 15  2021 bcm2835-rpi-cm1-io1.dtb
    -rwxr-xr-x 1 root root   19173 May 15  2021 bcm2835-rpi-zero-w.dtb
    -rwxr-xr-x 1 root root   18647 May 15  2021 bcm2835-rpi-zero.dtb
    -rwxr-xr-x 1 root root   19558 May 15  2021 bcm2836-rpi-2-b.dtb
    -rwxr-xr-x 1 root root   21027 May 15  2021 bcm2837-rpi-3-b-plus.dtb
    -rwxr-xr-x 1 root root   20238 May 15  2021 bcm2837-rpi-3-b.dtb
    -rwxr-xr-x 1 root root   52456 May 15  2021 bootcode.bin
    -rwxr-xr-x 1 root root     121 May 15  2021 cmdline.txt
    -rwxr-xr-x 1 root root    1809 May 15  2021 config.txt
    -rwxr-xr-x 1 root root    7314 May 15  2021 fixup.dat
    -rwxr-xr-x 1 root root    5446 May 15  2021 fixup4.dat
    -rwxr-xr-x 1 root root    3191 May 15  2021 fixup4cd.dat
    -rwxr-xr-x 1 root root    8454 May 15  2021 fixup4db.dat
    -rwxr-xr-x 1 root root    8452 May 15  2021 fixup4x.dat
    -rwxr-xr-x 1 root root    3191 May 15  2021 fixup_cd.dat
    -rwxr-xr-x 1 root root   10298 May 15  2021 fixup_db.dat
    -rwxr-xr-x 1 root root   10298 May 15  2021 fixup_x.dat
    -rwxr-xr-x 1 root root     145 May 15  2021 issue.txt
    -rwxr-xr-x 1 root root 5773448 May 15  2021 kernel7l.img
    drwxr-xr-x 2 root root   16384 May 15  2021 overlays
    -rwxr-xr-x 1 root root 2952928 May 15  2021 start.elf
    -rwxr-xr-x 1 root root 2228768 May 15  2021 start4.elf
    -rwxr-xr-x 1 root root  793084 May 15  2021 start4cd.elf
    -rwxr-xr-x 1 root root 3722504 May 15  2021 start4db.elf
    -rwxr-xr-x 1 root root 2981160 May 15  2021 start4x.elf
    -rwxr-xr-x 1 root root  793084 May 15  2021 start_cd.elf
    -rwxr-xr-x 1 root root 4794472 May 15  2021 start_db.elf
    -rwxr-xr-x 1 root root 3704712 May 15  2021 start_x.elf
    

    overlays 내용을 날리고, 새로 컴파일 버전으로 설치했고, start.elf, *.dat, bootcode.bin, *.txt를 전에 받았던 백업에서 복사했다. 다행히 잘 된다. 두 번은 하지만, 세 번은 못 하겠다. 책이 왜 스크립트를 설명했는지 이해된다.