임베디드 국비교육에서 배웠던 내용 복습

경력이 쌓이고 복습을 반복할 때마다, 이전에 배운 내용이 좀 더 잘 이해가 되고, 왜 이 내용을 설명했는지 알 수가 있다.

여러모로 느낀 바가 많은 시간.

 

아래는 복습하면서 재정리한 내용과 참조한 링크

 * 디바이스 드라이버는 이해하기 좋게 잘 연결되어 있지 않은 것으로 보인다. (내용을 짜집기 하기만 한듯?)추가적으로 책을 구매해 공부할 것.

 

1. 컴퓨터 아키텍처

 - 폰노이만 아키텍처 : 명령어와 데이터를 위한 메모리 인터페이스가 하나인 구조

    명령어 메모리(rom)와 데이터가 저장된 메모리(ram)에 접근하는 명령어, 데이터 버스를 공유한다

    (즉 명령어 버스와 데이터 버스를 공용으로 사용한다)

 - 하버드 아키텍처 : 명령어와 데이터를 위한 메모리 인터페이스가 분리되어 있는 구조

    (폰노이만 구조와 달리 명령어/데이터 버스가 각각 존재하여 병목현상이 없음)

 

 

2. 컴파일 과정

 - 전처리과정(pre-processing) : 헤더(h) + 소스코드(c, cpp등)  -> 전처리된 소스코드(i)

   : 주석제거, 헤더내용 합치기, 매크로 치환 등

 - 컴파일과정(compile) : 전처리된 소스코드(i) -> 어셈블리 파일(s)

   : 문법 검사 및 메모리 섹션 설정(bss, data, text등)

 - 어셈블리(assembly) : 어셈블리 파일(s) -> 목적파일(o)

   : 어셈블리어를 기계어로 변환

 - 링킹(linking) : 목적파일(o) + 다른 목적파일or라이브러리(a, so) -> 실행파일

   : 프로그램을 만들기 위해 다른 목적파일이나 라이브러리를 링크하는 과정. 동적 라이브러리(so)는 일부 정보만 반영되고 프로그램 실행시 로더에 의해 메모리에 적재(실행)된다.

   : 필요에 따라 startup code file을 같이 컴파일 한다

* 프로그램 실행시 로더(loader)에 의해 바이너리가 메모리에 적재된다.

* 로케이트(locate) : 메모리에서 실행가능하도록 코드와 데이터를 배치하여 최종 바이너리 이미지를 생성하는 도구. 대부분 링커에 포함되어 있음

* Linker script 파일 :  코드와 데이터의 메모리 배치(섹션 배치)를 정의한 파일

* 참조

 - https://bradbury.tistory.com/226

 - https://rateye.tistory.com/704

 - https://eunjinii.tistory.com/20

 

 

3. object 파일

 - 컴파일러나 어셈블러에 의해 만들어진 바이너리 format의 파일

 - 명령어와 자료구조 정보로 구성되어 있다

 - 목적파일의 자료구조

   1) Header :  Section에 대해 설명하는 내용이 존재

   2) Section : Text section, Data section, BSS section

   3) Symbol Table : 변수와 함수의 이름과 위치정보가 존재

 - 목적파일의 format : ELF(Extended Linker Format), COFF(Common Object File Format)

 

 

4. elf 파일과 dwarf

 - elf(Executable Linkable Format)

    : 실행 파일, 목적 파일, 공유 라이브러리 그리고 코어 덤프를 위한 표준 파일 형식. 목적 파일을 임의의 길이를 갖는 섹션들의 리스트로만 생각하며, 언제나 새로운 섹션의 추가가 가능하다

 - dwarf(Debugging With Attributed Record Formats)

    : elf의 디버깅을 위해 만들어진 디버깅 양식. elf에서 dwarf die(debugging information entries)가 디버그 섹션(.debug)을 생성한다

 * 참조

 - https://ko.wikipedia.org/wiki/ELF_%ED%8C%8C%EC%9D%BC_%ED%98%95%EC%8B%9D

 - https://ko.wikipedia.org/wiki/DWARF

 

 

5. rom에 탑재가능한 이미지(ROM able image, binary image)

 - 링커에 의해 생성된 이미지파일에서 header, section 정보, 디버깅 정보를 제거한 이미지

 - 타겟 CPU에서 HW적으로 실행가능한 기계코드(기계어)만 가지고 있다

 - ELF이미지는 실행코드 이외의 다른 정보를 가지고 있기에 ROM에 탑재되어 구동될 수 없다.

 

 

6. 인터프리터와 스크립트, 컴파일러 구분

 - 컴파일러 : 소스코드 모두를 모아 실행 가능한 바이너리로 만듬. 이후 한번에 실행

 - 인터프리터 : 소스코드를 인터프리터 해석기를 통해 한줄씩 실행

 * 참조

 - https://losskatsu.github.io/os-kernel/compiler-interpreter/#%EB%A6%AC%EB%88%85%EC%8A%A4-%EC%BB%B4%ED%8C%8C%EC%9D%BC%EB%9F%AC-vs-%EC%9D%B8%ED%84%B0%ED%94%84%EB%A6%AC%ED%84%B0-%EC%B0%A8%EC%9D%B4

 - https://velog.io/@jkijki12/%EC%BB%B4%ED%8C%8C%EC%9D%BC-%EC%9D%B8%ED%84%B0%ED%94%84%EB%A6%AC%ED%84%B0-%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8

 

 

7. 이미지 다운로드

 - 방식

  1) ROM(혹은 Flash)에 탑재 : ROM writer사용, JTAG 인터페이스의 Dongle 사용

  2) DRAM에 탑채

     : Target 보드에 모니터 프로그램 혹은 부트로더를 탑재하고 시리얼, 이더넷, usb등으로 다운로드

     : JTAG 인터페이스의 Dongle 사용

     : 전용 ICE 사용

  3) 전용 ICE를 사용하여 디버깅 정보와 함께 탑재하여 실행

 

 

