728x90

디바이스 드라이버 작성

-> 디바이스 드라이버 작성 및 테스트 필요

- 처음부터 개발 <-> 개발 시간 절약을 위해 기존 다비이스 드라이버 참고 or 유사 기능 디바이스 드라이버 참고

- 커널 소스트리 driver 디렉토리 밑에있는 디바이스 드라이버 참고 or 공개된 디바이스드라이버 참고

-> 기능 검증으로 사용시 에러가 발생되지 않고, 사용자가 쉽게 써야함

 

(1) 디바이스 드라이버 개요

1) 디바이스 드라이버 제어

2) 디바이스 유형

3) 디바이스 드라이버

4) 주번호, 부번호

 

1) 디바이스 드라이버 제어

디바이스 제어 방법

1. /dev/mem 디바이스 파일 사용

 - memory mapped io인경우 메모리 어드레스를 사용한 장치접근

 - 디바이스 상태 진단을위해 주기적으로 상태점검해야하는 폴링방식 사용

    -> 디바이스로부터 인터럽트 요구에 대한 핸들러 구현이 복잡

2. 디바이스 드라이버 사용 

 

리눅스에서 디바이스 접근

- 사용자 프로그램 : 디바이스 파일을 사용해 접근

- 커널 : 디바이스 식별자(주번호, 부번호) 사용

- 주번호 : 디바이스 드라이버 식별

- 부번호: 같은 디바이스드라이버를 사용하는 여러개 드라이버 식별하기위해 사용

 

디바이스 파일

- 디바이스 드라이버에 대한 파일형태 인터페이스

- 디바이스 드라이버에 대한 접근과 일반 파일에 대한 접근이 동일

- 커널에서 사용하는 디바이스 파일은 /dev 디렉토리에 저장

 

디바이스 파일 생성

- 디바이스 파일 생성 : mknde [디바이스 파일이름] [디바이스 유형] [주번호] [부번호]

 ex) mknod /dev/mydevice c 240 1

    -> mydevice 라는 문자형 디바이스 파일을 /dev/디렉토리 밑에 만들고 주번호 240, 부번호 1로 설정

- 디바이스파일처리 : 저수준 파일입출력함수사용

 

저수준 파일입출력함수

- open 열기

- close 닫기

- read 읽기

- write 쓰기

- lseek 이동

- ioctl(제어)

- fsync(동기)

- 저수준 입출력함수는 버퍼를 사용하지 않고 직접 시스템 콜 호출

- 스트림 파일 입출력 함수 : 중간처리용 버퍼를 사용해 형식화된 입출력가능, 함수이름앞에 접두사 "f" 붙음

 

디바이스 드라이버 소스

- /usr/src/linux/drivers : 에 있는 소스들을 참고/변형하여 새로운 디바이스 드라이버 제작

- 모듈 형태로 디바이스 드라이버 개발시 -> 커널 재구성때 Loadable module support 옵션 선택해야함

 

2) 디바이스 유형

리눅스 디바이스 유형

1. 문자 디바이스

2. 블록 디바이스

3. 네트워크 디바이스

 

문자 디바이스

- 자료의 순차성을 지닌 디바이스

- 버퍼 캐시를 사용하지 않음

- 장치의 raw 데이터를 사용자에게 제공

 ex) 터미널, 시리얼포트, 병렬포트, 키보드, 사운드카드, 스캐너

- 리눅스에서 문자 디바이스 : 디바이스 유형이 'c'로 표시

 

블록 디바이스

- 랜덤 액세스 가능

- 버퍼캐시를 사용한 블록단위 입출력

- 파일시스템에 의해 마운트 되어 관리되는 디바이스

 ex) 디스크, RAM-DISK, CD-ROM

- 리눅스에서 블록 디바이스 : 디바이스 유형이 'b'로 표시

 

네트워크 디바이스

- 대응되는 디바이스 파일이 없음

- 네트워크를 통해 패킷을 송수신할수있는 디바이스

- 응용프로그램과의 통신은 socket(), bind() 등 전용 시스템 콜함수사용

 ex) 이더넷, PPP, ATM

 

3) 디바이스 드라이버

개요

- 커널은 디바이스 드라이버를 통해 입출력 디바이스 액세스

- 디바이스를 제어하는데 사용되는 데이터 구조체와 함수들로 구성

- 사용자 : /dev 디렉토리에 저장된 특수 파일의 파일명을 사용해 액세스

- 커널 : 디바이스 드라이버와 디바이스 주번호, 부번호로 액세스

user program <-> device file <-> VFS <-> device driver <-> real device

* 사용자 프로그램과 디바이스 드라이버 인터페이스는 가상 파일 시스템 상에 구현된 디바이스 드라이버를 통해 됨

 

사용자 관점에서 디바이스 드라이버

- 사용자는 디바이스 자체 자세한 정보 알필요없음

 ->디바이스는 하나의 파일로 인식

- 디바이스 파일 접근을 통해 실제 디바이스에 접근 가능

 

4) 주번호, 부번호

주번호 major number

- 리눅스 커널에서 사용할 디바이스 드라이버의 식별자로 0~255 숫자할당

- 2.4 커널 8비트 할당, 2.6커널 12비트 할당

 ex) 21: SCSI, 3 : IDE HDD

- 커널에서 사용하는 주번호 정보 : include/linux/major.h

 

부번호 minor number

- 동일한 디바이스 드라이버를 사용하는 서로 다른 장치 구분

- 2.4 커널 8비트

- 2.6 커널 20비트 할당

 ex) IDE 하드디스크 드라이버의 주번호=3인경우 첫번째 하드디스크 부번호 0, 두번째 하드디스크 번호는 1

 

 

 

 

(2) 디바이스 드라이버 작성

1) 디바이스 드라이버 작성 절차

2) 디바이스 드라이버 등록과 삭제

3) 파일 처리 함수

4) 디바이스 드라이버 컴파일

 

1) 디바이스 드라이버 작성 절차

작성 절차

1. 디바이스 드라이버 모듈 프로그램 작성 및 컴파일

2. insmod 유틸리티를 통해 디바이스 드라이버 모듈 적재 (커널에서 디바이스 드라이버 주번호 할당)

3. mknod 를 이용해 할당된 주번호로 디바이스 파일 생성

4. lsmod 유틸리티로 디바이스 드라이버 정상 등록 유무 확인

5. 디바이스 사용

6. 사용끝나면 rmmod 유틸리티를 사용하여 디바이스 드라이버 모듈 해제

 

기본 함수

- init_module() : 디바이스 드라이버 등록, 메모리 할당, 초기화

- cleanup_module() : 디바이스 드라이버 제거, 할당된 IO memory 영역 변환

- 함수 : read(), ioctl(), write(), open(), release()

-> 사용자 공간과 커널 공간의 데이터 전송, 메모리에 값을 읽거나 씀

 

디바이스 드라이버 원형

- 파일 처리 함수 데이터 구조체 생성 및 구조체 맴버변수에 제작한 함수 매핑

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
// 헤더 파일

int device_open(){}
int device_release(){}
ssize_t device_write(){}
ssize_t device_read(){}
// 함수 프로토 타입

static struct file_operations device_fops =
{
	read:device_read,
    write:device_write,
    open:device_open,
    release:device_release
};
// 파일 처리 함수

int init_module(void){} // 모듈 설치시 초기화 수행
void cleanup_module(void){} // 모듈 제거시 반환 작업 수행

/*
디바이스 드라이버는 모듈 프로그램 사용
-> 모듈 프로그램 원형에 디바이스 드라이버에 필요한 파일 처리 함수부분 추가
*/

 

 

2) 디바이스 드라이버 등록과 삭제

디바이스 드라이버 등록

- 디바이스 드라이버를 커널에 등록하는 함수

- 문자형 디바이스 : int device_chrdev(unsigned int major, const char *name, struct file_operations *fops);

- 블록형 함수 : int register_blkdev(unsigned int major, const char *name, struct file_operations *fops);

- 파라미터

  주번호 : 0을 주면 사용하지 않는 값반환

  이름 : /proc/devices에 표시 

  fops : 디바이스와 연관된 파일 연선 구조체 포인터 

- 음수가 반환시 오류가 발생한것. 디바이스 드라이버의 init_module()에서 호출

 

디바이스 드라이버 제거

커널에 등록되어있는 디바이스 드라이버 제거

- 문자형 디바이스 : int unregister_chrdev(unsigned int major, const char *name);

- 블록형 디바이스 : int unregister_blkdev(unsigend int major, const char *name);

- 디바이스 드라이버내 cleanup_module 루틴 안에서 호출

 

3) 파일 처리 함수

개요

- 디바이스 드라이버를 일반적인 파일과 유사한 인터페이스를 이용해 관리

- 디바이스는 파일 형태로 존재

- 커널은 파일 연산을 이용해 IO 연산수행하도록 인터페이스 구성

- 디바이스 드라이버 구현? -> 파일 연산 구조체에서 요구되는 기능들을 프로그래밍

ex) "mydev" character device의 파일 연산 구조체 예시

static struct file_operations mydev_fops = {
	write:mydev_put,
    read:mydev_get,
    ioctl:mydev_ioctl,
    open:mydev_open,
    release:mydev_release,
};

void mydev_put(){};
void mydev_get(){};
void mydev_ioctl(){};
void mydev_open(){};
void mydev_release(){};

 

file_operations 구조체

- 디바이스에 따라 선택적으로 사용

- 디바이스 연고나 연산은 함수를 직접구현하여 이 구조체의 해당함수로 매핑

 

파일 연산 구조체의 맴버 연선

- lseek() : 파일 액세스 지점 이동

- read() : 디바이스로 부터 데이트 입력받음

- write() : 디바이스로부터 데이터를 출력받음

- readdir() : 디렉토리 엔트리읽음

- poll() : 디바이스로부터 이벤트를 대기하므로 현재 프로세스를 대기큐에 넣음

- ioctl() : 디바이스 파일을 제어하며, read/write 함수로 처리할수없는 입출력 데이터 처리에 사용.

- mmap() : 파일이나 디바이스를 현재 프로세스의 메모리공간에 매핑

- open(),release()  : 디바이스 열기 닫기

- fsync() ; 버퍼에 남은 데이터를 모두 디바이스에 사용

 

4) 디바이스 드라이버 컴파일

- 일반 어플리케이션 컴파일 방법에도 별도 옵션 추가

-> 디바이스 드라이버는 모듈로 되어잇어 모듈프로그램 컴파일과 동일

ex) arm-linux-gcc -c -Wall -D__KERNEL__ -DMODULE -O2 driver.c

-> arm 용 크로스컴파일러를 사용한 예시

 

디바이스 드라이버 컴파일 옵션

- -c : 목적 파일이 insmod 명령을 통해 커널과 동적으로 링크 -> 링커를 호출하지 않고 컴파일만 진행

- -D__KERNEL__ : 소스의 선택적 컴파일

- -DMODULE : 소스의 선택적 컴파일을 위해 심볼 정의필요, 모듈 프로그램인 경우 커널과 모듈 심볼은 반드시 정의

- -O2 : 컴파일 최적화 레벨을 2로 설정. 컴파일러는 실행코드가 너무커지지 않는범위서

        실행속도를 빠르게하는 최적화 작업 수행

 

디바이스 드라이버 컴파일

