Embedded Linux와 device driver Y.H. PARK
Embedded Linux의 필요성 Issues: for the New O/S Embedded Linux New Applications (Wireless, Internet, Multimedia, …) New Hardware (new cool CPU, Devices, …) Total cost: NRE, Unit-base, Support Just –in-Time Technical Support Embedded Linux The most Stable, Secure, Cost-Effective, Full-Featured Operating System ever exist Y.H. PARK
RTOS, WinCE, Linux Y.H. PARK
Embedded system을 위한 GUI Qt/Embedded (Troll Tech) Feature-rich GUI Shared Library : 500K–4M Compatible: Qt/X,Qt/Windows X-windows System FREE ! Tiny-X Server + X-lib Qt/X, GTK+, Motif XIM, Font Server Compatible: PC Linux Y.H. PARK
Embedded system을 위한 GUI Micro-windows FREE! 500KB (per Application) On-going GPL project Win32 like, X-Lib like API FLTK Other 3rd Party GUIs Non-Window GUI Eyelet, PEG, … Y.H. PARK
커널(Kernel) 메모리에 상주하여 시스템 구동에 필요한 환경을 만들고 관리하는 소프트웨어 방식 Monolithic kernel Micro kernel 하나의 메모리 공간에 모든 것이 존재 Function call 방식으로 커널 기능에 접근 구현이 쉽고, 자원을 효율적으로 사용 Y.H. PARK
커널(kernel) Monolithic kernel Micro kernel 다른 시스템에서 이용하기가 어려움 확장 시 크기가 커지고 관리가 어려워 짐 Micro kernel 확장이 용이 다른 시스템에서 재사용이 용이 Message passing 방식으로 커널 기능에 접근 구현이 어려움, 자원 활용도가 비 효율적 Overhead가 큼 Y.H. PARK
Linux 커널의 구성 Processes Management Memory Management File system Management Networking Device Control Y.H. PARK
프로세스/메모리 관리 프로세스의 생성, 상태 변화 및 소멸 프로세스간 통신(IPC, signal, pipe..) 프로세스의 생성, 상태 변화 및 소멸 프로세스간 통신(IPC, signal, pipe..) 프로세스 스케줄링 시분할 시스템에서 여러 프로세스가 병렬로 실행되게 하려면 꼭 필요 Scheduler 와 context switch 를 이용 가상 메모리(virtual memory) 관리 기법 제공 Y.H. PARK
파일 시스템 관리 Linux에서는 모든 것은 파일 개념으로 처리 가상 파일 시스템(VFS)에 의한 여러 파일 시스템 타입 지원 디스크의 물리적 구조를 논리적 구조로 표현 파일, 디렉토리 관리 Block I/O를 위한 buffer cache 관리 Y.H. PARK
네트워크 관리 프로그램과 네트워크 인터페이스 사이에서 데이터 페킷을 전달 네트워크로부터 데이터가 전달되기를 기다리는 프로그램을 재우거나 깨워야 함 통신 프로토콜 지원 네트워크 제어기 관리 네트워크 라우팅 및 주소 지정 Y.H. PARK
디바이스 제어 물리적 디바이스를 맵핑 디바이스를 제어하는 코드 : 디바이스 드라이버 I/O 요청의 검증 주변 장치와 메모리 간의 자료 전송 제어기 관리 인터럽트 요청 및 관리 Y.H. PARK
디바이스 드라이버 커널 프로그램으로 작성 디바이스의 분류 커널 메모리를 다룸 I/O port 제어 문자 디바이스(character device) 블록 디바이스(block device) 네트워크 디바이스(network device) Y.H. PARK
문자 디바이스 하나의 파일처럼 사용 파일 접근에 필요한 open, close, read, write 등의 시스템 콜을 구현 일반적으로 순차적 접근만 허용 콘솔, 병렬 포트 등 /dev/tty1과 /dev/lp1 과 같은 파일 시스템 노드(node)라는 방법으로 접근 Y.H. PARK
블록 디바이스 디스크와 같이 파일 시스템을 가질 수 있는 것 블록 단위로만 접근 Linux에서는 한번에 여러 크기의 바이트 전송 가능 -> 문자 디바이스와는 커널과 하드웨어의 인터페이스에만 차이가 존재 -> 파일 형태로 접근 가능하고 사용자에게는 문자 디바이스와 동일한 것으로 보임 Y.H. PARK
네트워크 디바이스 모든 네트워크 트랜잭션은 하나의 인터페이스를 통해서 처리 네트워크 인터페이스는 패킷 송수신을 책임짐 각 디바이스는 스트림은 상관 않고 패킷 만을 주시 -> 스트림 기반의 디바이스가 아님 파일 시스템 상에 존재하지 않는 특별한 이름으로 접근(eth0 등) 패킷 전송에 관련된 시스템 콜을 구현 Y.H. PARK
모듈 (module) 개념 디바이스 드라이버 : 커널 프로그래밍으로 작성 기존의 Unix에서는 디바이스 드라이버 추가 시 커널을 다시 컴파일 Linux에서는 실행 중에 커널 확장 : 모듈 개념 모듈 이용 : 디바이스 드라이버, 파일 시스템, 네트워크 프로토콜 스텍 작성 가능 기능 개발 시간의 단축 Y.H. PARK
Linux 모듈 여러 함수와 자료구조로 이루어진 하나의 독립된 프로그램 설치(install)과정을 통해 커널에 링크 됨 정적 로딩(static loading) 동적 로딩(dynamic loading) 사용자 프로세스는 시스템 콜을 통해 모듈의 함수를 사용 설치된 모듈 정보 : /proc/modules Y.H. PARK
커널 모듈 프로그래밍 이벤트 처리 프로그램의 형태를 갖는다. main() 함수가 없다. 모든 모듈은 커널 전체와 링크 됨 모듈의 전역 변수 -> 전체 커널의 전역 변수 이름 공간 오염(namespace pollution)문제 전역 변수를 static로 정의 잘 정의된 전치어 사용 폴트 : 시스템에 치명적인 손상을 줄 수 있다. 호출 시 반드시 에러 코드검사 Y.H. PARK
커널 심볼 테이블 커널이 생성될 때 커널 안의 공개된 데이터(public data)들은 헤더 파일을 통해 수출(export)됨 커널 심볼 테이블 모듈에서 이용 가능 모듈 적재 시 모듈의 전역 데이터는 커널 심볼 테이블에 추가 됨 (/proc/ksyms) 모듈 위에 새로운 모듈 쌓기가 가능함 Y.H. PARK
모듈 프로그램의 기본 구조 #include <linux/kernel.h> /*커널에서 수행될 때 필요한 헤더 파일 */ #include <linux/mocule.h> /* 모듈에 필요한 헤더 파일 */ #include <linux/errno.h> /* linux 커널의 에러 코드 헤더 파일 */ Int init_module(){ /* 모듈이 설치될 때 초기화를 수행하는 코드 */ ………….. } Void cleanup_module(){ /* 모듈이 제거될 때 반한 작업을 수행하는 코드 */ ……….. Y.H. PARK
init_module() 모듈의 진입 점 모듈 함수에 대한 미래의 요청에 대비하는 작업을 함 -> 모듈이 제공하는 모든 특성을 등록 일정 시점에서 에러 발생 할당 받은 모든 것을 스스로 제거 에러 코들를 되돌려 줌 /linux/errno.h에 정의된 값에 따라 설정된 음수 값 Y.H. PARK
cleanup_module() 모듈의 두번째 진입 점 모듈 삭제 시 호출 init_module()이 등록했던 모든 것을 원래의 상태로 되돌려 놓음 개발 시간을 단축시켜 줌 Y.H. PARK
모듈 컴파일 커널에 링크되어 실행 정의해야 할 심볼 컴파일 시 –c flag 사용 : 링커를 호출 안함 컴파일 시 –Wall flag 사용 : 에러나 경고 표시 컴파일 시 –O flag 명시 : 헤더 파일의 inline 함수들 때문 정의해야 할 심볼 __KERNEL__ : 헤더 파일에게 커널 모드에서 실행된다는 것을 알려 줌 MODULE : 헤더 파일에게 이 코드가 모듈임을 알려 줌 Y.H. PARK
Makefile CC = gcc INCLUDEDIR = /usr/include CFLAG = -D__KERNEL__ -DMODULE –O –Wall –I$(INCLUDEDIR) OBJS = sample.o all : $(OBJS) clean : rm –f *.o *~ core Y.H. PARK
모듈의 적재 insmod 명령을 이용 root 권한이 필요 형식 : /sbin/insmod [option][-o module_name] object_file 실행중인 커널의 심볼 테이블로 모듈의 unresolved symbols을 링크시켜 줌 동작은 kernel/module.c에 정의된 몇 개의 시스템 콜에 의존 Y.H. PARK
모듈 적재 과정 커널 함수 sys_create_module()을 통해 모듈을 수용하기 위한 메모리 할당 커널 함수 get_kernel_syms()를 통해 모듈이 참조하는 커널 내 데이터들의 위치 파악 커널 함수 sys_init_module()을 통해 재배치된 오브젝트 코드를 커널 공간으로 복사 모듈의 초기화 함수 init_module()을 호출 Y.H. PARK
모듈 적재 확인 /proc/modules 파일에서 적재된 모듈을 확인 lsmod 명령어를 통하여 적재된 모듈 확인 Y.H. PARK
모듈 삭제 rmmod 명령을 이용 root 권한이 필요 형식 : rmmod [option] module_name 심볼 테이블 제거 모듈이 위치하고 있던 메모리 반환 과정 delete_module() 시스템 콜을 호출 사용수 카운터 확인 0 이면 모듈의 cleanup_module을 호출 Y.H. PARK
사용수 카운터(usage count) 시스템이 각 모듈을 사용하고 있는 프로세스의 수를 유지 <linux/module.h>에 정의된 3개의 매크로로 관리 MOD_INC_USE_COUNT MOD_DEC_USE_COUNT MOD_IN_USE /proc/modules 파일 참조 Y.H. PARK
디바이스 드라이버 컴퓨터에 장착된 여러 종류의 장치들을 하나의 공통된 인터페이스(파일 연산의 형태)로 접근할 수 있도록 만들어 주는 추상 데이터 형식 알아야 할 매개 변수 H/W의 실제 입출력 주소나 메모리 영역 드라이버의 작동 방식에 영향을 미치는 매개 변수 제품의 이름이나 릴리즈 번호 등 Y.H. PARK
문자 디바이스 드라이버 Major number 0-255 사이의 숫자를 사용 0-100 까지 : 표준 장치들에 할당 새로운 디바이스 드라이버 0-100까지는 제외 /proc/devices 파일을 참조 <linux/fs.h>에 정의된 두 함수를 이용 모듈 초기화 시 int register_chrdev(unsigned int major, const char *name, struct file_operations *fops);에서 할당 모듈 삭제 시 int unregister_chrdev(unsigned int major, const char *name); 에서 반환 Y.H. PARK
문자 디바이스 드라이버 Minor number 16 bit의 숫자를 사용 동일한 디바이스 드라이버를 사용하는 서로 다른 장치들을 구분할 때 사용 보통 상위 8 bit는 디바이스 타입을 결정 하위 8 bit는 같은 타입의 서로 다른 디바이스를 지칭 Y.H. PARK
문자 디바이스 드라이버 파일 연산 Linux에서 각각의 디바이스는 파일 형태로 존재 커널은 파일 연산을 이용 I/O 연산을 수행 <linux/fs.h>에 정의되어 있는 file_operations 구조체를 이용 struct file_operations sample_fops = { read : sample_read, write : sample_write, open : sample_open, release : sample_release, }; Y.H. PARK
문자 디바이스 드라이버 open 연산 디바이스에 관련된 에러 체크 처음으로 열렸으면 디바이스를 초기화 minor number를 확인, 필요 시 filep 포인터 갱신 filep->private_data에 넣을 데이터가 있으면 이것을 할당하고 채움 사용수 카운터를 증가 Y.H. PARK
문자 디바이스 드라이버 release 연산 filep->private_data에서 할당된 모든 데이터 해제 사용수 카운터를 감소 마지막 close 시점에 디바이스를 정지시킴 Y.H. PARK
문자 디바이스 드라이버 read/write 연산 <asm/uaccess.h>에 정의된 함수를 이용 unsigned long copy_from_user(void *to, const void *from, unsigned long len); unsigned long copy_to_user(void *to, const void *from, unsigned long len); void get_user(dataum, ptr); void put_user(dataum, ptr); 블러킹 I/O 고려 Y.H. PARK
사용자와 드라이버의 연결 major number와 minor number가 일치하고 드라이버 이름과 일치하는 디바이스 파일을 mknod 명령어를 이용하여 생성 root 권한이 필요 형식 : mknod /dev/드라이버_이름 c Mn mn c : 문자 디바이스를 의미 Mn : major number mn : minor number Y.H. PARK
H/W control device driver 인터럽트 방식과 폴링 방식이 존재 폴링 사용자 프로세스가 디바이스에게 I/O를 요청 CPU가 주기적으로 디바이스의 상태를 점검 작업 완료를 CPU가 확인 인터럽트 작업 완료를 디바이스가 CPU에게 알림 사용자 프로세스가 재 실행 Y.H. PARK
인터럽트 처리 프로세스가 I/O 요청 디바이스가 I/O 작업 동안 프로세스는 TASK_INTERRUPTIBLE 상태로 대기 디바이스가 IRQ를 통해 CPU에게 인터럽트를 검 ISR 실행 프로세스를 TASK_RUNING 상태로 만듬 scheduler를 호출 Y.H. PARK
인터럽트 처리 드라이버는 필요 시 커널에게 IRQ를 요구 사용 후 반납 /proc/interrupts 파일에서 IRQ값과 연결된 디바이스 종류를 확인 사용되는 함수 Int request_irq(unsigned int irq, void (*handler) (int, void *, struct pt_regs *), unsinged long flags, const char *device, void *dev_id); Void free_irq(unsigned int irq, void *dev_id); 처리 함수의 등록은 드라이버의 open() 안에서 처리 함수의 제거는 release() 안에서 Y.H. PARK
블러킹 I/O 대기 큐 프로세스를 sleep 상태로 만드는 함수 프로세스를 깨우는 함수 struct wait_queue * 변수를 선언 프로세스를 sleep 상태로 만들 수 있는 각 사건마다 위의 포인터 변수가 필요 위 포인터 변수를 여러 sleep_on과 wake_up 함수의 인자로 전달 프로세스를 sleep 상태로 만드는 함수 void interruptible_sleep_on(struct wait_queue **q); viod sleep_on(struct wait_queue **q); 프로세스를 깨우는 함수 void wake_up_interruptible(struct wait_queue **q); void wake_up(struct wait_queue **q); Y.H. PARK
RTOS RT System RTOS의 고려 사항 Scheduling algorithm 일의 성공 여부가 시간과도 관계가 있는 시스템 RTOS의 고려 사항 모든 커널 서비스가 결정적(deterministic)이어야 함 각 프로세스의 데드라인을 고려할 수 있는 스케쥴링 알고리즘이 필요 Scheduling algorithm Rate monotonic Earliest Deadline First(EDF) Maximum Urgency First(MUF) Minimum Laxity First(MLF) Y.H. PARK
RTOS의 예 pSOSystem Chorus Virtuoso Chimera Nucleus HLinda vxWorks RT Mach QNX Y.H. PARK