임베디드 91

[ Linux Kernel ] 32. 콜 스택(Call Stack)

32. 콜 스택(Call Stack) 실행 중인 코드를 추적하는 공간이 콜스택 => 함수(function)의 호출(call)을 기록하는 스택(stack) 자료구조 콜 스택(call stack)이란 컴퓨터 프로그램에서 현재 실행 중인 서브루틴에 관한 정보를 저장하는 스택 자료구조이다. 실행 스택(execution stack), 제어 스택(control stack), 런타인 스택(run-time), 기계 스택(machine stack)이라고도 하며, 그냥 줄여서 스택(stack)이라고도 한다. 소프트웨어 프로그램의 기능 수행에 있어 콜 스택의 관리가 중요함에도 불구하고, 상세한 구현은 고급 프로그래미이 언어에서는 보통 감추어지며 자동화되어 있따. 많은 컴퓨터들이 스택 관리를 위한 특별한 명령어(기계어)를 제..

[ Embedded ] 23. HAL(하드웨어 추상화 계층)

HAL Hadrware Abstraction Layer (하드웨어 추상화 계층) 하드웨어 추상화 계층이란 컴퓨터 본체와 같은 물리적 하드웨어와 OS 같은 컴퓨터에서 실행되는 소프트웨어 사이의 추상화 계층이다. 이게 무슨말인가? 과거에는 운영체제의 커널이 하드웨어를 조작하기 위한 추상적 인터페이스를 제공하였다. System Call이라는 인터페이스가 있어서 하드웨어 I/O를 디바이스 노드에 실행하였다. 하드웨어 종류가 많지 않던 과거에는 이 방법이 나쁘지 않았다. 하지만 하드웨어 종류는 시간이 갈수록 늘어만 갔고 커널은 새로운 장치들을 인식하거나 변화된 상태를 인식하는데 많은 어려움이 따랐다. 그래서 하드웨어 차이에 상관이 없는 하드웨어 인식 방법을 개발하고자 하는 취지로 HAL은 연구되었다. 개발된 HA..

[ Linux Kernel ] 31. 메모리 맵 파일(mmap)

31. 메모리 맵 파일(mmap) 프로그래밍은 데이터를 입력받아 처리하고 출력하는 작업이고, 이 데이터는 파일로써 디스크에 존재합니다. 내가 만약 '회원명단.csv'란 엑셀 파일을 가지고 여러 데이터 처리 작업을 해야한다고 가정해봅시다. 그렇다면 해당 파일에서 '읽기', '쓰기'를 할 때마다 디스크까지 접근해야할텐데 이러면 속도가 너무 느리지 않을까요? 만약 그 파일이 디스크가 아닌 메모리에 있다면 접근 속도는 엄청나게 향상되지않을까요? 이러한 발상은 최소한의 디스크 접근을 위한 버퍼 입출력에서 한 단계 더 나아간 발상입니다. '버퍼'란 개념이 아닌 디스크-메모리간의 '페이지(page)' 개념을 활용한 방식으로, 프로세스의 가상 메모리 주소 공간에 파일을 매핑한 뒤 가상 메모리 주소에 직접 접근하는 것으..

[ Linux Kernel ] 30. 스트림(Stream)이란?

30. 스트림(Stream)이란? 우리는 프로그램을 실행할 때 키보드를 통해서 입력을하고 모니터를 통해서 출력을 하고 있죠? 우리는 별다른 무리없이 간단하게 입출력을 합니다. 생각을 해보면 키보드에서 입력을 받고, 하드웨어적인 부분을 처리하여야 입력이 되고 화면으로 출력이 되겠죠? 예로 A라는 문자를 눌렀다고 가정해봅시다. 그러면 키보드에서 신호가 나갈 것이고, 그것을 컴퓨터에서 처리하여, 출력장치인 모니터로 신호를 보내 결과적으로 화면에 A라는 문자가 찍힐 것입니다. 그러나, 우리는 이렇게 하드웨어적인 세세한 부분까지 신경을 쓰지 않습니다. 입출력을 도와주는 스트림(Stream)이란 녀석이 있기 때문이죠 스트림을 사용하는 입출력 장치(Input/Output Device)는 많습니다. 키보드나 모니터 뿐..

[ Linux Kernel ] 29. 버퍼 입출력 - 표준 입출력 라이브러리

29. 버퍼 입출력 - 표준 입출력 라이브러리 파일 시스템의 최소 저장 단위는 '블록'이라는 추상 개념입니다. 따라서, 모든 입출력 연산은 블록 크기의 정수배에 맞춰서 일어납니다. 단지 1Byte를 읽고싶다하더라도, 512Byte만큼(1블록 = 512Byte라 가정) 읽어와야한다는 얘기입니다. 또는 내가 단지 2.5블록만큼(대략 1250Byte) '쓰기' 연산을 하고싶다하더라도 3블록에 대해 '쓰기' 연산을 해야한다는 얘기입니다. 그런데 잘 생각해보면 사용자 애플리케이션에서는 512Byte 단위로 입출력 연산이 이루어지지 않는 경우가 대부분입니다. 보통 CSV 파일을 다루기 위해 '필드' 단위의 입출력 연산이 필요하다거나, JSON 파일을 다루기 ..