- makefile을 작성해 make

CFLAGS=-D__KERNEL__ -DMODULE -Wall -O2
MODULE_OBJS=hello.o
$(MODULE_OBJS):
	arm-linux-gcc $(CFLAGS) -c hello.c
clean:
	rm -f *.o

 

 

 

(3) 디바이스 드라이버 사용 및 분석

1) 디바이스 드라이버 사용 절차

2) 디바이스 드라이버 작성 예시

3) 디바이스 드라이버 분석

 

 

1) 디바이스 드라이버 사용 절차

디바이스 드라이버 사용절차

1. 디바이스 드라이버 로딩

 - 컴파일한 모듈을 insmod 명령어로 로등

 - mknod 명령어로 디바이스 파일 생성

2. 응용프로그램 작성

 - open 함수로 디바이스 파일 열기

 - 디바이스 드라이버에서 제공하는 함수를 이용해 디바이스 제어

 - close()함수로 디바이스 파일 닫기

3. 디바이스 드라이버 제거

 - rmmod 명령어로 모듈 제거

 

2) 디바이스 드라이버 작성 예시

모듈 프로그램 소스

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>

int init_module(void){
	printk("Start pf module!!\n");
}

void cleanup_module(void){
	printk("end of module!!\n");
}

Makefile

CC=arm-linux-gcc
KEERNELDIR=/working/kernel/linux-2.4.20
INCLUDEDIR=-I$(KERNELDIR)/include -I./

CFLAGS=-D__KERNEL__ -DMODULE -Wall -O2 -I$(INCLUDEDIR)

MODULE_OBJS=mymod.o
MODULE_SRCS=mymod.c

$(MODULE_OBJS):
	$(CC) $(CFLAGS) -c $(MODULE_SRCS)

clean:
	rm -f *.o

 

드라이버 적재 및 삭제

# insmod mymod.o // 모듈을 커널에 로딩
Using mymod.o
Start of Module !! //init_module 함수가 실행되어 printk함수에 의해 출력

# lsmod
Module	size	Usedby
mymod	247		0(unused)

# rmmod mymod //cleanup_module 함수 실행
End of Module !!

 

3) 디바이스 드라이버 분석

디바이스 드라이버

- ARM 프로세서 기반 하드웨어 플랫폼에서 ARM의 GPIO에 연결된 LED를 제어하는 LED 디바이스 드라이버소스

#include <linux/ioport.h>
#include <asm/uaccess.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <asm/io.h>

#define LED_MAJOR 0
#define LED_NAME "LED PORT"
#define LED_MODULE_VERSION "v1.0"
#define LED_ADDR 0xf1600000
#define LED_ADDR_RANGE 1
// LED 디바이스 주번호, 디바이스이름, 버전번호, 가상어드레스 주소, 어드레스 범위

static int led_usage = 0;
static int led_major = 0;
//LED 사용 여부 표시하는변수, 주번호 저장하는 변수

int led_open(struct inode *minode, struct file *mfile);
int led_release(struct inode *minode, struct file *mfile);
ssize_t led_writeb(struct inode *minode, const char *gdata, size_t length, loff_t *off_what);

static struct file_operations_led_fops = {
	write:led_writeb,
    open:led_open,
    release:led_release,
};

int init_module(void){
	int result;
    
    result = register_chrdev(LED_MAJOR, LED_NAME, &led_fops);
    if (resulr <0){
    	printk(KERN_WARNING "can't get any major\n");
    	return result;
    }
    led_major =result;
    //커널에 등록된 IO자원중 지정된 주소로부터 일정 크기 영역사용가능한지 여부 확인
    if(!check_region(LED_ADDR, LED_ADDR_RANGE))
    	request_region(LED_ADDR, LED_ADDR_RANGE,LED_NAME); //시용영역확부
    else
    	printk("Can't get IO region");
    printf("init module, led major number : %d\n",result);
    return 0;
}

void cleanup_module(void){
	release_region(LED_ADDR, LED_ADDR_RANGE);
    if (unregister_chrdev(led_major, LED_NAME))
    	printk(KERNEL_WARNING "%s driver cleanup failed \n",LED_NAME);
}

int led_open(struct inode *mindoe, struct file *mfile){
	if (led_usage !=0) return -EBUSY;
    MOD_INC_USE_COUNT;
    led_usage=1;
    return 0;
}

int led_open(struct inode *mindoe, struct file *mfile){
    MOD_INC_USE_COUNT;
    led_usage=0;
    return 0;
}

//디바이스에 데이터를 써넣는 함수
ssize_t led_Writeb(struct file *inode, const char *gdata, size_t length, loff_t *off_what){
	unsigned char *addr;
    unsigned char c;
    
    //사용자 영역변수인 gdata로부터 커널영역인 c변수로 데이터 전달받음
    get_user(c, gdata);
    addr=(unsigned char*)(LED_ADDR);
    *addr=c;
    return length;
}

 

 

응용 프로그램

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main(int argc, char **argv){
	int dev;
    char buff;
    
    if (argc <= 1) return -1;
    dev = open("/dev/led", O_WRONLY);
    if (dev != -1){
    	buff =atoi(argv[1]);
        write(dev, &buff, 1);
        close(dev);
    }
    else {
    	printf("Device open Error\n");
        exit(-1);
    }
    return 0;
}

 

300x250
728x90

리눅스에서 입출력

- 수많은 입출력 장치해야함

- 디바이스 드라이버를 커널에 포함시켜 제공

- 직접 개발한 입출력 장치 추가하는경우 -> 장치 제어를 위한 디바이스 드라이버를 개발해야함

- 리눅스는 모놀리식 커널 -> 커널 기능 추가 및 변경 후 재컴파일 필요

- 대신 모듈을 사용해 커널에 동적으로 추가하거나 제거 ->재컴파일 해결, 필요할때만 커널의 크기를 줄이기가능

 

(1) 커널 프로그래밍 개요

1) 커널 프로그램과 응용 프로그램 비교

2) 커널 프로그래밍 주의사항

3) 커널 프로그램 함수

 

1) 커널 프로그램과 응용프로그램비교

실행 방식차이

1. 응용프로그램 : 실행 순서가 순차적임

  

2. 커널프로그램 : 커널에서 제공하는 시스템 콜/인터럽트에 의한 비동기적 프로그램

              -응용프로그램에서 시스템 콜 호출 or 외부 장치의 인터럽트

 

라이브러리

1. 응용프로그램 : 대부분 라이브러리를 링크하여 사용가능

2. 커널 프로그램 : 커널에서 export한 전용함수만 사용

 

어드레스 공간

- 응용프로그램, 커널 프로그램 : 서로 다른 어드레스 영역을 사용하여 각각 프로그램 코드에서 영향주지않음

- 페이지 오프셋 매크로를 기준으로 하위는 사용자 공간 상위는 커널공간이 된다.

 

사용자 공간과 커널 공간

1. 응용 프로그램 

 - 사용자 공간에서 실행. 직접적으로 하드웨어 장치나 메모리 접근 불가

2. 커널 프로그램

 - 커널 공간에서 실행. 직접적으로 하드웨어나 메모리 접근 가능.

 

변수및 함수명 충돌

1. 응용프로그램

 -현재개발하는 프로그램에서만 함수와 변수명 등 구별

2. 커널 프로그램

 - 커널 전반적인 함수와 변수명이 충돌하지 않도록 프로그래밍 해야함

 

2) 커널 프로그래밍 주의사항

커널 프로그래밍 주의사항

1. 라이브러리

 - 응용 프로그램에서 쓰던 "stdio.h" 같은 헤더파일의 중복성 유의

 - 커널에서 포함하는 헤더파일 사용

2. 변수및 함수명 충돌방지

 - 외부파일과 링크할 필요없는 심볼은 static 으로선언

 - 외부 파일과 링크할 필요있는 심볼은 심볼 테이블에 등록

 - 전역변수는 잘 정의된 접두어 사용

3. 주소 공간

 - 커널 스택 크기 제한. 인터럽트 핸들러 동일한 스택 사용 -> 큰 배열을쓰거나 재귀호출이 많이 안나도록 주의

 - 응용프로그램과 커널의 주소공간이 다르므로 응용프로그램과 데이터를 주고받기위해 특별한 함수사용

4. 에러 처리

 - 커널은 하드웨어 접근에 어떠한 제어 없음 - 커널 오류 ->치명적인 결과

 - 함수 호출시 에러발생 여부 검사해주고 처리

 

3) 커널 프로그램 함수

입출력 포트함수

- 일반 라이브러리 사용 불가

- 커널이 export 해준 함수만 사용가능

1. 입출력 포트함수

 - 디바이스 드라이버 프로그래밍에서 디바이스 레지스터 액세스에 활용

 - 입출력 포트 액세스 방법

    입출력 포트 함수 사용 : 입출력 포트 액세스 권한 획득 -> 포트 입출력 함수 호출

 - 디바이스 파일 통한 방법 : 디바이스 파일 /dev/port 오픈 -> read/write 함수 사용

2. 입출력 포트 할당

 - 커널 모드에서 액세스 권한 획득 - requset_region 함수

 - 커널에서 사용하고 있는 포트 확인 :/proc/ioports

 - 사용자 모드에서 액세스 권한 획득. ioperm 특정 포트에 대한개별설정함수, iopl 레벨로 권한설정하는 함수 함수

3. 데이터 입출력 함수

 - 입출력 포트로부터 데이터 입력 : inb,inw,inl(1,2,4바이트 입력)

 - 입출력 포트로부터 데이터 출력 : outb,outw,outl(1,2,4 바이트 출력)

4. 스트링 단위 데이터 입력 함수

 - insb, insw, insl(1*,2*,4* count 바이트 만큼 addr이 지정한 주소에 저장)

5. 스트링 단위 데이터 출력 함수

 - outsb,outsw,outsl(8비트, 16비트, 32비트  *count 만큼 출력)

 

인터럽트 처리 함수

- 디바이스 드라이버 -> 디바이스 관리 소프트웨어

- 인터럽트 핸들러 필요 -> 디바이스 드라이버에서 인터럽트 핸들러 등록 및 제어

- 인터럽트를 설정하고 처리하는 함수/매크로

1. 인터럽트 제어 함수

 - cli() :인터럽트 금지

 - sti() : 인터럽트 가능

2. 프로세서 상태 저장/복수 함수

 - save_flags : 현재 프로세서 상태를 flags 파라미터에 저장하는 함수

 - restore_flags : flags 파라미터에 저장딘 프로세서 상태 복원

3. 인터럽트 핸들러 등록/해제

 - request_irq : 인터럽트 핸들러 등록

 - free_irq : 등록된 인터럽트 핸들러 해제

4. 커널에서 동적 메모리 할당할떄 쓰는 함수

 - get_free_page, free_page : 한페이지 메모리할당하고 해제하는데 사용

 - kmalloc(), kfree() : 물리적으로 메모리를 할당하고 해제하는데 사용

 

(2) 모듈 프로그램

1) 커널 모듈

2) 모듈 프로그램 구성

3) 모듈 유틸리티

4) 모듈 컴파일

 

1) 커널 모듈

커널 모듈

- 커널 일부 기능을 독립적으로 구현한 코드

 -> 커널 실행중 동적으로 적재하거나 삭제 가능. 임베디드 시스템에 필요한 기능을 적재하는데 커널 모듈 사용