8. ICE(In-Circuit Emulator)

 - 호스트의 디버거와 함께 타겟 시스템의 레지스터와 메모리의 내용을 디버깅하기 위해 사용하는 장비

 - 호스트에 연결되는 인터페이스 : parallel, ethernet, usb등

 - 디버거에 연결되는 인터페이스 : JTAG, BDM ㄷ,ㅇ

 - 사용 ICE 장비 종류 : Multi ICE, RealView ICE, Trace32, VBOX, VBOX-Pro, OpenICE, JEENI, MAGIC

 * 참조 : https://en.wikipedia.org/wiki/In-circuit_emulation

 

 

9. startup code와 bootloader, bios 차이

 - startup code(boot code) : main 함수 실행 전 하드웨어 설정, 메모리 설정 등의 작업을 수행하는 code

   : 모든 작업 이후 main 함수를 호출한다.

    ex) HW 및 메모리 초기화, 레지스터 설정, bss 영역 생성 및 초기화, stack 메모리영역 setup 등

 - bootloader : 하드웨어 초기화, OS 및 응용프로그램의 Image를 메모리에 적제하여 실행하는 시스템 프로그램

                        bootloader의 위치는 일반적으로 ROM계열(nor)의 물리주소 0x0번지에 위치한다

                        (nand의 경우 몇블록 ~ 몇블록까지를 bootloader위치로 잡는다)

    ex) clock 설정, mux, pll lock time등 설정, 메모리 초기화, device 초기화(uart, ethernet, usb등)

 - bios : rom에 위치되어 있으며, 펌웨어에 해당. bios는 HW 동작점검(POST, Power On Self Test)이후 부트로더를 호출한다.

 * 링크 :  부트로더와 스타트업 코드의 차이

 - 스타트업 코드는 부트로더의 일부분(서브루틴)을 수행한다

 - 스타트업 코드는 응용프로그램 내부에 존재(컴파일 시 main함수 실행전에 스타트업 코드를 컴파일러가 추가)하고, 부트로더는 별도의 프로그램이다

 1) https://www.quora.com/What-is-the-difference-between-bootloader-startup-code-and-bootstrap-loader

 2) https://www.edaboard.com/threads/boot-loader-and-start-up-code.360150/

 

 

10. 프로세스 메모리 로드시의 섹션정보

High

  | stack

  | heap

  | ZI(.bss)

  | RWdata(.data)

  | ROdata(.text)

Low

 

 

11. 시스템 초기화

시스템 초기화에 수행하는 과정은 다음과 같다

 - Entry point 정의

 - Exception vector 설정

 - 메모리 시스템 초기화

 - 스택 포인터 레지스터 초기화

 - Critical I/O 초기화

 - (필요시) 프로세서의 모드 및 state 변환

 - 인터럽트 제어기 초기화

 - C 프로그램에서 사용되는 변수 영역 및 메모리 초기화

 - C코드로 분기(main 함수 실행)

* Entry point : 프로그램이 시작되기 위해 정의된 포인트(여기에서는 부팅에 해당하는 엔트리 포인트)

 : 보통 어셈블러로 구성되어 있으며, crt0.S, init.S, startup.S의 파일명을 가진다

   * 참조 : https://en.wikipedia.org/wiki/Entry_point

* Exception vector 설정

 - 2가지 방식이 있다

   1) 0x0 번지의 ROM에 vector table가 정의되어 있는 경우

     : ROM에 vector table이 고정되어 있고, 시스템 동작 중에 별도의 vector table의 설정이 필요없는 경우 사용

     : Re-mapping이 지원되지 않는 경우에는 항상 vector table이 고정된다

   2) 0x0 번지의 ROM에 vector table없이 초기화 코드만 있는경우

     : 0x0번지에 최소한의 reset handler가 동작하도록 정의되어 있고, 이 reset handler에서 re-mapping과 vector table을 초기화를 수행한다

     : Re-mapping이 지원되는 경우 (대부분) 시스템 동작중에 vector table의 초기화 과정이 존재한다

     * 임베디드 리눅스와 같은 임베디드 OS는 OS 초기화 과정에서 exception vector table 초기화 과정을 수행한다

* 시스템 초기화 과정 예시

 - Power-on 또는 reset switch으로 시스템 reset

 - reset handler로 분기

 - watch-dog 타이머 초기화

 - 외부 인터럽트 블록

 - clock 주파수, pll 등 타이머 초기화

 - 메모리 제어기 초기화

 - SVC, USR 등 각 모드별 stack을 초기화

 - 변수영역 초기화(.data, .bss 등)

 - c함수 분기 및 실행(main함수 실행)

 

 

12. 콜백함수

 - 함수를 call하는 방향이 반대인 구조, 하위 블록에 위치한 함수에서 상위(외부)에 위치한 함수를 함수포인터를 사용하여 호출하는 방식

 - 호출되는 함수가 죽어도 나머지 함수가 정상동작 될 수 있어 에러 메세지 출력 등의 행위로 사용자에게 알리고, 예외처리를 수행할 수 있도록 도와준다

 - https://namu.wiki/w/callback%20%ED%95%A8%EC%88%98

 - https://inpa.tistory.com/entry/JS-%F0%9F%93%9A-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%BD%9C%EB%B0%B1-%ED%95%A8%EC%88%98#%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8_%EC%BD%9C%EB%B0%B1_%ED%95%A8%EC%88%98_%EB%9E%80? 

 

 

