본문 바로가기
학교 공부/내장형 시스템

[내장형 시스템] make 파일과 임베디드 파일 시스템

by 그적 2020. 9. 21.

< 내장형 3주차 >


Make(Make Utility)
: 컴파일을 자동화 해주는 명령어 생성 프로그램
 - 최종 목표 파일의 빌드 과정을 정의해두면 필요한 작업만 수행하여 목표 파일을 생성한다.
 - rule을 정의해둔 파일이다.
 - make [-f filename]            // filename을 사용하여 make파일을 생성한다.

★★makefile의 기본구조★★
(기본 주요 구성 3가지)
- target : 반드시 존재, command를 실행하면 target이 만들어진다는 의미
- dependency : 없을 시에 target을 만들어 낼 때 필요한 것이 없다는 의미
- command : 없을 시에 아무 수행도 하지 않는다.

Target [or filename] : Dependency [file1, file2, ...]
[TAB] command // command를 사용할 땐 TAB이 필수. >> 없을 시에 syntax 오류가 발생
[TAB] command


(예시)
이전에 우리는 hello.c 파일과 hello_main.c 파일을 이용하여 hello 실행파일을 만들어 냈다.


hello : hello.o hello_main.o 

gcc -o hello hello.o hello_main.o // 위의 두 파일을 기준으로 아래 명령어를 실행한다. 

hello.o : hello.c 
gcc -c hello.c 

hello_main.o : hello_main.c 
gcc -c hello_main.c 



(매크로 예시)
복잡하고 반복되는 일련의 코드를 단순하게 표현한다. // 매크로를 정의한 후, 실제 사용 시에는 $으로 사용
- 사용자가 임의로 정의하여 사용할 수 있는 매크로
- 시스템에서 미리 정한 매크로


TARGET = hello 
OBJECTS = hello.o hello_main.o 
CC = /usr/bin/gcc 

$(TARGET) : $(OBJECTS) 
$(CC) -o $(TARGET) $(OBJECTS) 

hello.o : hello.c 
$(CC) -c hello.c 

hello_main.o : hello_main.c 
$(CC) -c hello_main.c 

clean :  
rm $(TARGET) $(OBJECTS) 

// 기본적으로 make라고 치면 make 파일을 뒤져서 제일 먼저 나오는 $(TARGET)을 먼저 실행하게 된다. 
// $make clean 을 치면, clean이라는 target을 실행시킨다.


-------------------------------------------------------------------------------------------------------------------------------------- 

리눅스 파일 시스템
- 파일이란? 디스크와 같은 물리적인 저장 매체에 저장되는 데이터 집합
- 파일 시스템이란? 파일을 어떻게 관리할 것인가에 대한 정책
                           (파일 + 디렉터리 구조)

임베디드 파일 시스템은 "Journaling Flash File System"
: 로그로 기록해두었다가 시스템 결함으로 문제가 발생할 경우, 파일 시스템을 복구시킨다.
  (ex. JFFS, EXT3)

1) Flash Memory를 위한 파일 시스템은 wear-leveling과 out-place update 방식을 사용한다.
   - wear-leveling은 전체 영역을 uniform(균등)하게 사용하는 것을 의미한다.
   - out-place update 방식은 overwrite 가 아닌, 반드시 delete를 하고 적재가 가능하다. 
2) 모든 inode를 읽어서 메모리에 저장한다.
 flash memory를 시스템에 연결할 때 flash memory 전체를 스캔하여 모든 inode를 메모리에 저장한다. 이렇게 할 경우 디렉토리 searching을 할 때 외부 메모리(flash memory)를 액세스 할 때보다 (메인 메모리에 저장하므로) 더 빠른 속도로 진행할 수 있다.
3) Linux Kernel 2.4부터 사용 가능
4) JFFS2는 JFFS의 문제점을 보완했다.


파일 저장 공간의 할당 방법
: 디스크 block 단위로 관리한다.

1) 연속 할당 : 연속된 블록을 하나의 파일에 순차적으로 할당한다.
  // 문제점 : 파일의 크기가 가변적으로 변화하는 경우에 연속 할당의 경우 성능 저하가 일어난다.

2) 불연속 할당
  - linked allocation : 순차 접근일 경우에 효과적이며, 직접 접근시에는 매우 비효율적이다. (ex. FAT)
                                  하나가 깨지면 뒤에 전체가 깨지기 때문이다.
  - indexed allocation : 인덱스 블록만 까보면 어떤 index를 사용하는지 알 수 있기에 index block을 관리해야 하며, 이로 인해 용량이 적은 경우에 낭비가 될 수 있다. 인덱스 블록이 필요하면 이를 연결 리스트로 관리한다. (ex. inode 기법)

 ** 리눅스에서는 디스크가 설치되면 장치 파일을 이용하여 해당 디스크에 접근한다. 장치 파일은 /dev에 위치한다.