- 타겟 보드 목적과 구성에 따라 입출력 디바이스 설정

- 커널 설정시 모듈 설치가능 -> 정적로딩

- 커널이 실행되는 중간에 모듈 설치 ->동적 로딩

=> 사용자는 시스템 콜함수을 사용하여 모듈 사용가능

1. 디바이스 드라이버를 모듈로 설계

2. 커널 실행중 디바이스 드라이버를 동적으로 적재하거나 삭제

3. 커널을 반복적으로 재컴파일 하는 과정을 없앰

-> 개발시간 단축 + 불필요한 기능 동적 제거 => 커널 자원 효율적 이용

 

2) 모듈 프로그램 구성

모듈 프로그램 구성

1. 커널에서 수행될때 필요한 헤더파일과 모듈에 필요한 헤더파일 포함

2. init_module() 함수 정의

 - 모듈이 설치될때 초기화 수행 코드

 - 모듈에 필요한 메모리 할당 및 초기화 작업 실행

3. cleanup_module() 함수 정의

 - 모듈 제거시 반환작업 시행하는 코드

4. 모듈 설치될때초기화를 수행하는 코드와 모듈이 제거될때 반환하는 작업을 수행하는 코드 작성

5. init_module()과 cleanup_module() 함수 호출

 

모듈 관련 매크로

- MODULE_AUTHOR(string) : 모듈 제작자 정보

- MODULE_DESCRIPTION(string) : 모듈에 대한 설명 추가

- MODULE_PARAM() 모듈 파라미터 지정시

- MODULE_LICENSE() : 모듈 라이센스 설정

 

3) 모듈 유틸리티

모듈 적재

- /sbin/insmod [option] [-o module_name] object_file

- 옵션

  f : 커널과 모듈 버전이 달라도 강제 적제

  k : 모듈 일정시간안쓸시 kerneld 데몬이 자동 삭제

  m : 커널 패닉때 로드맵 출력해서 디버깅 쉽게함

  p : 모듈 적재 가능성 검사

  o : 모듈 이름 직접지정시 사용

  s : syslog에 메시지 출력

 

모듈 삭제

- /sbin/rmmod [option] module_name

- 옵션

 f : 강제 제거

 w : 모듈이 제거될수있을때까지 기다리다 제거

 s : syslog 매시지 출력

 

적재된 모듈 확인

- /sbin/insmod 나 cat /proc/modules로 확인 가능

 

모듈 사이 의존성 검사

- depmod 유틸리티

 

모듈의 적재 및 제거

- modprobe -> /etc/modules를 탐색하여 해당 모듈과 의존관계 있는 모듈들을 같이 적재

 

4) 모듈 컴파일

컴파일 옵션

- c 옵션 : 커널 모듈은 독립적 실행이 아니라 커널에 링크되어 실행됨. 링크 호출 제거

- Wall 옵션 : 잘못 동작되면 오류메시지 출력

- O 옵션 : 최적화 실행

 

심볼 정의

- _KERNEL 심볼 : 모듈이 커널모드에서만 실행

- MODULE 심볼 : 헤더파일에게 모듈에서 사용되는 코드로 인식

- LINUX 심볼 :리눅스를 인식

300x250
728x90

임베디드 시스템에서 입출력 장치 접근

1. 디바이스 드라이버 사용하는방법

 - 디바이스 데이터 입출력 기능과 디바이스 제어하는 기능

 - 디바이스에 대한 공통 인터페이스(파일 인터페이스)를 통해 모든 디바이스에 유사한 방법으로 접근

2. 물리 어드레스를 통해 직접 접근하는 방법

 - 운영체제 안쓰는 경우 디바이스 물리 어드레스맵으로 물리어드레스를 알수있슴

 - 리눅스 경우 메모리 디바이스 파일을 이용해 물리 어드레스 공간에 접근

 -> 물리 어드레스로 디바이스 제어를 위해 디바이스 동작과 제어 방법을 이해해야함

 

(1) 입출력 장치 제어 방법

1) 임베디드 시스템 정의

2) 가상주소를 이용한 접근

 

1) 입출력 장치 제어

입출력 장치 접근방법

1. 물리 어드레스 사용한 접근

 - 가상 어드레스를 물리 어드레스로 변경하는 전용함수로 입출력 장치 접근

2. 디바이스 드라이버 사용한 간접 접근

 - 운영체제서 제공하는 디바이스 드라이버로 간접적으로 접근

 

입출력 장치 제어 프로그램 구현 방법

1. 물리 어드레스 사용한 접근

 - 가상 메모리 변환 함수 사용

2. 디바이스 드라이버 사용한 간접 접근

 - 커널에 디바이스 드라이버 모듈 등록

=> 사용자 응용 프로그램 특성에 따라 입출력 제어방식 선택

 

입출력 장치 어드레스 매핑 방식

1. Memorry Mapped IO

 - 입출력 장치와 메모리가 동일한 주소체계

 - 프로세서는 입출력 장치도 메모리 처럼취급

 -> 다양한 메모리 접근 명령어들을 입출력 장치에 동일하게 사용가능

 <-> 메모리 공간이 줄어듬

2. IO Mapped IO

 - 메모리 주소체계와 입출력 장치 주소체계를 분리해서 사용

 - 입출력 전용 명령어 및 전용 주소 체계 사용

 -> 메모리 공간 손실 없음

 <-> 입출력 전용 명령어 필요

=> 대부분 32비트 프로세서는 Memoery Mapped IO 사용

 

가상 어드레스 Virtual Address

- 리눅스 커널 내부에서 사용하는 논리적 어드레스 체계

- 메모리 관리 시스템 MMU을 사용하여 물리 어드레스와 가상 어드레스 변환

- TLB Translation Looaside Buffer

  1. MMU 내부에 존재

  2. 물리 어드레스 또는 가상 어드레스로 변환시 참조하는 테이블

  3. 응용프로그램에서 사용하는 가상 어드레스는 TLB를 사용해 물리 어드레스로 변환되어 메인 메모리를 직접 액세스

  4. 대부분 32비트 프로세서는 Memory mapped io 사용

   -> TLB를 통해 가상 어드레스만으로 입출력 장치를 직접 액세스

 

포인터를 사용한 데이터 전송

- 응용프로그램에서 입출력 장치에 데이터 전송하는것은 포인터 변수에 물리 어드레스줘 데이터를 쓰고읽으며 이루어짐

* 리눅스 커널에서 물리적 접근을 허가하지 않기 때문에 아래의 경우 오류가 발생 -> 가상주소를 사용해야함

unsigned int *ptr;
ptr = 0xf1000000;	//물리주소 할당
*ptr = 0xc0;		//포인터를 사용한 데이터 쓰기

2) 가상주소를 사용한 접근

메모리 디바이스

- 메모리 디바이스 파일 /dev/mem

  -> 시스템 메모리 공간에 접근할수 있는 장치파일

- 메인 메모리의 이미지를 가진 문자형 디바이스

- 주로 시스템 테스트 용도로 사용

- 입출력 장치를 직접접근하는 디바이스로 활용

 

응용 프로그램에서 특정 물리 어드레스 접근

- 가상 어드레스 획득 : mmap()함수

1. 입출력 장치의 가상어드레스 획득

2. 어드레스에 대한 읽기 쓰기 작업 실행

3. 입출력 장치와 데이터 전송

- 데이터 읽기쓰기 : 메모리 장치 디바이스를 통한 lseek(), read(), write()함수 사용

 

mmap 함수 사용

- 파일이나 디바이스를 메모리로 매핑시켜주는 함수

- 반환값 : 주어진 물리주소에 해당하는 가상주소값

 

응용 프로그램 코드에서 "mmap()" 함수 사용절차

1. mmap() 호출

2. 커널은 내부적으로 mmap() 함수 파라미터를 해석하여 매핑 영역 설정

3. 그 위치에 해당하는 가상주소를 계산하여 반환

4. 응용프로그램에서는 반환된  가상주소를 포인터 변수에 대입

5. 포인터 변수에 값을 할당하거나 변수 값을 읽어 데이터 전송

 

2)munmap()

- munmap() - mmap() : par 함수

- mmap으로 맵핑된 메모리 해제

- 형식

#include <unistd.h>
#include <sys/mman.h>
int munmap(void *start, size_t length);

- 파라미터

  start : mmap()에서 반환했던 가상주소를 대입하여 해제할 매핑영역 전달

  length : 해제할때 영역의 길이를 byte 단위로 계산하여 대입

- 성공시 0 실패시 -1 반환

 

munmap() 실행에 따른 오류반환값

1. EBADF : fd가 유효하지 않거나 MAP_ANONYMOUS가 설정되지않음

2. EACCES : MAP_PRIVATE가 설정되어있지만, fd가 못쓰는 경우

3. EINVAL : starrt나 length나 offest 이 적당하지 않음, 너무크거나 PAGESIZE 경계로 정렬되지 않음

4. EAGAIN : 파일이 잠겨있거나 너무 많은 memory가 잠김

 

mmap/munmap 함수사용하는 방법

1. open()함수로 파일 디스크립터 획득

2. mmap()함수로 제어할 IO 포인터 획득

3. 포인터로 값을 읽거나 원하는 값을씀

4. munmap() 함수로 매핑한 메모리 공간 해제

5. close()함수로 오픈한 파일디스크깁터 반환

 

간단한 LED 제어

#include <unistd.h>
#include <sys/mman.h>

#define ADDR_LED 0x00a1111

fd = open("/dev/mem",O_RDWR);
addr= mmap(NULL,1,PROT_WRITE,MAP_SHARED,fd,ADDR_LED);
//1바이트를 메모리에 매핑, 매핑 영역에 대한 쓰기 권한 허용, 다른프로세서에서 쓸수있도록 매핑공유
*addr=0xaa;
munmap(addr,1);
close(fd)

간단한 전체 프로그램

#include <unistd.h>
#include <sys/mman.h>
#include <asm/fcntl.h>

int main()
{
	int fd;
    unsigned int *maddr, *ptr;
    if (((fd=open("/dev/mem", O_RDWR)) < 0) exit(1);
    
    maddr=mmap(NULL, 1024, PROT_WRITE, MAP_SHARED, fd, 0xf0000000);
    if ((int)maddr <0) return -1;
    ptr = maddr;
    ptr= ptr+68;
    *ptr=0x1000401;
    ptr++;
    *ptr=0xf10080000;
    munmap(maddr,1024);
    close(fd);
    return (0);
}
300x250
728x90

임베디드 시스템

- 부피/전력이 큰 하드디스크 대신 플래시 메모리 사용

- 하드디스크를 가상으로 구현하고 파일시스템을 만든것 -> 플래시 파일시시스템

 

플래시 시스템

- 플래시 메모리 특성에 최적화

- 데이터 읽기는 블록과 관계없이 바이트 단위로 자유롭게 읽음

- 데이터 변경시 블록 단위로 처리

- 쓰기 수명이 있어 메모리 수명고려

- 모든 블럭에 골고루 쓰기하여 수명을 최대한 늘여야한다.

 

(1) 플래시 파일 시스템

1) 플래시 메모리 구조

2) 플래시 파일 시스템

3) JFFS

4) YAFFS

 

1) 플래시 메모리 구조

플래시 메모리