[ Linux Kernel ] 28. 가상 파일 시스템

프로그래밍을 하다보면 빠지지 않는 것이 파일 처리인데요, 혹시 파일 작업을 하기 위해 read(), write()와 같은 시스템콜을 사용하면서 "왜 매개변수로 어떤 파일 시스템인지 넘겨주지않지?"라고 생각해보신적 있으신가요? 사실 조금만 생각해보면 답이 금방나오는 질문입니다. 이유는 파일 시스템이 추상화되어있기 때문입니다. 구조를 표현하면 다음 그림과 같습니다. 파일 시스템간의 공통된 인터페이스를 둠으로써 얻는 장점은 여러 가지가 있습니다. 동일한 방법으로 접근이 가능하다. 파일 시스템간의 이식성이 좋아진다. 새로운 파일 시스템이 추가되더라도 설계를 변경할 필요가 없다.

[ Linux Kernel ] 27. 다중 입출력 - poll()

27. 다중 입출력 - poll() poll() 시스템콜은 유닉스 운영체제의 최초 상용화 버전 중 하나인 'Unix System V'에서 제공하는 다중 입출력 방식이었습니다. 리눅스에서 제공하고 있던 select() 시스템콜보다 더 좋았던 까닭에 리눅스에서도 poll() 시스템콜을 도입하였습니다. select() 시스템콜의 단점을 보완한 poll() 시스템콜이지만, 기존에 select()로 다중 입출력을 구현했던 개발자의 습관과 타 시스템으로의 이식성을 이유로 덜 사용된다고 합니다. #include int poll(struct pollfd* fds, nfds_t nfds, int timeout); struct pollfd { int fd; // 파일 디스크립터 short events; //..

[ Linux Kernel ] 26. 다중 입출력 - select()

26. 다중 입출력 - select() '다중 입출력'은 프로그램(단일 스레드)에서 여러 개의 파일을 작업하고자 할 때 사용할 수 있는 메커니즘입니다. 사실 '단일 스레드'에서 여러 개의 파일을 작업하고자 할 때 사용할 수 있는 다른 방법으로는 '논블록(Non-Block) 입출력'을 사용하는 방법도 있긴 합니다만, '논블록(Non-Block) 입출력'은 프로그래밍 작업이 까다롭습니다. 이제부터 설명할 'select'는 '블록/비동기적 입출력'에서의 '다중 입출력' 모델입니다. A, B, C, D 4개의 파일을 다루는 작업을 하고싶다고 가정해볼때 다음과 같은 시나리오를 생각해볼 수 있습니다. A 파일에 대한..

[ Linux Kernel ] 25. 파일 입출력 - open(), read(), write()

25. 파일 입출력 유닉스 시스템에서는 거의 모든 것을 파일로 표현하므로 '파일 입출력'은 매우 중요한 부분입니다. 알다시피 파일은 '읽기'나 '쓰기' 전에 반드시 '열기(open)'를 해야합니다. 그리고 커널은 '파일 테이블'이라고 하는 프로세스별로 열린 파일 목록을 관리합니다. 각 프로세스에는 기본적으로 0, 1, 2 값을 가지는 파일 디스크립터가 open되어 있습니다. 0 - 표준 입력(stdin) 1 - 표준 출력(stdout) 2 - 표준 에러(stderr) 위의 3가지 파일 디스크립터를 직접 참조하는대신 C 라이브러리는 #define 매크로 정의를 제공합니다. 따라서, 해당 파일 디스크립터를 사용하고싶다면 아래 정의된 매크로로 참조하는게 좋습니다. #define STDIN_FILENO 0 #d..

[ Linux Kernel ] 24. 커널 프로그래밍에서 쉘 명령을 실행하는 방법

24. 커널 프로그래밍에서 쉘 명령을 실행하는 방법 유저레벨에서 커널에 있는 API 를 동작시키는 인터페이스는 시스템 콜로써 항상 사용되는 것이다. 하지만 커널 레벨에서 사용자 공간의 어플리케이션을 실행하는 것은 그다지 알려져 있지 않다. 하지만 가만히 생각해 보면 핫플러그인과 같이 USB 가 꼽히면 자동으로 마운트되는 것을 우리는 알고 있다. 과연 어플리케이션에서 주기적으로 USB 꼽힌 것을 체크해서 마운트 하는 것일까? 그렇지 않다. 커널 레벨에서 USB가 인식되면 종류에 따라 마운트를 시켜주는 함수가 실행되게 된다. 혹은 모듈이 필요하면 모듈까지도 로딩을 시켜준다. 이런 인터페이스가 가능한 커널 함수를 소개한다. 그 인터페이스의 이름은 usermodehelper API 이다. 그 API를 한번 살펴..