13. 패딩 바이트

 - 컴파일러가 구조체의 메모리 결정시(컴파일과정에서) 추가적인 메모리 접근 없이(빠른 엑세스를 수행하기 위해) cpu가 한번에 읽어가는 크기(32bit 시스템은 32bit, 64bit 시스템은 64bit)에 맞추어 맴버들 사이에 여백(padding)을 넣는 방식

 * 참조 : https://coding-factory.tistory.com/670

 - 패딩 바이트 설정(byte alignment) 방법

    #pragma pack(1) //1바이트 단위로 패딩 설정(즉 패딩 존재x)

    #pragma pack()  //패딩설정 초기화

 

 

14. 비트필드

 - 구조체 또는 공용체의 맴버(필드)를 비트단위로 할당하는 방식

 - 선언함 멤버 순으로(혹은 역순으로, 컴파일러의 리틀엔디안, 빅엔디안에 따라 다름) 비트 단위로 순차적으로 할당

 - 사용법

 struct aa

{

    unsigned int a : 1; // 1bit 할당, 0~1값 저장가능

    unsigned int b : 3; // 3bit 할당, 0~7값 저장가능

}

 

#define GPCON (*(volatile aa *)0x10000000) // GPCON이라는 레지스터에 해당 구조체 자료형을 사용하고, 주소지에 맵핑

 

void main()

{

    GPCON.bb = 0x3; //0x10000000번지에 특정비트에 값입력

}

 

 * 참조

 - https://dojang.io/mod/page/view.php?id=472 

 

 

15. word의미

 - 한번에 처리하는 데이터의 크기, 레지스터의 크기를 의미하기도 하며, cpu가 한번에 읽어가는 데이터의 크기로도 이해할 수 있다. 또한, word 크기단위의 자료형을 int형이라고 한다(그래서 1word는 16bit일수도 32bit일수도 있다)

 

 

16. 풀업 풀다운 저항

 - 풀업 저항(pull-up resistor) :  전원부에 달려있는 저항. 스위치가 open되어 있는 상태(default)에서 입력단자를 high level로 유지시켜주기 위해 사용

 - 풀다운 저항(pull-down resistor) :  접지부에 달려있는 저항. 스위치가 open되어 있는 상태(default)에서 입력단자를 low level로 유지시켜주기 위해 사용

* 보다 정확한 개념은 플로팅 현상을 방지하기 위해 사용한다.

 - 플로팅 현상 : default상태는 스위치가 연결되지 않은 상태이고, 이때 저항이 없으면 전류가 흐르지 않아 입력단자(cpu입장에서)에서 해당 전위가 high 인지 low인지 알 수가 없게 되는 현상

 * 참조

 - https://k96-ozon.tistory.com/59

 - https://electronic-king.tistory.com/2

 

 

17. INTERRUPT, EXCEPTION, TRAP 구분

 - 워낙 혼용이 많이되고 있다. 시스템에 따라 다른 것으로 보임

 - EXCEPTION : HW에서 발행하는 인터럽트 중 오류에 해당하는 인터럽트. cpu 기준의 명령어 실행 오류, 데이터 읽기 오류 등이 여기에 해당하며, 일정 기준(혹은 시간)에 따라 오류가 발생하기 때문에 동기식 인터럽트에 해당한다

 - INTERRUPT : HW에서 발행하는 인터럽트 중 오류가 아닌 인터럽트. timer나 I/O 장치에 의해 발생하는 인터럽트가 여기에 해당하며, 예측이 불가하게(랜덤으로) 인터럽트가 발생하기 때문에 비동기식 인터럽트에 해당한다

 - TRAP : 소프트웨어 인터럽트라고도 한다. 실행 중인 프로그램 내에서 해당 인터럽트가 발생하면 매칭되는 ISR이 실행된다.

* 소프트웨어 인터럽트(SWI)는 시스템 콜에 의해 발생된다.

* exception의 분류가 이야기가 다르다. 어떤 곳에서는 exception은 HW에 해당하는 오류라고 하고, 어떤 곳에서는 SWI인 TRAP의 하위 분류에 해당한다고도 하고, trap과 exception은 서로 비슷한(혹은 같은) 의미로 사용된다고도 한다.

아무래도 임베디드 low단에서의 관점과 os에서의 관점이 다른 듯하다.(내가 임베디드를 배울때는 위에 적은 개념이 맞다)

나중에 공룡책을 따로 공부해야할듯

* 참조

 - https://kldp.org/node/49903

 - https://melonicedlatte.com/computerarchitecture/2019/02/12/213856.html

 - https://velog.io/@ohjinhokor/interrupt-vs-trap-%EA%B7%B8%EB%A6%AC%EA%B3%A0-software-interrupt-vs-hardware-interrupt

 - https://velog.io/@tlsdmsgp33/OS-%ED%8A%B8%EB%9E%A9%EA%B3%BC-%EC%8B%9C%EC%8A%A4%ED%85%9C%EC%BD%9C

 - https://luv-n-interest.tistory.com/997

 

 

18. HZ, jiffies에 대한 정리

 - tick time : 시스템 타이머의 인터럽트 사이의 시간

 - jiffies : 시스템이 부팅된후 발생한 틱타임 갯수

  아래의 링크에서 잘 설명되어 있다

* 참조

 - https://blog.naver.com/ryutuna/100167671737

 - https://velog.io/@whattsup_kim/Linux-Kernel-interrupt

 

 

19. TCM

 - Tightly Coupled Memory

 - sram으로 되어 있으며, core와 보다 가깝게 위치해 있다(캐쉬와 같이). 단, 캐시와는 다르게 별도의 port로 core와 직접 연결되어 있으며, cpu 기준 물리메모리 맵의 일부로 인식된다.

 - 주기억장치(램)의 특정 부분을 CPU 바로옆에 위치한 TCM메모리에 복사하여 시스템의 성능을 높이기 위해 사용한다.

 - 보통 interrupt handler, interrupt stack과 같은 critical data structure를 저장한다.

 * 참조

 - https://m.blog.naver.com/yyg1368/60209469032

 - https://blog.naver.com/chcbaram/222087830825

 - https://developer.arm.com/documentation/den0042/a/Tightly-Coupled-Memory

 

 