- 저비용 불활성 메모리

- In-system rewritable eprom

- nor형 : 셀 크기가 크지만, 고속 랜덤 액세스 가능

- nand 형 :셀 크기가 작고, 고속의 burst 액세스 가능

 

                       NOR형     NAND형

- 프로그램 속도    느림         빠름

- 직접도              낮음         높음

- 액세스 단위 속도  높음        낮음

                            x     임베디드시스템에서 주로사용

* 데이터 액세스 속도가 느리므로 대부분 프로그램은 플래시메모리 내용을 메인메모리에 복사하여 실행

 

2) 플래시 파일 시스템

플래시 파일 시스템

- 플래시 메모리상에 구현된 전용파일 시스템

- 아래의 이유로  ext2 파일 시스템 구현 힘듬

 ->블록 크기차이 : 플래시 메모리 - 64k ~256k / ext2 - 1 ~ 8k

 -> 플래시 메모리 삭제 및 횟수 제한

- 비용부담 -> 파일 시스템 크기 축소하기위해 파일시스템 이미지 합축

- 파일시스템 신뢰도향상 -> 저널링 사용

 

플래시 메모리의 XIP(Excutable in place) 기능

- 플래시 메모리에 저장된 내용을 RAM에 복사하지 않고 플래시 상에 직접 실행하는 독작모드

- 파일시스템 압축 -> XIP 구현힘듬

- XIP 기능 사용 -> writabe 파일시스템 구현 힘듬

 

MTD(Memory technology device)

- 리눅스에서 제공하는 플래시 메모리 추상화 계층

- 다양한 플래시 메모리에 대해 동일한 API 사용

- MMC, SD, CF 지원하지 않음

- /dev/mtd0, /dev/mtd1 를 통해 데이터 입출력

- ioctl() 함수를 사용하여 MTD 정보 참조

 

FTL(Flash Translation Layer)

- 플래시 메모리를 블록 디바이스로 추상화

- 리눅스에서 플래시 메모리를 블록디바이스로 처리가능 -> 파일시스템 구현 가능

 

3)JFFS

JFFS

- Journaling Flash File System

- 디스크 없는 임베디드 시스템에서 NOR 플래시 메모리를 사용한 저널링 파일 시스템

- MTD 통해접근, 순환로그를 사용해 플래시 메모리 수명 늘림

 

JFFS2

- JFFS의 NAND 플래시용 파일 시스템

- 압축을 통한 성능향상

- 하드링크 지원

 

(2)임베디드 시스템의 플래시 메모리 활용

1) 플래시 메모리 활용

2) 플래시 메모리 맵

3) 플래시 메모리 퓨징

4) 플래시 메모리 퓨징 실시 예

 

1) 플래시 메모리 활용

임베디드 시스템의 플래시 메모리 활용

 1. 부트로더, 커널이미지, 램디스크 이미지 저장공간으로 사용

 - 초기 부팅과정에서 모두 메인메모리로 압축해제된 형태로 복사되어 실행

 - 응용프로그램 실행과정에서 데이터 저장이 필요한 경우 플래시 메모리 특정공간을 할당해서 직접 써넣음

2.. JFFS, YAFFS 플래시 파일 시스템을 사용하여 하드처럼 사용

 

2) 플래시 메모리 맵

- 플래시 메모리의 분할 구조

- 플래시 메모리를 블록단위로 나누어 그 용도를 사전에 정의

- 임베디드 소프트웨어 컴포넌트들이 저장되는 위치들로 맵을 구성

 

플래시 메모리 맵 예시

- 램디스크들의 물리적 위치가 사전에 정의

3) 플래시 메모리 퓨징

- 퓨징 : 프로그램 또는 데이터를 플래시 메모리 맵에 따라 써넣는것

  ->퓨징의 주체에따라 호스트 컴퓨터 퓨징, 타겟보드 퓨징

 

호스트 컴퓨터 퓨징

-호스트 컴퓨터에서 타겟 보드 플래시 메모리를 직접 퓨징

- 호스트 병렬 프린텉 포트와 타겟보드의 JTAG 인터페이스 연결하여 퓨징

- 타겟 보드에 초기화 프로그램(부트로더)가 설치안된경우 초기화 프로그램을 퓨징할때 사용

 

타겟보드 퓨징

- 초기화 프로그램(부트로더)에서 TFTP를사용

- 소프트웨어 컴포넌트를 타겟보드의 RAM에 다운로드

- 부트로더의 퓨징 명령어 사용

- 플래시 메모리 퓨징

-> 초기화 프로그램을 제외한 나머지 컴포넌트를 퓨징할때 사용

 

300x250
728x90

램디스크

- 파일시스템을 램 상에 구현한 가상의 하드디스크

- 부팅 초기에 부팅속도 향상을 위해 루트파일시스템을 마운트하여 사용

- 임베디드 시스템에서는 비휘발성인 플래시 메모리에 램디스크 이미지를 압축해서 저장

- 부팅과정에서 램디스크 이미지를 휘발성 메모리인 램에 로딩해서 사용

- 리눅스 상에서 램디스크를 생성하고 수정하는 절차를 배움

 

(1) 램디스크 개요

1) 램디스크

2) 램디스크 관련 명령어

3) 램디스크 생성 절차

4) 램디스크 수정 절차

 

1) 램디스크

램디스크 개요

- 램디스크 : 메모리의 일정공간을 하드디스크 처럼 사용

- 램디스크 이미지 : ext2 파일시스템의이미지를 갖는파일

   ->  램디스크 이미지 1개로 표현

- 램디스크 오브젝트 : 램디스크 이미지를 가지고있는 ELF 오브젝트 파일

   -> 램디스크를 리눅스 커널에 링크할때 사용

- 램디스크 디바이스 파일명 /dev/ram0

 

램디스크활용

- 장점 : 하드디스크보다 rw 속도빠름

- 단점 : 휘발성 메모리로 전원공급중단시 파괴

- 부팅 초기에 루트파일시스템의 필수부분만을 마운트하여 부팅속도 향상

1. 플래시 메모리에 램디스크 이미지 압축저장

2. 부팅과정에 램디스크 이미지 압축해재

3. 휘발성 메모리 램에 로딩하여사용

 

임베디드 시스템에서 하드쓰지 않는경우

- 램드스크, 플래시메모리상에 플래시파일시스템사용하여 시스템구현

 

응용프로그램개발, 유틸리티 프로그램이 추가되야하는경우

-> 램디스크 이미지 수정작업이 필요

 

루프백(Loopback) 디바이스

- 파일을 블록디바이스처럼 사용하는 가상디바이스

- 사용전에 파일 시스템에 마운팅

- 램디스크같이 파일 시스템이 파일로 표현되는경우 사용

- 램디스크 이미지는 루프백 디바이스로 설정해주어야 한다.

- 루프백 디바이스명 : /dev/loop0

 

초기 램디스크 디바이스

- initr : 주번호 1, 부번호 250, 읽기전용 디바이스, 리눅스부팅시 임시루트파일 시스템저장하는 램디스크

      init 프로세스 실행에 필요한 디바이스 드라이버 및 유틸리티포함

 

초기 램디스크 디바이스 사용한 부팅절차

1. 초기램디스크디바이스마운팅완료

2. 램디스크 상에있는 /linuxrc 프로그램실행

3. 실제 루트파일시스템으로 마운팅

  -> 실제 루트파일시스템이 /initrd 디렉토리를 포함하고있으면 램디스크 디바이스 마운팅 위치가/에서 /initrd로바뀜

4. 램디스크상에 있는 /linuxr 프로그램이 실행

 

2) 램디스크 관련 명령어

dd(Data definition) 명령어

- raw 데이터를 저수준에서 복사하거나 변환 하는 명령어

- 초기 램디스크를 만들경우 사용

 

mke2fs 명령어

- 파티션 초기화

- ext2 or ext3 파일시스템 생성

 

mount 명령어

- 파일시스템을 마운트하는 명령어

 

losetup  명령어

- 루프백 디바이스 셋업 및 제어

 

4) 램디스크 수정

- 램디스크 이미지 파일은 압축된 루프백 디바이스 파일

  -> 압축해재후 루프백 디바이스를 사용하여 마운트 과정이 필요

 

 

(2) 루트파일시스템

1) 루트파일 시스템개요

2) 루트 파일 시스템 생성

 

1) 루트파일시스템 개요

개요

- 루트파일시스템 : "/" 디렉토리에 마운트되는 파일시스템

- 시스템  초기화 및 각종 주변장치들을 제어하기위한 파일 및 부팅에 필요한 내용들을 포함하는 파일시스템

- 루트 파일 시스템은 일반적으로 읽기 전용으로 마운트 되었다가 커널이 정상적으로 로딩 되면 RW모드로 변경

 

루트파일시스템의 구성

- 루트파일 시스템에 필요한 최소 디렉토리로 시스템 운영에 필요한 디렉토리로 구성

1. /dev : 디바이스 파일

2. /proc : 커널 실행정보

3. /etc : 시스템 설정파일

4. /sbin : 시스템 관리에 필요한 필수실행파일

5. /bin : 시스템 기본 실행파일

6. /lib : 런타임 공유 라이브러리

7. /mnt : 마운팅 포인트로 사용

8. /usr : 유틸리티와 응용프로그램

9. /root : 루트사용자의 홈디렉토리

10. /boot : 부트로더의 디렉토리

 

루트파일시스템 구현

- 임베디드시스템은 하드디스크가 없거나 부팅속도향상을 위해 루트파일시스템을 램디스크상에 구현

- 범용 리눅스시스템은 부팅속도 향상을 위해 부팅 초기단계에서 램디스크 사용

 

루트 파일시스템 생성 절차

1. dd 명령어로 램디스크 이미지 생성

2. 파일시스템 ext2 포멧

3. 파일 시스템 마운팅

4. 기본 디렉토리 생성 : /dev,/proc,/sbin ...

5. 필수 라이브러리 복사 : glibc 복사

6. init 및 스크립트 설치 : sysvinit 패키지

7. 디바이스 파일 설치 :mknod

8. 필요한 응용프로그램 설치 :busybox, tinylogin

9. 쉘프로그램 설치 ; bash

10. 루트파일 시스템 이미지 생성 : gzip과 mkimage 명령어 사용

 

 

300x250
728x90

리눅스  파일 시스템

- 리눅스 커널에서 사용하는 데이터, 프로그램 저장

- 커널 동작을 위한 데이터/실행파일들이 루트파일시스템에 마운트되야 사용가능

- 모든 파일들을 계층적 구조로 관리 -> 최상위에 /가 있고 아래에 트리구조로 연결됨

 

기본 파일 시스템 "ext2"

- 가상 파일 시스템을 사용해서 다른 종류의 다양한 파일 시스템 지원

- 파일 시스템 생성 및 관리 도구 사용방법 숙지 필요

- 임베디드 시스템의 경우 램이나 플래시메모리로 파일 시스템 생성 및 관리

- 파일 시스템에 대한 기본적인 정보는 범용 컴퓨터와 동일하게 적용

 

(1) 파일 시스템 개요

1) 파일 시스템

2) 리눅스 파일 시스템

3) 리눅스 파일 유형

4) 가상 파일 시스템

5) 리눅스 파일 시스템 구조

6) /proc 파일 시스템

 