[ VoIP ] 07. LINUX Audio Programming

LINUX Audio Programming OSS(Open Sound System) 리눅스 커널에서는 기본적으로 사운드 디바이스 드라이버를 제공한다. 하지만, 리눅스 커널에 기본적으로 포함되어 있는 드라이버는 수가 적어 다양한 사운드 디바이스를 사용할 수 없다. 따라서, 몇가지의 대안이 존재한다. 리눅스의 커널에 기본적으로 포함된 사운드 디바이스 드라이버를 OSS/Free라고 한다. OSS/Free는 4Front Technologies에서 개발한 OSS를 따르는 공개 드라이버로 4Front Technologies의 OSS 개발자가 대부분을 개발하였다. 그러나 다양한 드라이버가 OSS/Free에는 존재하지 않고, 그 외의 많은 드라이버는 4Front Technologies에 의해 상용으로 개발된다. 따라서..

[ Linux Kernel ] 23. Platform Device & Driver

23. Platform Device & Driver 플랫폼디바이스는 하드웨어에 내장되어 있기 때문에 hot-pluggable이 아니다. 이 장치를 위한 드라이버는 장치의 존재를 확인할 필요가 없고 그냥 작동시키고(전원을 켜고) 장치가 작동하게 할 수 있도록 필요한 것을 작업한다. 만약 장치가 발견되지 않으면 드라이버는 가볍게 무시된다. 플랫폼 디바이스는 리눅스 커널이 USB나 PCI와 같은 버스를 통해 동적으로 감지할 수 없는 SoC(System-on-Chip)에 내장된 시스템 장치이다. 커널은 플롯폼 디바이스 메커니즘을 제공함으로써 실제로 존재하는 하드웨어에 대해 알 수 있다. 이 글에서는 플랫폼 디바이스의 커널 인터페이스에 대해 설명하며 디바이스 트리와 통합을 하기 위한 내용을 설명하겠다. Platf..

[ Linux Kernel ] 22. 커널에 모듈 추가하기

22. 커널에 모듈 추가하기 Kconfig => Kernel에 새로운 장치를 추가하고, 해당하는 모듈을 추가하기 위해서는 먼저 Kconfig라는 파일을 알아야한다~ Kconfig를 정리하자면 Tree구주로 된 Configuration option들의 집합으로 자신만의 종속성을 가지고 있음 Child Entry는 Parent Entry가 선택되어 볼 수 있게 되었을 때만 보임 Menu entry들은 각각의 config option을 정의하고 있음. 각각의 config option들은 자신만의 type을 가지며, tristate, bool type이 있음 tristate : bool : 이 type에 따라 어떤 선택을 하느냐에 따라 Kernel에 해당 모듈을 포함하는 여부가 결정된다.( 보통 make men..

[ Embedded ] 22. 임베디드 리눅스 구성요소(BSP)

6. 임베디드 리눅스 구성요소(BSP) - BSP란? BSP(Board Support Package)란 말은 본래 RTOS에서 나온 용어로, "보드를 떠받치는(지원하는)" 소프트웨어 패키지란 뜻으로, "보드(하드웨어)를 동작 시키기 위해 필요한 (임베디드) 소프트웨어 묶음" 이다. 위 그림은 Firmware와 RTOS로 구동되는 시스템과 Non-RTOS로 구동되는 시스템의 차이를 보여주고 있다. WindRiver 사의 VxWorks와 같은 일부 상용 RTOS를 제외하고 대부분의 RTOS와 자체 Firmware에는 Non-RTOS와 같은 파일 시스템(File System)이 없다. 즉 소스들이 아무리 많다 하더라도 결국 컴파일이 끝나면 최종적으로 (CPU에 종속적인) 바이널 실행 코드 하나만 생성된다. 따..

[ Embedded ] 21. 임베디드 개발환경(Toolchain, Compile...)

5. 임베디드 개발환경 Tool - Chain ? 리눅스에는 “gcc” 라는 C 컴파일러가 있다. 리눅스에서 gcc 컴파일러로 컴파일할 때 별도의 출력 파일 이름을 지정하지 않으면 a.out이라는 이름으로 생성된다. 생성된 파일은 “실행 가능한 ELF 파일” 타입으로 되어 있다. 즉, UNIX나 Linux에서 gcc로 컴파일하면 무조건 ELF 파일이 생성된다. 컴파일 과정(Compile) 텍스트로 되어 있는 소스 코드 파일을 이진 바이너리(Binary) 코드로 변환하는 과정. 가장 먼저 실제 컴파일을 진행하기 전에 소스 코드 상에 "#"(전처리기, Preprocessor)으로 처리되어 있는 부분들을 먼저 처리한다. 이후에 처리가 끝나면 C 문법 검사를 하게 된다. 오류가 없다면 이진 바이너리 코드로 변환..