20. PIC

 - Programmable Interrupt Controler

 - cpu에서 HW 인터럽트를 처리하기 전, 여러 인터럽트들을 분류/처리 해주는 소자

 * 참조

 - https://itguava.tistory.com/17

 - https://ko.wikipedia.org/wiki/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EB%B8%94_%EC%9D%B8%ED%84%B0%EB%9F%BD%ED%8A%B8_%EC%BB%A8%ED%8A%B8%EB%A1%A4%EB%9F%AC

 - https://en.wikipedia.org/wiki/Programmable_interrupt_controller

 - https://access.redhat.com/documentation/ko-kr/red_hat_enterprise_linux_for_real_time/7/html/reference_guide/advanced_programmable_interrupt_controller

 

 

21. 미들웨어란

 - https://velog.io/@unyoi/%EC%9D%B8%ED%94%84%EB%9D%BC-%EB%BF%8C%EC%8B%9C%EA%B8%B01-%EB%AF%B8%EB%93%A4%EC%9B%A8%EC%96%B4-%EA%B0%9C%EB%85%90%EC%9D%84-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90

 

 

22. OS 관련 자료

 - https://kernel.bz/blogPost/kernel-mov-list

 

23. soft realtime, hard realtime, firm realtime system의 차이점

 - soft realtime : 시간제약사항을 여러번 어겨도 문제는 없지만 시스템 성능이 저하되는 시스템

 - hard realtime : 시간제약사항을 한번이라도 어기면 시스템에 치명적인 문제를 발생시키는 시스템

 - firm realtime : 시간제약사항을 몇 번 어기면 시스템 성능이 저하되고, 일정 이상으로 시간제약사항을 지키지 못하면 시스템에 치명적인 문제를 발생시키는 시스템

* 참조

 - https://www.shresthanischal.com.np/2021/02/difference-between-soft-hard-and-firm.html

 - https://stackoverflow.com/questions/17308956/differences-between-hard-real-time-soft-real-time-and-firm-real-time

 

24. 함수, 서브루틴, 프로시저 차이

 - 프로시저 : 함수와 서브루틴을 통칭하여 부르는 용어

 - 함수 :  실행 후 반환 값이 있는 구문 (코드블럭)

 - 서브루틴 :  실행 후 반환 값이 없는 구문(코드블럭)

 *  c나 c++에서는 동일한 의미로 사용된다고 한다

 

25. Bit Rate와 Baud Rate 차이

 - Bit Rate : 초당 전송 bit수

 - Baud Rate : 초당 전송 심볼(의미 있는 데이터 묶음)수

* 참조

 - https://melonicedlatte.com/2020/04/28/204700.html

 - https://ko.wikipedia.org/wiki/%EB%B3%B4_(%ED%86%B5%EC%8B%A0_%EB%8B%A8%EC%9C%84)

 - https://m.blog.naver.com/gmqgufrn/220862079486

 

26. 흐름제어란

 - 데이터 통신과정에서, 송신이 수신보다 더 빠른 속도로 데이터를 보내지 않도록 제어하는 것

 - 혼잡제어와는 구분해야한다

* 참조

 - http://www.ktword.co.kr/test/view/view.php?m_temp1=392

 - https://ko.wikipedia.org/wiki/%ED%9D%90%EB%A6%84_%EC%A0%9C%EC%96%B4

 

27. 동시성 문제와 race 상태

 - 동시성 문제 : 여러 프로세스 혹은 스레드가 동일한 자원에 접근하여 자원을 사용하고자 할 때 발생하는 문제

     ex: 두 스레드가 동시에 한 자원에 데이터를 쓰고자 함

 - race condition : 여러 프로세스 혹은 스레드가 동일한 자원에 접근하여 자원을 사용할 때, 접근 순서나 시점에 따라 예기치 않은 동작이 이루어지는 문제

* 참조

 - https://zzang9ha.tistory.com/443

 - https://en.wikipedia.org/wiki/Race_condition

 - https://iredays.tistory.com/125

 

28. 동기화, 비동기화 차이

 - 동기화 : 주어진 작업을 수행도중 상대에게 요청을 할 경우, 상대의 응답을 받을 때 까지 기다렸다가 응답이 도착하면 본인의 작업을 이어서 진행하는 방식

 - 비동기화 : 주어진 작업을 수행도중 상대에게 요청을 할 경우, 상대의 응답을 받지 않고도 본인의 작업을 이어서 진행하는 방식(나중에 응답을 받게된다)

* 참조

 - https://nesoy.github.io/articles/2017-01/Synchronized

 - https://da-nyee.github.io/posts/operation-system-synchronous-asynchronous/

 

29. 세마포어와 뮤텍스 차이

 - 세마포어 : 멀티테스킹 환경에서 공유자원을 관리하기 위한 변수, 바이너리 세마포어, 카운팅 세머포어로 구분된다

 - 뮤텍스 : 점유한 자원을 자기 자신만 반환이 가능한 바이너리 세마포어

* 참조

 - https://velog.io/@heetaeheo/%EB%AE%A4%ED%85%8D%EC%8A%A4Mutex%EC%99%80-%EC%84%B8%EB%A7%88%ED%8F%AC%EC%96%B4Semaphore%EC%9D%98-%EC%B0%A8%EC%9D%B4

 - https://en.wikipedia.org/wiki/Semaphore_(programming)

 

30. RTOS 포팅 후 시험

 - 코드가 정상적으로 컴파일, 어셈블링, 링크되었는지 확인

 - idle 함수(혹은 프로세스, 테스크), 초기화 함수(루틴 등) 를 소스레벨 디버거 및 Go/No Go 실행 사용하여 기능 확인

 - Idle 함수와 일반 함수간의 컨텍스트 스위칭 여부 확인

 - 클럭틱 ISR 확인

 