1) 파일 시스템

파일 시스템

- 운영체제가 파일들을 효율적으로 디스크에 저장하고 관리하기 위한 방법과 자료구조

- 데이터나 프로그램을 저장하고 있는 파일들을 저장, 탐색, 접근, 조작하기 위한 추상적 자료구조 집합체

- 디스크의 물리적인 트랙, 섹터, 실린더를 논리적 단위로 할당

 

파일 유형

- 일반 파일, 디렉토리

- 디바이스 파일 :문자디바이스, 블록디바이스

- 기타 파일 : 소켓, 파이플, 심볼릭/하드링크

- 모든 자원들을 파일과 동일하게 처리

 

저장 자원

- 하드 디스크

- 플로피

- CD롬

- DVD

- Flash ROM

 

루트파일시스템

- 리눅스 디렉토리 구조의 최상위 위치인 "/"에 연결된 파일 시스템

- 리눅스 리눅스 실행시 필요한 데이터와 프로그램 저장

 

루트 파일 시스템 최소 구성

-최소 디렉토리 : /dev, /proc, /bin, /etc, /lib, /lusr, /tmp

-기본 유틸리티 프로그램 : sh, ls, cp, mv, etc

- 최소 설정 파일 : rc, initab, fstab, etc.

- 기본 디바이스 : /dev/hd*, /dev/tty*, /dev/fd0, etc.

- 유틸리티 위한 런타임 라이브러리 준비되야함

 

마운트

- 마운팅 : 새 파일시스템을 루트파일시스템에 연결

- 마운팅포인트 : 새파일시스템이나 파일이 연결되는 위치

 

inode

- 파일에 대한 정보를 보관하는 커널 데이터 구조체

- 구성 정보 : 파일 유형, 접근권한, 소유권, 시간기록, 크기, 링크카운터, 데이터블록에대한 포인터

- include/linux/fs,h에서 정의

 

접근 권한

- 파일에대한 읽기 쓰기 실행에 대한 접근 허가권

- setuid, setgid, chmod, umask 로 설정

 

2) 리눅스 파일시스템

리눅스 파일시스템

- 가상 파일시스템 (VFS)를 사용하여 다양한 파일시스템 지원 및 통일된 접근 방법 제공

- 대표적인 파일시스템

  ext2 : 기본파일 시스템

  ext3 : ext2에 저널링 기능 추가

  NTFS : 윈도우 파일시스템

 

리눅스 기본 파일시스템

- 초기 파일시스템 : Minix 파일시스템

- ext(extended file system) : 1992. 리눅스 버전 0.96c서 사용

- ext2 : 1993.1 개선된 ext파일 시스템 릴리즈

  -> 최대 2gb 파일크기와 4TB 전체파일시스템 구성 가능

  -> 가변 블록 크기 변경 및 파일시스템 확장 가능

 

3) 리눅스 파일 유형

일반 파일

- 데이터나 프로그램을 저장한 일반 파일은 커널 내에서 inode라는 데이터 구조체로 표현

-포인터로 직접 연결

- 포인터로 간접 연결

- 이중 연결

-> 많은 블록을 필요한 대용량 파일도 사용가능

 

디렉토리

- 계층적 파일시스템 구성

- 파일과 하위디렉토리에 대한 정보 저장

- indoe 번호와 파일이름을 테이블 형태로 저장하는 파일

 

디바이스 파일

-모든 디바이스는 디바이스 파일을 통해 접근

- 디스크 공간을 쓰지 않고, 디바이스 드라이버에 대한 접근 포인터 가능

- 입출력 장치 유형에 따른 디바이스 파일 사용

   문자 디바이스 파일 : 문자 모드 입출력 동작

   블록 디바이스 파일 : 버퍼캐쉬를 통한 블록 단위 입출력 동작

- 디바이스 파일에 대한 입출력요청은 디바이스드라이버에 전달

- 디바이스 식별은 주번호와 부번호를 사용

 

링크

- 하나의 파일에 여러개 indode 지정

- 동일한 파일에 서로 다른 파일명 지정 가능

- 하드링크 : inode 에 대한 포인터 사용. 동일 파일시스템 내에서 사용가능

- 심볼릭 링크 : inode에 대한 포인터를 사용안함. 해당 파일의 파일이름을 저장하고있는 파일

- 하드링크는 동일 시스템내에서만 링크가능, 심볼릭링크는 다른 파일시스템도 링크가능

 

4) 가상 파일시스템

- VFS

- 파일시스템과  커널 사이 가상의 파일시스템 층 생성

- 파일시스템에 통일된 인터페이스 제공

 

가상 파일 시스템 구조

- 다양한 파일 시스템 접근 가능하게 함

1. 사용자 프로세스는 시스템 콜로 파일 시스템 접근 요청

2. 가상 파일 시스템을 통해 실제 파일시스템에 접근

3. 어떤 파일시스템을 사용하더라도, 동일한 접근방식 사용 -> 안정성, 이식성 증가

 

VFS가 지원하는 파일시스템

1. 디스크 기반 파일 시스템 

  - 로컬 디스크 파티션의 저장공간  관리

  - ext2, NTFS, MS-DOS, CD-ROM

2. 네트워크 기반 파일 시스템

  - 네트워크상 다른 컴퓨터의 파일시스템에 접근가능

  - NFS, SMB

3. 특수 파일시스템(가상 파일시스템)

  - 디스크 공간을 사양하지 않음

  - /proc : 사용자가 커널 데이터 구조에 접근할수 있는 인터페이스 제공

  - /dev/pts : UNIX98 표준 가상 단말 제공

 

5) 리눅스 파일 시스템 구조

파일 시스템 개요

- / : 최상위 디렉토리

- bin : 중요한 명령어들 포함

- boot : 커널 시스템 부팅관련 파일 저장

- dev : 시스템 디바이스 파일 저장

- etc : 시스템 전체 환경 설정 파일 저장

- home : 사용자 홈 디렉토리

- initrd : 부팅과정에서 사용되는 초기 램디스크

- lib : 프로그램에 필요한 라이브러리 저장

- lostfound : 파일시스템 검사 명령어 fsck 가 사용하는디레게토리

- misc : 시스템 아키텍처에 독립적인 자료 저장

- mnt : 마운트 포인트 사용되는 디렉토리

- opt : add-on 패키지가 설치되는 패키지

- proc : 실행중인 프로세스나 현재 시스템 정보를 파일형태로 보여주는 가상파일시스템

- root : root사용자 홈디렉토리

- sbin : 시스템 관리자용 명령어들이 저장된 디렉토리

- tmp : 임시저장디랙토리

- usr: 각종어플리케이션

    lib : /lib 에 있지않은라이브러리 디렉토리

    include : C프로그램에 필요한 헤대 퍼일

    local : 웹 서버등 추가 소프트웨어 설치

    sbin : /bin에서 제외된 명령어와 네트워크 관련 명령어

    src : 프로그램 소스 저장

- var : 시스템 운용중 생성되었다가 삭제되는 임시보관장서

  6. /proc 파일 시스템

- 커널 내부데이터 구조에 대한 인터페이스 제공

- 커널 상태나 실행중인 프로세스에 대한 정보 제공

- 커널, 프로세서, 주변장치들의 운용상태 및 동작상태 정보 제공

- /proc/pid : 실행중인 프로세서에 대한 정보. 프로세서 번호별로 디렉토리 생성

- /proc/loadavg : 1,5,15분 단위 평균시스템 부하

- /proc/uptime : 시스템 시작후 지난 시간 초단위 표시

- /proc/meminfo : 메인메모리와 스환 전체 크기, 사용량, 여유공간을 바이트단위로 표시

- /proc/ksmg : 커널 메시지

- /proc/cpuinfo : 프로세서 파라미터

- /proc/pci : pci 슬롯 점유상호아

- /proc/scsi : scsi 디바이스 정보

- /proc/net : 리눅스 네트워크 레이어 관련 정보 

     unix : 사용중인 unix domain 소켓 정보 저장

     arp : arp 테이블

     route : 라우팅 테이블

     tcp : TCP 소켓 정보

...

 

(2) ext2 파일 시스템

1) ext2 사양 비교

2) ext2 구조

3) ext3 및 ext4

 

1) ext2 사양 비교

ext2 사양비교

- 1993.1 기존 ext 파일시스템 개선한 파일시스템

- 데이터 블록 크기 : 1~8KB

- 디렉토리 당 최대 하위디렉토리 수 : 32,768

- 최대 파일 시스템 크기 : 2T ~ 32TB

- 최대 파일 사이즈 : 16G ~2TB

- ext2 파일시스템은 ext3,4 로 확장되어 리눅스에 사용

 

ext2 파일 시스템 구조

- /usr/include/linux/ext2_fs.h에 정의

- 맨 앞에 boot sector

- 뒤로 block group이 따라감

- block group은 boot sector, block group, data bitmap, inode bitmap, inode table, data block로 구성

 

슈퍼 블록

- 파일 시스템에 대한 메타 데이터 저장한 구조체

- 하드디스크 시작위치에서 1024 바이트 오프셋 위치에 저장된 메모리공간

- 파일 시스템 마운팅에 필수 정보

- 구성 : inode 수, 사용중인 블록, 블록 크기, 프래그먼트 수, 파일시스템 마운팅 시간, 마지막 쓰기 시간 등

 

inode

- 128 바이트로 구성

- 파일 타입, 접근권한, 생성시간, 접근시간, 소유자 아이디, 데이터 블록의 수와 데이터 포인터, 간접블록용 포인터

 

ext2 라이브러리

- libext2fs

- ext2 파일시스템 제어구조 처리할수있는 함수

- 파일 시스템 관련 함수

- 디렉토리 관련함수

- inode 관련함수 제공

 

유틸리티 프로그램

- e2fsprogs

- ext2 파일시스템을 생성 수정 변경 디버깅 할수있는 유틸리티 포함하는 패키지

- mke2fs : 파일시스템 초기화하여 ext2 파일시스템 생성

- tune2fs : 파일시스템 파라미터 수정

- e2fsck : 비정상 종료후 파일시스템 일관성 검사

 

3) ext3, ext4

 

ext3

- ext2+저널링 : 파일시스템 신뢰도 향상

 

저널링 파일 시스템

- 파일시스템 변동이력을 저널에 보관하여 신뢰도 향상

- 갑자기 전원공급 중단이나 시스템 다운시 복구를 용이하게함

 

ext4

- ext3의 개선

- pre-allocation : 파일 저장에 필요한 디스크 공간 미리 확보

- delayed allocation : 데이터가 디스크에 쓰여질떄까지 디스크 할당 지연

 

300x250
728x90

커널

- 운영체제 핵심 기능

- 파일 시스템 및 입출력장치 지원

-응용 소프트웨어 실행 환경 제공위한 소프트웨어 모듈

 

하드웨어 자원이 제한적이고/ 응용분야에 특화된 소프트웨어의 경우

- 운영체제 커널 필수 기능/소프트웨어만 남기고 나머지 삭제

-> 하드웨어 자원 활용도 높이고, 시스템 성능 향상

 

임베디드 시스템에 리눅스 설치

- 사용하는 타겟보드에 맞추어 커널 수정 필요

- 리눅스 소스 수정? -> 커널에 대한 정확한 이해, 안정성 보장 힘듬