논리적으로 하나의 시스템이지만, 물리적으로 서로 다른 디스크에 저장되어 있을 수 있다. 
>> 이러한 저장장치들을 연결하기 위한 것이 mount라는 명령어이고, mount라는 개념이 중요하다.



EXT2 파일 시스템
파일 시스템은 여러개의 block group으로 구성
(block 1 - partition boot sector를 위해 예약됨, bootloader인 LILO 또는 GRUB이 들어감)

★super block★  : 파일시스템에 관련한 파일 관련 정보를 저장한다.
 -
슈퍼 블록이 깨지게 되면 파일 시스템이 깨지게 된다.
 - 블록 그룹들 마다 슈퍼 블록이 존재하여 super block이 손상되더라도 전체 파일 시스템에 대한 정보를 잃지 않기 위해 복사본을 여러 곳에 유지시킨다.
(명령어 : $dumpe2fs /dev/sdb1 )

block bitmap
: 이 블록에 속한 각 비트는 그룹 내에 있는 각 블록의 사용 상태(yes/no)를 나타낸다.
 블록 크기가 4KByte면, 4K*8개(비트 하나를 가지고 블록을 표현할 수 있기에 8개) 블록의 사용 여부를 표시한다.

inode bitmap
: 사용되는지 사용되지 않는지를 확인한다.

inode table 
: 각각의 inode에 대한 정보를 나타내는 inode descriptor로 구성한다.
 1) mode, owner info, size, timestamp : file에 관한 메타 정보들 
 2) block pointers array : 파일의 실제 데이터가 저장된 위치(블록 번호)가 담김
  - direct block : 다이렉트
  - indirect blocks : 가리키는 블록이 데이터 블록
  - double indirect block : 가리키는 블록의 가리키는 블록이 데이터 블록



메모리에 위치하는 파일 시스템? proc 파일 시스템
: 현재 프로세스 및 커널에 관한 정보를 갖고 있다.
/proc/meminfo - 메모리 사용의 세부사항
/proc/filesystems - 설정된 파일 시스템 목록



리눅스 부팅 시퀀스
(시스템 콜을 구현하는 예제를 통해 우리는 결국 커널 소스코드를 수정하고, 수정된 코드를 컴파일할 것이다.)

1) 전원 ON
2) ROM-BIOS 실행(하드웨어 오류 검사(Post On Self Test, POST), 부팅 매체 탐색, 부트 로더 로딩(커널 존재를 앎))
3) 커널 로딩(부트 로더를 메모리에 적재함)
4) 커널 이미지 압축 해제
5) 메모리에 올린다음에 초기화 한 다음에 로그인 화면 고고



bootloader를 메모리에 적재 >> 하드 디스크의 첫 번째 섹터인 MBR의 내용을 메모리에 로딩한 후 제어권을 넘김
(MBR은 보통 부팅 매체의 0번 섹터를 지칭하며, 512byte를 가진다. 최근 나오는 컴퓨터의 용량은 커서 512바이트에 부트로드 코드를 다 적재하기는 힘들기 때문에, 기본적으로 필요한 부분만 MBR에 저장하고, 이를 통해서 2차 부트 로더를 호출한다. )

커널은 압축된 이미지이기 때문에 압축된 이미지를 풀고 수행한다. 커널 코드를 수정하는 사람은 많지 않기 때문에 커널 코드 수정할 수준이 되면 몸값이 올라간다.



시스템 콜
: 운영체제가 해야할 중요한 역할 중 하나가 사용자 프로세스들이 안정하게 사용할 수 있도록 하는 것.
 사용자 프로세스가 운영체제에게 수행되어야할 서비스를 제공받기 위한 프로그래밍 인터페이스이다.
  >> s/w interrupt를 이용하여 kernel에서 서비스를 요청한다.

- 사용자 모드에서 커널 모드로 스위치. 사용자 프로세스에서는 시스템 콜을 호출하는 라이브러리를 사용한다.
- read함수 안에 시스템 콜을 호출하는 코드가 들어있다. 
- portability가 향상된다.

** system call implementation
   : 번호가 할당되어 있어, 시스템 콜 인터페이스를 통해 i번째 커널 함수가 어디 있는지 알려주고, 수행하고 다시 컴백

system call 처리 과정
1) system call table 초기화
2) 라이브러리를 호출 후, 라이브러리에서 발생하는 system call 번호를
eax 레지스터에 저장
3) s/w 인터럽트(0x80) 발생시킴 // eax를 사용하면 32비트 컴퓨터임. 

4) user-> kernel로 변경
5) IVT(Interrupt Vector Table)을 뒤져, ISR이 0x80에 있는 것을 확인
6) ISR(Interrupt Service Routine)로 점프 후, 시스템 콜을 뒤져서 해당 커널 함수로 점프
7) 커널에서 시스템 콜 실행

8) kernel -> user로 변경 즉, 사용자 프로세스로 복귀



댓글