31. 임베디드 리눅스 시스템 구축 시 고려사항

 - 부트로더(하드웨어 의존성, 부트로더 옵션 또한 고려)

 - 커널 버전(적당한 기간이 지난, 안정화된 커널)

 - 루트파일 시스템에 포함할 항목 : 시스템 가동을 위한 응용프로그램, 라이브러리 등 최대한 가볍게 구성(파일 시스템의 크기 또한 고려해야함)

 

32. 리눅스 커널 부팅과정

 - 보드에서 압축된 커널의 압축을 풀고 난 이후의 과정

1) linux kernel start

 : start.S와 같이 어셈으로 실행(아래 과정 대부분 어셈블리로 실행된다), 코드상으로는 kernel entry가 존재하는 지점(ENTRY())이다

2) SVC 모드 전환 및 인터럽트 중지

3) 프로세서 정보 검색

 : 성공시 다음단계로, 실패시 에러(__error_p)

4) 머신 아키텍처 정보 검색

 : 성공시 다음단계로, 실패시 에러(__error_a)

5) 페이지 테이블 설정

6) MMU 및 Cache 설정

7) 스택 및 시스템 정보 설정

8) BSS Clear 

9) 시스템 정보 저장

10) start_kernel() 호출

 : 여기서부터 c코드로 구성됨

 : kernel page table, init kernel thread 생성 , irq 비활성화, kernel tick 초기화, smp core 설정, 스케줄러 호출 등을 수행

* init kernel thread

 - rfs 마운트, /dev/console open(stdin, stdout, stderr), 부팅시 부트로더에게 받은 kernel argument가 있으면 해당 명령어 실행,  init 프로세스 호출

 - init 프로세스는 /sbin/init, /etc/init, /bin/init, /bin/sh 순으로 생성을 시도한다. 성공시 프로세스 1번으로 생성.

11) kernel 초기화

 : 드라이버 체크 등의 초기화 과정 수행

* 참조

 - https://ko.wikipedia.org/wiki/%EB%A6%AC%EB%88%85%EC%8A%A4_%EC%8B%9C%EC%9E%91_%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4

 

33. linux에서의 인터럽트

 - 아키텍처에 따라서 interrupt controller의 구현이 다르다

 - 리눅스에서는 커널에 종속적인 인터럽트 처리 루틴과 아키텍처 종속적인 인터럽트 처리 루틴이 따로 구현되어 있다

 

 

34. udev

 - A Userspace Implementation of devfs, 커널을 위한 장치관리자

 - /sys 디렉터리를 들여다보고 실제 존재하는 디바이스에 대해 동적 디바이스 디렉토리를 제공

 - hotplug 서브시스템의 일부로서 디바이스가 추가되거나 제거되면 udev가 실행됨

   -> 모듈 적재 -> hotplug에 의해 udev 호출 -> /sys 조회(/etc/udev/rules.d/에 존재하는 udev 규칙에 따라 + /etc/udev/permissions.d/의 허가조건을 기반으로 /dev에 장치파일 생성)

* 참조

 - https://ko.wikipedia.org/wiki/Udev

 - https://access.redhat.com/documentation/ko-kr/red_hat_enterprise_linux/6/html/logical_volume_manager_administration/udev_device_manager

 

35. 포팅 순서

 - 필요에 따라 NAND 플래시 포팅 필요

 1) 개발환경구축(크로스 컴파일을 위한)

 2) 부트로더 포팅(u-boot)

 3) kernel 포팅

 4) RFS 포팅

 5) 패키징

 

36. 램 디스크(Ram disk)

 - ram 영역을 디스크 처럼 사용하는 방식

 - 임베디드 기준으로(sw방식으로)

 : 부팅 시 커널 이미지를 압축해제하는 것과 같이, 커널이 루트(/ 디렉터리)이하에 램디스크 이미지를 압축해제하여 타겟시스템 동작을 위한 init, busybox와 같은 프로그램을 사용하도록 한다.

 : 즉, 유틸리티와 같은 프로그램을 사용할 수 있도록  부족한 rom을 대신하여 ram를 활용한다

* 참조

 - https://ko.wikipedia.org/wiki/%EB%9E%A8_%EB%93%9C%EB%9D%BC%EC%9D%B4%EB%B8%8C

 - https://namu.wiki/w/%EB%9E%A8%20%EB%94%94%EC%8A%A4%ED%81%AC

 

37. 슬라이딩 윈도우

 - 두 호스트간의 네트워크 흐름을 제어하기 위한 기법

* 참조

 - https://ko.wikipedia.org/wiki/%EC%8A%AC%EB%9D%BC%EC%9D%B4%EB%94%A9_%EC%9C%88%EB%8F%84

 - https://velog.io/@alkwen0996/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EC%8A%AC%EB%9D%BC%EC%9D%B4%EB%94%A9-%EC%9C%88%EB%8F%84%EC%9A%B0Sliding-Window

 

38. 네트워크 통신방식

 - 유니캐스트 : 1:1 통신

 - 브로드캐스트 : 네트워크 그룹 내의 모든 호스트에게 통신(1:n, 불특정 다수)

 - 멀티캐스트 : 특정 그룹 내의 호스트들에게 통신(1:n, 특정집단)

 - 애니캐스트 : 같은 주소를 가진 호스트들 중 가장 근접한 호스트와 통신(1:1 통신, 네트워크 상황에 따라 가장 효율적인 네트워크를 제공하는 호스트(서버)와 통신)

* 참조

 - http://www.ktword.co.kr/test/view/view.php?m_temp1=549&id=845

 