=> 커널 코드 수정 대신 구성이나 기능을 선별적으로 선택하여 재구성을 함

- make 유틸리티

- 커널 기능과 sw 모듈들의 선택적 컴파일

=> 커널 실행파일

 

(1) 커널 재구성 옵션

1) 커널 컴파일 및 재구성

2) 커널 재구성 옵션

 

1) 커널 컴파일 및 재구성

 

커널 컴파일 및 재구성

1. 커널 컴파일 : 커널 소스로부터 커널 실행파일 얻는 과정

    - generic 커널 소스에 사용하고자하는 하드웨어 플랫폼용 패치 추가

    - make 유틸리티로 컴파일

   - make 유틸리티로 커널 컴파일 과정 시 다양한 커널 옵션 제공.

      사용 목적에 따라 커널 기능 설정하여 크기나 성능 최적화하도록 구성

  - 커널 옵션 설정 후 컴파일 하여 커널 이미지를 생성하여 실행

 2. 커널 재구성

   - 메뉴로 커널 옵션 선택/해제

    -> 커널 기능 일부 활성화/비활성화

    -> generic 커널이나 기존 커널 변경

   - 커널 소스 직접 수정 -> 소스 깊은 이해 필요

   - 커널 옵션을 통해 컨러 설정

    -> 주요 설정을 옵션 매뉴형태로 제공하여 쉽게 간단히/비활성화

3. 커널옵션 설정

  - 텍스트 기반 메뉴를 사용한 설정 : make menuconfig

  - X-윈도우 기반 설정 : make xconfig

  - 커널 옵션 설정 : /usr/src/linux/.config 파일 설정

 - 변경된 커널 실행 : 부트로더에 등록. 시스템 부팅시 변경된 커널이 선택되어 실행되도록 해줌

 

2) 커널 재구성 옵션

커널 재구성 옵션

- 커널 메인 메뉴에는 설정가능옵션 나열

- 선택시 서브메뉴 표시

- 메인 메뉴 옵션리스트는 시스템에 따라 다름

 

code maturity level options

- 불완전한 커널코드나 드라이버 사용여부 -> 시스템 안정성확보를 위해 선택안하는게 좋음

 

Loadable module support

-  set version information on all module symbols : 다른 버전 커널에서 생성한 모듈을 사용할 경우

 

processor type and feature

- math emulation : 수치연산 보조프로세서가없는 경우 에뮬레이션하는 경우 선택

- MTRP(memory type range resister) support : pci나 agp 버스를 사용하는 경우 선택

- 특정 프로세서, 플랫폼에 따른 설정 파라미터들을 정의해 선택적 커널 컴파일

 

general setup

- networking support : 네트워크 지원 여부 -> 대부분 임베디드시스템에서 쓰므로 선택이 좋음

- pci/eisa/mca support : pci/eisa/mca 버스지원여부 선택

- system v ipc : system v ipc 사용여부 설정

- pcmcia/cardbus support : pcmcia 카드 사용여부

- support hot-pluggable device : hot plug 디바이스 사용 여부

- bsd processing account : 프로세스 종료시 프로세서 관련 정보를 파일로 저장

- sysctl support : 커널 실행 중에 커널 파라미터나 변수값 설정

- kernel core format  : 커널 코어 포맷 설정

- kernel support for elf binaries : elf 지원 여부

- power management support : 자원 관리 모드 지원 여부

 

Memory Technology Device(MTD)

- MTD support : 플래시 메모리 사용여부 - 대부분 임베디드 시스템에서 플래시 메모리 쓰므로 반드시해야함

- Parallel port support : 프린터 및 병렬포트 사용하는 디바이스 지원

 

Plug and Play configuration

- plug and play support : PnP 기능을 가진 디바이스 지원

 

Block devices

- Loopback device support : 루프백 디바이스 사용 여부 -> 램디스크 사용하는 경우 루프백 디바이스 기능 사용

- RAM disk supoort : 램디스크

- Default RAM disk size : 기본 램디스크 크기지정

- Initial RAM disk supoort: 초기 램디스크

- Flash memory block support : 플래시 메모리를 램디스크로 쓸건지 설정

 

Networking options

- 대부분 임베디드 시스템에서 이더넷 지원하므로 네트워크 설정 작업은 매우 중요

- 다양한 옵션들을 시스템 동작환경에 따라 신중하게 설정해야함

- packet socket : 패킷 프로토콜 사용 여부 ->네트워크 디바이스에 직접 접근할경우 설정

- neetwork packing filtering : 네트워크 패킷에 대한 필터링 기능 지원 여부 ->라우터 게이트웨이,방화벽등 사용시 필요

- socket filtering : 소켓에 대한 필터링 여부

- undix domain sokets : 유닉스 도메인 소켓 지원 여부

- TCP/IP networking : TCP/IP 지원 여부

 

Network device support

- Network device support : 네트워크 카드 사용, SLIP, CSLIP 등 프로토콜 지원

- Ethernet : Ethernet network interface card(NIC) 사용 여부

- 네트워크 인터페이스 카드는 시스템에서 사용하는 네트워크 디바이스에 따라 선택적으로 선택

-> 커널 재구성전 네트워크 인터페이스에 대한 정보 파악

 

IrDA(infrared) support

- IrDa subsystem supoort : 적외선 통신 지원

 

Input core support

- input core support : 키보드 마우스 조이스틱 사용여부

 

character devices

- virtual terminal : 가상 단말 지원 여부

- support for console on virtual terminal : 가상터미널을 콘솔로 사용

- support for console on serial port : 표준 시리얼 포트를 콘솔로 사용

- unix98 pty support : pty 단말기 지원 여부

- watchdog cards : 하드웨어 및 소프트웨어 와치독 지원

 

USB support

- support for usb : usb 지원

- usb device file system : usb 파일 시스템 지원

 

console drivers

- vga text console : 일반 vga 표준 모드 콘솔 지원

- video mode selection support : 커널 시작시 비디오 모드 설정

- frame buffer support : 콘솔에서 그래픽 기능 지원하도록 설정

 

file systems

- quota support : 사용자별로 디스크 사용량 제한

- kernel automounter support : 원격 파일 시스템 자동 마운트

- /proc file system support : 시스템 상태 정보를 제공하는 가상 파일 시스템인 /proc 파일시스템 사용 여부

- /dev/pts file system for unix98 pys : /dev/pts 파일시스템 지원 여부. 텔넷 사용할 경우 선택

- second extended fs support :ex2 파일시스템 지원 여부. 리눅스 기본 파일시스템이므로 반드시 설정

- network file system : nfs 기능 쓰려면 설정

 

kernel hacking

- verbos kernel error message : 시스템 내부 에러 출력 여부

- verbos user fault message : 사용자 프로그램 에러 메시지 제공여부

 

 

(2) 커널 이미지 생성 절차

1) 임베디드 커널 이미지 생성 절차

2) make 유틸리티 작업 흐름

 

1) 임베디드 커널 이미지 생성 절차

임베디드 커널 이미지 생성 절차

- 임베디드용 커널 이미지 생성 절차는 일반 pc에서 리눅스 커널 컴파일 절차와 크게 다르지 않음

-> 커널 소스에 사용하는 프로세서와 타겟보드에 관련된 소스패치 작업이 필요

-> 재구성 과정에서 타겟보드에 관련된 커널 구성옵션 사용함

-> 생성된 이미지를 타겟 보드에 퓨징해서 사용함

 

임베디드 커널 이미지 생성 절차

1. 커널 소스를 다운받아 작업 디렉토리 /usr/src/linux에복사

2. 크로스 컴파일러를 포함한 툴체인 설치 확인 /usr/local/arm/bin

3. 타겟보드 환경에 적합하도록 커널 패치

4. 작업 디렉토리에서 이전 커널작업환경 삭제

5. 커널옵션사용한 커널 재구성

6. 커널 재구성과정을 통해 매뉴를 소스에 적용

7. 메이크파일간 상호의존성 검사

8. 불필요한 목적파일 삭제

9. 커널을 컴파일 및 이미지 생성

10. 커널 이미지를 FTP 명령어와 플래시메모리 퓨징명령어로 타겟보드에 퓨징

11. 타겟 보드 리부팅 후 새로운 커널 실행 확인

 

2) make 유틸리티 작업 흐름

1. check target-board environments

2. make menuconfig

3. make depend

4. make clean

5. make zImage

6. zImage를 타겟 보드에 퓨징 ->ftp zImage kernel, falsh kernel

 

300x250
728x90

리눅스 설치를 위한 리눅스 커널의 기본구조와 특징

- 리눅스 커널 재구성시 필요

- 운영체제에 대한 기본적인 이해 -> 커널 소스 구조 및 커널 내부를 구성하는 구성요소에 대한 이해

- 리눅스 소스 설치 -> 커널 컴파일 -> 부트로더 설정

- 리눅스 커널 수정은 커널에 대한 이해 필요 -> 컴파일은 매우 복잡

* 수정 후 컴파일 보단 설정 변경으로 절차 최소화 하는것이 편리

 

(1) 리눅스 커널 구조

1) 커널 개요

2) 커널 구조

3) 마이크로 커널

4) 모노리식 커널

5) 리눅스 커널 소스

6) 리눅스 커널 내부구조

 

1) 커널 개요

운영체제

- 하드웨어 자원 관리, 응용 프로그램 실행시키는 통합적 환경 제공

- 구성요소 : 커널, 디바이스 드라이버, 명령어 쉘, 사용자 인터페이스, 파일시스템, 시스템유틸리티

- 응용프로그램 인터페이스 -> 시스템 콜

- 하드웨어 인터페이스 -> 디바이스 드라이버

 

커널 kernel

- 운영체제의 가장 핵심적인부분

- 하드웨어 자원관리

- 시스템 원할히 동작하도록 제어

- 사용자가 입력한 명령어 수행

 

커널 구성요소

- 스케줄러 : 프로세서 실행 제어

- 인터럽트 핸들러

- 메모리 메니저

- 시스템 서비스 모듈 : 네트워크, 프로세스간 통신

 

2) 커널 구조

- 사용자 레벨- 응용프로그램

- 커널 레벨 - 시스템콜 인터페이스 / 커널 코어/ 디바이스 드라이버

- HW 레벨-하드웨어

 

자원 관리자로서의 커널

- 하드웨어 요소들과 주변장치 등 물리적 자원 관리

- 물리적 자원을 추상화 시켜 추상적인 자원으로 관리

- 자원의 추상화 : 물리적 자원에 적용되는 연산들을 단순화 시켜 물리적 장치를 다루는 세부적인 사항을 다룸

- 물리적 자원 기반 추상화 : 태스크 스레드, 세그먼트와 페이지, 파일, 디스크 드라이버, 터미널 드라이버

- 물리적 자원과 무관한 추상화 : 세마포어, 메시지

 

커널 동작 레벨

1. 사용자 레벨 : 응용프로그램 레벨. 사용자 프로그램과 응용프로그램이 위치하는 사용자공간사용.

                  일반적인 명령어 +프로그램 실행파일(프로세스

2. 커널 레벨 - 하드웨어 자원 관리. 사용자 레벨 프로세스의 요청 받아 서비스 제공

                - 커널은 하드웨어 인터페이스와 인터럽트 등을 통해 하드웨어와 통신

                - 사용자 프로세스와는 시스템 콜로 통신

3. 하드웨어 레벨 - CPU, 메모리, 하드디스크 같은 물리적인 자원들로 구성

 

커널의 종류

1. 모노리식 커널

2. 마이크로 커널

 

3) 마이크로 커널