39. 프로세스와 스레드 차이

 - 프로세스 : 별도 자원을 할당 받음. 별도의 IPC 통신을 구현해야함

 - 스레드 : 프로세스 내에서 존재하며, 다른 스레드와 자원을 공유(stack만 예외)

 

40. IPC 통신 종류

 - PIPE, Named PIPE, Message Queue, Shared Memory, Memory Map, Socket, Semaphore, Signal, Mailbox 등

* 참조

 - https://namu.wiki/w/%ED%8C%8C%EC%9D%B4%ED%94%84(UNIX)

 

41. Wiresharke, TCPdump

 - Wiresharke : Host 네트워크 내 패킷을 캡처하여 분석하는 프로그램. GUI 지원.

 - TCPdump : CLI에서 실행하는 패킷 캡처 및 분석 프로그램. 가벼워 임베디드에서 잘 사용한다

* 참조

 - https://namu.wiki/w/Wireshark

 

42. Subnet Mask

 - IP 주소에서 네트워크 아이디(Netid)와 호스트 아이디(Hostid)를 구분하기 위한 정보

 - 네트워크 클래스를 구분하기 위해 기본 서브넷 마스크가 존재하며, 

   & 연산 시, 네트워크 아이디를 구할 수 있고, (~)|  연산 시 호스트 아이디를 구할 수 있다.

* 참조

 - https://learn.microsoft.com/ko-kr/troubleshoot/windows-client/networking/tcpip-addressing-and-subnetting

 

43. 특정 목적의 IP 주소

 - 대표적으로 루프백 주소(보통 127.0.0.1 사용)가 있다

* 참조

 - https://xn--3e0bx5euxnjje69i70af08bea817g.xn--3e0b707e/jsp/resources/ipv4Info.jsp

 - https://namu.wiki/w/%EB%A3%A8%ED%94%84%EB%B0%B1%20IP

 

 

44. 커널 메세지 출력

 - /proc/kmsg : 커널 메세지 확인 경로(dmesg가 해당 경로에 커널메세지를 출력한다)

 - printk() : 커널 메세지로 출력시킬 수 있는 함수. print문과 같이 실행기간이 길고, 개행문자(\n) 가 있어야 출력을 시작한다

 

45. 디바이스 드라이버에서의 변수 사용법

 - 동시성 문제 발생 등을 방지하기 위해 지역변수를 사용하고, 전역변수가 필요할 경우 해당 드라이버 내에서만 사용할 수 있게 static 변수를 사용한다.(커널에는 방대한 함수와 전역변수가 선언되어 중복을 방지할 수도 있다)

 * 단, 블록내에서 static을 사용하면 전역변수 처럼 라이프 사이클이 변경되기 때문에, 전역변수에만 사용할 것

 - 전역변수는 보통 드라이버 시작(init) 부터 해제되는 시점(exit)까지 유지해야 하는 정보일 경우 사용한다

 

46. 커널에서의 동적메모리 관리

 - kmalloc(), kfree()를 사용한다

 - vmalloc(), vfree() :  가상메모리를 할당하는 함수, kmalloc과 다르게 할당할 수 있는 메모리의 크기가 제한되어 있지 않다(단, 가상 공간이 허용하는 한계까지만 가능)

   또한, 가상메모리 관리 루틴이 수행되까 때문에 kmalloc보다 느리며, 인터럽트 서비스 함수 안에서는 사용이 불가하다

 

47. dentry(Dentry Cache, Directory-entry Cache)

 - 한번 접근한 파일에 빠르게 접근하기 위해, inode 캐시에 대한 디렉터리 경로를 맵핑시켜놓은 캐시

* 참조

 - https://velog.io/@whattsup_kim/Linux-Kernel-Linux-File-System

 - https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=eldkrpdla121&logNo=220706916315

 - https://dataonair.or.kr/db-tech-reference/d-lounge/expert-column/?mod=document&uid=53002

 - https://unix.stackexchange.com/questions/4402/what-is-a-superblock-inode-dentry-and-a-file

 - https://karatus.tistory.com/203

 

48. 가상 파일시스템에 대한 자세한 분석

 - https://repository.kisti.re.kr/bitstream/10580/8041/1/2007-117%20%EA%B8%B0%EC%88%A0%20%EB%B6%84%EC%84%9D%20VFS.pdf

 - https://brewagebear.github.io/linux-kernel-internal-2/

 

49. 가상주소에서의 메모리영역

 - 커널 구성시 임의로 조절이 가능하나, 아래의 내용은 통상적인(default) 내용이다

 - 32bit 시스템은 가상 메모리 4gb를 할당

 - 64bit는 이론적으로 16EB의 가상 메모리 영역을 할당 받을 수 있지만, 너무 크고 비효율적이여서 128TB 정도로 제한

 - 32bit linux : 1gb 커널, 3gb 유저

 - 32bit windows : 2gb 커널, 2gb 유저

 - 64bit일때는 core가 x86-64이냐, arm이냐, 주소비트를 몇 비트를 사용할 것이냐에 따라 갈린다.

  하지만 구성비는 커널:유저 = 1:1이며, 0부터는 유저, fff... 부터는 커널이 할당되고, 중간에 주소로 할당되지 않는 공간은 비표준(non-canonical, 유효하지 않은 공간) 영역으로 둔다

* 참조

 - https://unix.stackexchange.com/questions/386522/why-does-debian-linux-allow-up-to-128tib-virtual-address-space-per-process-but-j

 - https://unix.stackexchange.com/questions/509607/how-a-64-bit-process-virtual-address-space-is-divided-in-linux

 - https://www.kernel.org/doc/html/v5.8/x86/x86_64/mm.html

 - https://kldp.org/node/162855

 

50. exception과 interrupt

 - 인터럽트 발생 시,  exception vector table를 확인하여 인터럽트(IRQ, SWI 등)인지 exception(Abort등)인지 확인 후,

    interrupt vector table를 확인하여 ISR(인터럽트를 처리하는 커널함수)을 실행하게 된다

 * 인터럽트 핸들러(Interrupt Handler) == 인터럽트 서비스 루틴(Interrupt Service Routine, ISR)

* 참조

 - https://wpaud16.tistory.com/277

 

 

51. top half와 bottom half

 - 인터럽트 발생 시, 해당하는 처리과정을 완수하기에는 너무 많은 과정이 있을 수 있다. 그래서 리눅스에서는 해당과정을 top half와 bottom half라는 두 과정으로 나누어 수행한다

 - top half

 : 인터럽트 핸들러에 해당. 시간적으로 매우 중요한(time critical) 작업 수행

 - bottom half

 : 상대적으로 나중에 해도 되는 작업, 모든 인터럽트가 발생이 가능한(block 되어 있지 않은) 환경에서 수행한다.

   (즉, 인터럽트가 완료되고 실행)

 : 최근에는 cpu의 발달로 bottom half를 잘 사용하지 않는 추세라고 한다(스레드를 통해 별도로 기능을 수행한다던가..)

 

 - 인터럽트 작업에서 top half와 bottom half를 구별하여 넣는 기준

 : 작업의 실행시간이 중요한 경우 top half(ISR)

 : 작업이 HW와 관련되어 있다면 top half(ISR)

 : 작업이 수행되는 도중 다른 인터럽트에 의해 방해되지 않아야 한다면 top half(ISR)

 : 그 외는 bottom half

 

 - bottom half의 종류

 : BH(초기 바텀하프), task queue, softirq, tasklet, work queue 등이 나왔지만 결론적으로 

  -> softirq, tasklet, work queue를 사용한다

 - softirq(빠른 반응속도)

   : time critical 하거나 자주 사용되는 작업일 때 사용. 서로 다른 프로세서에서 동시에 실행될 수 있기 때문에 동시성 방지작업 필요

 - tasklet(중간)

   : 스레드와 같이 동시에 수행되지 않고 휴면이 필요없는 경우 사용

   : 인터페이스가 간단하다

 - work queue(가장 느린 속도)

   : 지연된 작업이 프로세스의 컨텍스트에서 수행되도 문제가 없는 경우 사용

   : 즉, 해당 작업이 sleep 이 가능한 경우 사용한다

   * ex: 네트워크와 같이 초당 수천번의 인터럽트가 발생하는 상황은 work queue는 적절치 않다

   * 사용 편의성(개발자의 작업 난이도)

     : (쉬움) work queue > tasklet > softirq  (어려움)

 

52. 동시성 문제

 - 시스템에 존재하는 여러 프로세스가 특정한 공유자원을 동시에 사용할 때 발생

 - 동시성 문제가 발생하는 원인 : SMP 시스템, 선점형 커널, 디바이스 인터럽트의 비동기식 이벤트, 워크큐/테스크릿/타이머와 같은 메커니즘 사용

 - 동시성 회피 방법

   : 공유자원 사용 자제(ex: 커널 전역 변수 사용 자제)

   : 공위자원 관리(세마포어, 스핀락, 뮤텍스)

   : 자원에 대한 참조카운터 처리

 

53. 락킹 기법

 - sleep하는 락 : semaphore, mutex, reader writer semaphore, completion

 - sleep하지 않는 락 : spinlocks, seqlocks

   * 잘 중복되지 않고, 빠른 응답이 요구될 때 사용(즉 잠들지 않고 프로세서를 점유하며, 락이 풀리면 바로 실행됨)

 - 기타 락 : RCU(read-copy-update), atomic variable, bit operations

 - 락킹 기법 사용시 고려점

   : 데드락 상태 발생을 주의

   : 락킹 기법을 사용하는 함수는 락을 획득했다는 가정하에 작성할 것

   : 여러락을 얻을 경우 항상 같은 순서로 획득해야 함

   : 작은 단위의 락과 큰 단위의 락을 쓸 경우를 구별해야한다(단위의 구별은 임계영역(critical section)의 길이에 따라 구분)

   : 락이 필요없는 형태의 데이터 구조(원형버퍼 등)로 락킹기법을 최대한 사용하지 않도록 한다

 

 

54. 타이머 인터럽트

 - 타이머(HW)가 일정한 간격으로 생성하는 인터럽트, 시스템 시작 시 커널에서 HZ을 참조하여 설정한다(HZ는 상수로 define되어있음)

 - 아키텍처마다 HZ값은 다르며, 해당 아키텍처의 param.h에 정의되어 있음

 - HZ 값을 기준으로 스케줄링 시 동작시간을 체크할 수 있는 기준 값을 jiffies(jiffies_64)라고 한다

 - 관련변수

    1) HZ : 1초당 발생되는 타이머 인터럽트 횟수

    2) USER_HZ : 리눅스 2.4의 HZ값

    3) jiffies : 초당 HZ값 만큼 증가하는 전역변수, <linux/jiffies.h>에 선언되어 있다(1sec = jiffies/HZ)

    4) jiffies_64 : 64bit 크기의(jiffies는 32bit) jiffies (리눅스 2.6부터)

    5) get_jiffies_64() : jiffies_64 획득함수(리눅스 2.6부터)

 * USER_HZ의 용도 : 리눅스는 HZ값을 100으로 설정하는 것이 관행이었지만, 2.6부터 성능확장(프로세서별로 다른 HZ값을 가지기 때문에)을 위해 기존 2.4의 HZ를 USER_HZ로 하고, 해당 변수를 기반으로 현 시스템에 맞는 HZ 값을 계산(설정)하여 사용한다

 * tick time이란 타이머 인터럽트 간의 간격(시간)을 의미한다. 즉 tick = 1/HZ이다

 * 참조

 - https://stackoverflow.com/questions/17410841/how-does-user-hz-solve-the-jiffy-scaling-issue

 

 - 커널 타이머 : 틱단위로 타이머 인터럽트가 발생하고, 해당 시점에 특정 함수(작업)를 실행할 수 있다.

   즉, 특정 함수(작업)를 일정시간 이후에 실행시키거나, 하드웨어 상태를 주기적으로 감시(polling)하고자 할 때 사용한다.

 * 참조

 - https://mns010.tistory.com/27

 - https://julrams.tistory.com/4

 

 