마이크로 커널

- 커널의 기능을 최소화 하여 가장 핵심적인 부분만 커널에 포함시킨 구조

- 이외 기능들은 서브 모듈(서비스 서버)로 나누어 각각 프로세스로 구현되어 동작

- 상호간의 메시지 전송 기능을 통해 서비스의 요청과 응답을 수행

마이크로 커널 구조

마이크로 커널의 장단점

- 장점 : 기능 확장과 수정 용이, 다른 시스템으로 이식 쉬움

- 단점 : 프로세스간 통신에 있어 메시지 전달에 따른 오버헤드발생, 문맥 교환으로 인한 자원 이용 효율성 저하

 

대표적인 마이크로 커널

- Mach : 1980년 카네기 멜론대에서 개발

- EROS, Spring OS, VSTa, Symbian OS 등 ..

 

4) 모노리식 커널

- 시스템 관리에 필요한 모든 커널기능들이 통합되어 동작

모노리식 커널 구조

모노리식 커널 장단점

- 장점 : 마이크로 커널에 비해 구현쉽고 빠름. 효율적자원관리

- 단점 : 커널이 커짐, 커널 변경시 커널 전체를 재컴파일 해야함. 다양한 시스템에 포팅이 힘듬

 

대표적인 모노리식 커널

- 리눅스 커널

- UNIX 계열

- 윈도우

 

5) 리눅스 커널 소스

커널 소스 구조

- 압축된 리눅스 커널 소스 다운로드 및 설치시 아래와 같은 디렉토리 구조

- arch : 플랫폼 아키텍처 관련 코드

리눅스 커널 소스구조

arch 디렉토리

- 모든 아키텍처 및 CPU에 종속적인 커널 코드 포함

- 각 아키텍처별 부트 관련 코드 존재

- 지원하는 아키텍처별 하위 디렉토리가 구성 ex)i386, alpha, arm

 

include 디렉토리

- 커널 코드를 생성에 필요한 모든 헤더파일들

- 지원하는 아키텍처별로 서브디렉토리 존재 ex) 인텔 i386 계열 : include/asm-i386

 

init 디렉토리

- 커널 초기화 코드, 메인함수

 

ipc 디렉토리

- 프로세스간 통신 코드 기능을 위한 코드

- 파이프, 시그널, 소켓, 메시지 패싱 등

 

mm 디렉토리

- 모든 메모리 관리 코드

- 아키텍처에 종속적인 메모리 관리 코드 : arm/해당아키텍처/mm  ex) arch/i386/mm

 

drivers 디렉토리

- 블록 디바이스 드라이버, 문자 디바이스드라이버, 네트워크 디바이스 드라이버. 디바이스 드라이버들이 세분화

 

fs 디렉토리

- 파일 시스템 코드가 파일 시스템 별로 디렉토리 세분화 되어 존재

 

kernel 디렉토리

- 메인 커널 코드 : 프로세스, 인터럽트, 타이머, 시그널, 프로그램의 실행 등

-  arch/아키텍처이름/kernel 디렉토리에 저장 ex) arch/i386/kernel

 

net 디렉토리

- 커널의 네트워크 관련 디렉토리

 

lib 디렉토리

- 커널에서 사용하는 라이브러리 코드 ex)arch/i386/lib

 

scripts 디렉토리

- 커널 설정에 필요한 스크립트들이 존재

 

6) 리눅스 커널 내부구조

리눅스 커널 내부구조

- 크게 사용자/커널/디바이스 공간으로 나뉨

- 시스템 콜 : 사용자와 커널 사이 인터페이스

- 디바이스 인터페이스 (디바이스 드라이버) : 커널과 디바이스 사이 인터페이스

리눅스 커널 내부 구조

 

 

프로세스 매니저

- 프로세스의 생성 및 소멸

- 프로세스간 통실

- CPU 스케쥴링

- 시그널 처리

- 프로세스간 동기화

- 다중 프로세서의 효율적인 관리 기능

 

메모리 매니저

- 프로세스에 메모리 할당

- 페이징 기법을 이용한 가상 메모리 관리

- 가상 주소를 실제적인 물리 메모리 주소로 변환

- 페이지 폴트와 같은 예외 상황 처리

 

파일 매니저

- 파일의 생성과 파일 디렉토리 관리

- 파일에 대한 사용자들의 접근 제어

- 가상 파일 시스템을 사용한 다양한 파일시스템 지원

- 디스크 물리구조에 따른 논리적 기법 표현

- 블록디바이스의 입출력을 위한 버퍼캐시관리

 

네트워크 매니저

-통신 자원 관리

- 소켓인터페이스, 통신프로토콜 등 서비스 제공

<- 통신 프로토콜 구현, 네트워크 라우팅 및 주소지정, 네트워크 제어기 관리, 네트워크 드라이버와 접속작업

 

디바이스 매니저

- 시스템에 연결된 여러 주변장치들의 디바이스 드라이버들을 구성하여 관리

- 입출력 요청의 검증

- 입출력 작업 스캐줄링

- 주변장치간의 자료 전송

- 제어기 관리

- 인터럽트 요청 및 처리

 

 

(2) 리눅스 커널 컴파일

1) 커널 다운로드

- 커널 컴파일 과정은 2.4 버전 사용

- www.kernel.org /usr/src 디렉토리에 다운

 

2) 압축 풀기

-  tar xvfz linux-2.4.32.tar.gz

 

3) 설정 초기화

- make mrproper : 기존 설정 있는 커널 설정을 초기화 -> 기존 .config 파일 삭제

 

4) 커널 옵션 설정

- make menuconfig : 커널 옵션 설정하는 부분 -> 커널 설정 정보가 .config에 저장

- make oldconfig : 기존 설정값들로 재설정

- make config : 콘솔 환경에서 설정

- make xconfig : x윈도우 환경에서 설정

 

5) 파일 종속성 검사

- make dep : 커널 설정을 바탕으로 각 파일들의 종속성을 검사

 

6) 오브젝트 파일 제거

- make clean : 기존 컴파일시 생성되었던 object 파일 제거

 

7) 커널 이미지 만들기

- make bzImage : 커널 이미지를 만들기 위한 컴파일 과정

- 커널 이미지 : arch/i386/boot 디렉토리에 생성

- vmIinux : 압축되지 않은 커널 이미지

- zImage : 압축 커널, 1MB 이하

- bzImage : 압축 커널 = vmInux + 초기화 코드 (bootsect.S, setup) + bzImage

 

8) 이미지 복사

- cp arch/i386/boot/bzImage /boot/bzImage-2.4.32

 

9) 모듈 컴파일

- make module : 모듈 컴파일

- 옵션으로 설정한 모듈들을 컴파일

- 처음 컴파일 하는 경우에만 쓰면됨

 

10) 모듈 복사 및 확인

- make modules_install : 컴파일 모듈들을 적절한 디렉토리에 복사

- ls /lib/modules/2.4.32

 

11)  환경 설정 파일 수정

- vi /etc/grub.config 하여 수정(부트로더가 LILO or GRUB)

- default : 부팅 순서. 0이번 1번째, 1이면 두번째 커널 선택해 부팅

- timeout : 대기 시간

- splashimage : GRUB 사용시 표시되는 배경화면

- title : 리눅스 커널의 이름

- root : 루트 파티션 위치

   ex) root(hd0,4) /boot 가 hda5에 위치

- kernel : 부팅시 로딩할 커널파일 위치와 이름 설정

- reboot : 시스템 재시작

 

300x250
728x90

ARM 프로세서, 리눅스 기반 임베디드 시스템에서 사용되는 부트로더

 -> 동일 시스템 개발 시 참고 가능

 -> 처음부터 개발은 힘드므로 이미 개발된 부트로더나 오픈소스 부트로더를 수정

 

(1) 부트로더 구현 사례

1) SM_BOOT

2) SM_BOOT 명령어

3) SM_BOOT 동작 흐름도

 

1) SM_BOOT

SM_BOOT의 의미와 실행화면

- ARM 기반 플랫폼 전용 임베디드 시스템 부트로더

 

SM_BOOT 메모리맵

- 플래시 메모리에 부트로더, 커널이미지, 환경변수 등 존재

- 환경변수 : 시스템 환경변수 설정

- 사용자 : 플래시 메모리 전용 파일시스템 만들어 하드디스크 처럼 사용

 * 램은 전원중단시 사라지므로 보존 필요한 데이터는 따로저장해야함

2) SM_BOOT 명령어

SM_BOOT 명령어

- 임베디드 부트로더의 한사례로 부트로더 구현방법/제공 명령어 검토

-> 새로운 부트로더 설계에 큰 도움

- 부트로더 기능 수행 : boot(램에 로딩된 커널 부팅, 수동 운영체제부팅), reset(부트로더 재실행)

- 시스템 개발 : bootp(bootp 프로토콜로 ip 어드레스 할당-데이터 송수신 필요시 해야함), setpi(ip어드레스 수동 설정),

          macwrite(이더넷 인터페이스 카드의 맥어드레스 설정), tftp(tftp 데이터전송), download(시리얼 전송),

          flash(플래시 메모리에 데이터 저장), 

- 간단한 디버그 : read(특정 메모리주소 값 읽기), write(특정 주소에 값 쓰기), status(메모리,레지스터,이더넷 상태표시)

 

부트로더 공간 크기

- bootroader는 0x00000000에서 시작하며 길이는 0x0000C0000

- 길이가 2^16이므로

- 부트로더에 설정된 공간 크기는 2^6 * 2^10 = 64 * 1024 -> 64KB

SM_BOOT status 명령 예시

 

3) SM_BOOT 실행 흐름도

SM_BOOT 실행 흐름도

1. Power On

2. Start.S

 - 벡터 테이블 설정

 - 레지스터 설정(클럭, 메모리, GPIO 등)

 - 부트로더를 RAM으로 복사

 - 스택 포인터 설정

 - 램 상의 부트로더로 제어권 이동

3. main.c

 - 시리얼 초기화

 - 이더넷 초기화

 - 램으로 이미지 복사(커널, 램디스크)

 - 부트모드 결정

 - 명령어 입력/리눅스 커널 부팅

 

 

(2) 부트로더 동작 흐름

1) ARM 기반 부트로더 동작 흐름

2) 링커 스크립터

 

1) ARM 기반 부트로더 동작 흐름

ARM 기반 부트로더 동작 흐름

1. 인터럽트 벡터 테이블 설정 

  - 시스템 전원 인가시 마이크로 프로세서는 무조건 0x0000 0000 번지의 데이터를 읽음

 - 하드웨어적으로 이벤트 발생시 특정 번지로 이동해 그 위치의 명령어를 읽음

 - 예외 : 하드웨어/소프트웨어적으로 발생하는 이벤트

 - 예외처리기 : 예외상황이 발생시 실행하는 작업

 - 인터럽트 벡터 테이블 : 예외처리기 위치 정보를 가진 테이블

 - 이테이블은 메모리 가장 낮은 위치에 저장되어 부트로더 소스중 가장 먼저 실행되는 코드