55. 버스, 디바이스, 드라이버, 클래스

 - 디바이스 드라이버 중 일부 디바이스 드라이버는 문자나 블록 드라이버로 구분하기 어려운 경우가 있다. 커널 2.6부터 이러한 HW를 분류하고 처리방식을 통합하기 위해 아래와 같이 분류하였다.

1) bus : HW가 연결된 채널(bus구조)

 - 기존 버스나 새로운 가상버스를 생성하고 기존의 드라이버를 이 버스에 연결하여 관리

 - PCI, IDE, USB, PCMCIA, SCSI, I2C, PLATFORM(SW적으로 구성한 가상버스) 등이 있다

 

2) device : 실제 HW를 추상화(즉 실제 HW를 의미)

 - 커널에서 동작하는 하드웨어 개체, 실제 디바이스가 여러개일 경우 디바이스와 드라이버를 별도로 구분지어 관리해야한다

 - 저 수준 단계에서 디바이스를 device 구조체(struct device)의 인스턴스로 표현해야하며, 해당 구조체 등록 전에 bus_id, release, parent, bus필드를 설정해두어야 한다.

 - device 구조체는 < linux/device.h >에 정의되어 있다 

 

3) driver : 디바이스를 제어하는 소프트웨어

 - 드라이버는 시스템에 알려진 모든 드라이버를 추적, 관리하며(디바이스와 드라이버는 서로 매칭되기 때문에), device_driver  구조체로 정보를 관리한다

 

4) class : 하드웨어의 종류

 - 연결방식(bus)이나 동작방법(driver)보다는 기능적인 측면에서 디바이스를 관리

 - 대부분은 /sys/class에서 확인할 수 있으며, 일부 /sys/block에서 확인이 가능하다

 - class 구조체로 정보를 관리한다

 

 * 참조

 - Documentation/driver-model/

 - include/linux/device.h

 

 

56. kobject 란

 - '커널이 제공하는 가상파일 시스템(sysfs)'과 '시스템에서 인식한 디바이스'와의 연결을 위해 사용하는 kobject 타입의 객체를 의미

 - /sys 디렉터리 하위에 장치들이 등록된 것을 확인할 수 있다

* 참조

 - https://kernel.bz/boardPost/118679/9

 - http://www.learningaboutelectronics.com/Articles/Kobject-linux.php

 - https://yongshikmoon.github.io/2021/04/11/kobject.html

 

 

57. platform device 란

 - 커널에 의해 핫플러그인이 불가한(즉, 자동으로 감지되지 않는) 하드웨어 디바이스
 - 보통 system on chip에 통합된 컨드롤러나 레거시 포트기반의 장치 등에서 발생한다
 * 레거시 포트의 예 : https://www.quora.com/What-is-a-legacy-port-used-for
* 참조
1) 플랫폼 디바이스란?
 - https://makersweb.net/embedded/17478
 - https://byu-cpe.github.io/ecen427/documentation/platform-device-tree/
 - https://docs.kernel.org/driver-api/driver-model/platform.html
 - https://freekhson.wordpress.com/2018/06/02/the-platform-device-api/
2) 플랫폼 디바이스와 타 디바이스간의 차이
 - https://kldp.org/node/164779
 - http://jake.dothome.co.kr/device-driver-3/
3) 플랫폼 드라이버에 대한 참조
 - http://www.aesop.or.kr/index.php?mid=Board_Community_QandA&document_srl=33652
 - https://slowbootkernelhacks.blogspot.com/2017/05/yocto-project-linux-device-driver.html

 

 

58. 응용프로그램 관점에서의 접근구조

 - 모든 관계를 한번에 도식화한 그림이 없어서 아래의 링크에 있는 사진을 적절히 조합해서 봐야함

 - app 입장에서는 low level i/o 함수를 사용하여 장치파일에 접근/읽기/쓰기를 수행

 - 이때 시스템 콜이 발생하고 이후부터는 커널단(가상 파일시스템을 거쳐 해당 장치파일에 연결된(매칭되는) 디바이스 드라이버를 실행)에서 수행한다.

 - 디바이스 드라이버에서 장치(HW)를 제어 시, device controller가 HW를 제어한다.

* 참조

 - https://en.wikipedia.org/wiki/Device_file

 - http://csmylov.blogspot.com/2017/07/device-control.html

 - https://karatus.tistory.com/206

 

 

기타

59. systemd

 - 

 * 참조

 - https://ko.wikipedia.org/wiki/Systemd

 - https://etloveguitar.tistory.com/57

 - https://stackframe.tistory.com/12

 - https://access.redhat.com/documentation/ko-kr/red_hat_enterprise_linux/7/html/system_administrators_guide/chap-managing_services_with_systemd

 

60. HAL

 - 

* 참조

 - https://namu.wiki/w/HAL

 - https://velog.io/@ketchup0211/%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C-Hardware-Abstraction-Layer-HAL-%EC%9D%B4%EB%9E%80

 

 

 

 

 

 

 

 

 

 

 

'Study > Embedded basic' 카테고리의 다른 글

Arm 구조 및 제어 - 2  (0) 2022.05.29
Arm 구조 및 제어 - 1  (0) 2022.05.29
임베디드 C 프로그래밍  (0) 2021.09.24
임베디드 시스템 이해 - 2  (0) 2021.09.24
임베디드 시스템 이해 - 1  (0) 2021.09.23

+ Recent posts