2. 인터럽트 마스킹

 - 부트로더 실행중 인터럽트 발생 방지

 - 마스킹 발생 방지 방법 : 마이크로 프로세서에 따라 다름

 - ICMR 값을 클리어하면 인터럽트 발생이 방지됨

3. sleep mode 방지

 - 소비전력 절약을 위한 sleep 모드 지원

 - 부팅 과정 중 시스템이 슬립모드 진입을 막는 코드가 있음

4. cpu 클럭 설정

 - 동작 속도 설정을 위해 cpu 클럭 설정 레지스터에 원하는 cpu 클럭 속도 지정

5. gpio 설정

 - 표준 입출력 포트를 사용하기 위한 기본적인 설정

 - 표준 입출력 포트가 입력용인지 출력용인지, 라이징엣지에서 인식할지 폴링엣지에서 할것인지 정해야함

6. SDRAM 설정

 - 메인메모리로 SDRAM을 많이 사용, 프로세서에 메모리 컨트롤러 내장

 - ARM 프로세서에 SDRAM을 사용시 메모리 동작모드 및 액세스속도 등 관련도니 설정 레지스터, 어드레스 설정값

 - 부트로더에서 설정 레지스터에 적절한 설정값을 지정해야됨

7. 스택 포인터 설정

 - c 함수를 사용하기 위한 스택 포인터 설정

-------------------start.S 파일의 어셈블리 코드 실행과정

8. beforeMain 함수 호철

9. beforeMain 함수 실행

 - 어셈블리 코드가 아닌 c프로그램으로 main.c에 포함

 - cmain 부트로더 메인함수 호출전 실행

 - 플래시 메모리에 저장된 부트로더 코드를 메인 메모리에 복사한후 cmain 함수 호출

10. cmain 함수

 - 시리얼포트 전송/다운로드 속도 설정

 - 시리얼 포트/타이머/lcd/ether 초기화

 - 사용자 key 입력 대기 : 입력시 부트로더 명령어 모드 진입/ 없을시 커널 부팅

11. 부트로더 명령어 모드

 - display prompt 함수 호출 - 명령어 프롬프트 출력

12. 자동 부팅

 - 플래시 메모리에 저장된 커널.램디스크 이미지를 메인메모리에 복사 -> DoBootKernel 함수 호출

 

 

2) 링커 스크립터

링커 스크립터

- 링커명령어로 쓰여진 스크립터

- 목적파일의 섹션들을 실행파일들에 매핑시키는 방법기술

- 실행 파일의 메모리 레이아웃 제어

- 링커 명령어를 사양한 다양한 동작 구현가능

 

링커 스크립터 종류

- 기본 링커 스크립터 : 링커 실행파일 내부에 정의된 기본 스크립터. 사용자가 별도 스크립터 지정하지않을시 적용.

- 사용자 정의 스크립터 : 사용자가 정의함. -T옵션으로 적용 가능

 

부트로더 실장위치

- 부트로더가 램의 특정 위치에 로딩되도록 링커 스크립터에 정의

- 시스템 설계 단계에서 결정한 매모리맵에 원하는 프로그램을 로딩할때 사용

 

300x250
728x90

부트로더 bootloader

- 전원 공급시 가장 먼저 실행

-> 시스템 하드웨어 초기화 + 메모리에 운영체제로딩

- 하드웨어 추가로 운영체제 실행 전 초기화 작업이 필요한 경우 -> 부트로더 실행

- 부트로더 수정/코드 추가 -> 하드웨어 및 운영체제에 대한 이해가 필요

-> 부트로더에 명령어 추가시 부트로더를 다양하게 사용가능

- 초기화 코드가 어셈블리로 작성되는 경우 어셈블리 코드에 대한 이해도 필요

 

(1) 부트로더 개요

1) 부트로더

2) 부트로더 기능

3) 부트로더 소스파일 구성

4) 부트로더 생성 절차

 

1) 부트로더

부트로더(Boot Loader) 역활 및 유형

- 시스템 부팅 후 처음으로 실행되는 프로그램

- 시스템 초기화/ 운영체제 로딩

 

데스크탑 리눅스용 부트로더

-  하드디스크의 마스터부트레코드에서 동작

- 멀티부팅 : 운영체제의 선택적 부팅 기능 제공

- LILO(Linux Loader), GRUB(Grand Unified Boot loader)

 

임베디드 시스템용 부트로더

- 각 임베디드 시스템에 특화된 전용부트로더

- 플래시 메모리에 저장, 메인 메모리에서 실행

- 단일 운영체제 부팅

- 시스템 개발 관련 명령어 지원 : 호스트 컴퓨터와 타겟 보드의 데이터 전송명령어, 플래시 메모리 쓰기, 메모리 dump

- ARMBoot, BLOB(Boot Loader OBject), U-BOOT

 

2) 부트로더 기능

부트로더 주요작업

- 하드웨어 초기화 : CPU클럭설정, 메모리 파라미터설정, 시리얼 포트 설정, TCP/IP 설정

- 프로그램 복사 : 플래시메모리에 저장된 부트로더 자신, 커널이미지, 램디스크 이미지를 메모리에 옮김

-부트로더 명령어 제공 : 명령어 제공. 호스트 컴퓨터와 데이터교환, 플래시 메모리 퓨징, 간단한 디버깅 기능

- 운영체제 부팅 : 저장된 운영체제로 부팅하여 프로그램 제어권을 운영체제로 넘김 -> 응용프로그램 실행준비

               + 임베디드 시스템 개발에 필요한 작업, 환경설정 변수들을 추가/변경 -> 부트로더 기능 확장

 

3) 부트로더 소스파일 구성

소스파일

- 1개의 어셈블리 소스파일과 여러개의 C소스파일

- makefile : make에서 사용하는 컴파일 스크립트파일

- start.S : 부트로더 초기 코드로 어셈블리 코드, CPU, 메모리, gpio 초기화, 플래시 메모리를 DRAM 영역으로 복사

- main.c 부트로더 메인 소스코드

- commands.c : 명령어처리고드 포함

- lib.c 부트로더에서 사용하는 라이브러리 포함

- 타겟 보드에 실장된 디바이스에 대한처리프로그램 : flash.c, serial.c, time.c, net.c, bootp.c, tftp.c

 

헤더 파일

- 각 소스파일에서 사용하는 변수나 매크로들을 정의한 파일

- ld-xsacle : 링커 스크립트 파일(컴파일된 프로그램의 링크 방법)

- config.h : 부트로더 환경설정파일

 

부트로더 환경설정 파일

- config.h 매크로 형태로 정의된 변수

- 시리얼 포트 전성속도

- 자동부팅 지연시간

- 메모리 맵 : 부트로더, 커널, 램디스크 등 소프트웨어 컴포넌트를 플래시 메모리나 DRAM 어디에 저장할지 설정

  -> 매크로 선언 값을 수정하여 메모리 저장위치를 변경할수있음.

- 프로세서가 메모리 컨트롤러 내장한 경우

  -> 메모리 액세스 타이밍정보, 파라미터들이 메모리 제어 레지스터에 정확하게 설정되어야 함

 

4) 부트로더 생성절차

소스 컴파일

1. 부트로더 소스파일 sm_boot.tar.gz 준비

2. 압축파일 해제 tar zxvf sm_boot.tar.gz

3. 소스파일 수정 vi main.c

4. 부트로더 컴파일 make

 -> 부트로더는 타겟 임베디드 시스템에서 실행되므로 크로스 컴파일러로 부트로더 소스를 컴파일

 

부트로더 퓨징 fusing

- 부트로더 소스 수정, 컴파일해서 실행파일 만듬

- 실행파일을 타겟보드에 다운로드하여 플래시 메모리에 넣어야 함

 -> 이 작업을 플래시 프로그래밍 or 퓨징 이라 함

- 부트로더는 초기화 프로그램이므로, 보드 상태에 따라 퓨징 작업이 달라짐

 

퓨징하는 방법

1. 호스트 컴퓨터에서 전용 프로그램으로 직접 퓨징

 - 플래시 메모리에 아무런 소프트웨어도 설치안된경우

 - 타겟보드에 호스트 컴퓨터와 통신할수있는 프로그램이 없으므로, 하드웨어 적으로 플래시 메모리에 부트로더를 씀

 - 타겟보드의 JTAG 인터페이스 사용

  타겟 보드의 JTAG 인터페이스와 호스트 컴퓨터 병렬 연결 -> 전용 프로그램으로 플래시 메모리에 부트로더 실행파일을 넣음

 

2. 기존에 설치된 부트로더 사용하는 방법

 - 기존 부트로더를 새 부트로더로 교체하는 방식

 - 기존 부트로더에 호스트와 통신가능한 통신명령어와 플래시 메모리 쓰기 명령어를 포함함

 - 통신 명령어로 호스트 컴퓨터로 새 부트로더를 다운로드받고 플래시 메모리 쓰기 명령어로 대체함

 - 고속 데이터 전송을 위해 이더넷 인터페이스와 플래시 메모리의 특정 주소에 데이터를 쓰는 플래시 쓰기 명령지원

  -> 이더넷 인터페이스를 통한 부트로더 퓨징

   1. 호스트 컴퓨터에서 FTP 서버를 설치하고, FTP로 전송할 파일을 루트 디렉토리에 옮김

   2. 타겟보드 부트로더에는 FTP전송을 위해 필요한 IP를 설정한 후, FTP 명령어로 새부트로더 다운

   3. 다운로드 후 플래시 쓰기 명령어로 다운 받은 부트로더를 플래시 메모리에 써넣음

   4. 타겟 보드를 재시작하면 새 부트로더가 시작

 

(2) 부트 초기화 과정

1) 부트 초기화란

2) 부트 초기화 순서

 

1) 부트초기화란

부트 초기화

- 메모리에 커널 로등 후 하드웨어가 초기화 되어 시스템을 사용가능한 상태로 만드는 과정

- 프로세서 초기화, 메모리 점검 및 초기화, 각종 하드웨어 점검 및초기화

- 커널로딩, 커널 자료 구조 등록 및 초기화, 시스템 사용환경구성 설정

 

2) 부트 초기화 순서

- power on : 시스템 전원 인가

- rom-bios 실행 : 바이오스가 실행

- post 과정 실행 : power on self test. 진원 인가 동시에 디바이스들의 오류 여부 확인

- mbr의 부트로더 읽기 : 보조기억장치 부팅파티션에 있는 MBR을 읽어 부트로더 실행

- 부트로더 실행

   부팅 메뉴 선택(/boot/grub/grub.conf 환경설정)

   압축 kernel 이미지 로드 (/boot/bmlinuz-버전)

   시스템 제어권을 커널(kernel)에게 넘겨줌

   스와퍼(swapper)프로세서 호출

- swapper 프로세스 실행 : 커널 이미지 압축 해제. 각 장치 드라이브 초기화

            루트 파일 시스템을 ro 모드로 마운트 후 파일 시스템 검사, 루트파일시스템을 rw 모드로 마운트하여 init 호출

- init 프로세스 실행 : /etf/initab 파일 참조 -> /etc/rc.d/rc.sysinit 스크립트 실행 -> /etc/rc.d/rc.local 실행

                          -> 가상 콘솔 프로토콜 (mingetty)실행 -> login 프롬프트 출력

 

 

 

300x250

+ Recent posts