레이블이 Linux Device Driver인 게시물을 표시합니다. 모든 게시물 표시
레이블이 Linux Device Driver인 게시물을 표시합니다. 모든 게시물 표시

2010년 4월 14일 수요일

linux 2.6 device model

* 5 component for device model

  • the device model core -> defines a set of structures and functions
    • 'include/linux/device.h', 'drivers/base/*.c'
  • the generic bus drivers
    • bus / struct bus_type / bus_register(), bus_unregister()
  • the bus  controller drivers
    • device / struct device / device_register(), device_unregister()
  • the device drivers
    • driver / sturce device_driver / driver_register(), driver_unregister()
  • the class drivers
    • class / struct class / class_register(), class_unregister()

 

* Device Model Core

  • 'struct bus_type' : Represents busses(PCI, USB, I2C, etc.)
  • 'struct device' : Represents devices(Intel AC97 audio controller, Intel PRO/100 ethernet controller, a PS/2 mouse, etc.)
  • 'struct device_driver' : Represents kernel drivers that handle devices
  • 'struct class ' : Represents a class of devices(sound, input, graphics, etc.)
  • 'include/linux/device.h', 'drivers/base/*.c'

 

* device_register() : 한 device에 대해 맞는 driver들을 검색

* driver_register() : 한 driver에 대해 맞는 device들을 검색

 

* Generic Bus Drivers

  • kernel이 지원하는 모든 bus마다 generic bus driver가 있다. Generic bus driver는 sturct bus_type을 allocate하고 bus_register()를 써서 kernel의 bus type list에 register한다.
  • bus_type structure
    • name (string)
    • !klist_devices (klist)
    • !klist_driver (klist)
    • match (fp)
    • suspend (fp)
    • resume (fp)
  • klist_devices는 이 bus에 존재하는 device들의 list, Bus controller driver가 device_register()를 호출함에 의해 update 됨.
  • Bus controller driver는 system initialization 시 bus를 scan해서 어떤 device들이 있는지 check한 뒤 각 device마다 device_register()를 호출해서 klist_devices를 scan해서 맞는 driver (match() 이용)를 찾는다. 그런 뒤 device를 klist_devices에 update한다.
  • Bus controller driver는 또한 gadget이 hot plugged 되었을 때(어떤 device인지 확인한 뒤) device_register()를 호출해서 klist_drivers를 scan해서 각 device 마다 맞는 driver( match() 이용 )를 찾는다. 그런뒤 device를 klist_devices에 update 한다.
  • klist_driver는 이 bus에 존재하는 device들을 handle할 수 있는 driver들의 list, Device driver가 스스로 initialization 할 때, driver_register()를 호출하여 자신을 등록함으로써 갱신된다.
  • Device Driver가 kernel에 inserted 되면, 이 driver는 driver_register()를 호출하여 해당 bus에 대해 klist_devices를 scan하여 이 driver가 다룰 수 있는 device들을 찾는다. 그런 뒤 driver를 klist_drivers에 update 한다.
  • match()에 의해 device와 driver가 associated 되는 것을 binding이라고 한다.
  • ex) 'drivers/net/phy/mdio_bus.c'
  • struct bus_type mdio_bus_type = {
    . name = "mdio_bus",
    .match = mdio_bus_match,
    .suspend = mdio_bus_suspend,
    .resume = mdio_bus_resume,
    };

 

* '!' is internal to the device motel core and should not be touched by the bus controller driver directly.

 

* Bus Controller Drivers

  • Bus의 device driver다. 따라서, 여느 device drivers와 마찬가지로 자신을 driver_register()로 등록함. 그러나 추가적으로 자신이 다루는 bus 상에 있는 devices를 detect하여 device_register()를 이용해 등록한다. bus_type 구조체의 klist_devices list에.
  • 새로운 Linux device driver model에서 모든 device는 bus 상에 존재하므로, 결국 bus controller driver가 모든 device를 등록한다. struct device 형태로. bus_type 구조체의 klist_devices list에.
  • device
    • bus_id (string)
    • bus (bus_type)
    • parent (device)
    • !driver(device_driver)
  • 'drivers/net/gianfar_mii.c'

 

* Device Drivers

  • 모든 device driver는, driver_register()를 호출해 bus_type 구조체의 klist_driver list에 자기 자신을 등록한다. 그 다음에 device model core가 이 driver를 한 device와 binding을 시도함.
  • 한 device가 registered 되면 (이는 곧 이 device를 handle할 수 있는 drivers가 klist_drivers에 등록된다는 말이므로) 한 특정 driver에 의해 handled 될 수 있는데, 그 driver의 probe member가 하는 일이 바로 그 특정 device 하나를 위해 이 driver의 한 instance를 생성해내는 (그리고 그 device를 초기화하는) 일이다.
  • device_driver
    • bus (bus_type)
    • probe (fp)
    • remove (fp)
    • suspend (fp)
    • resume (fp)
  • bus는 이 driver가 등록될 klist_drivers를 가진 bus_type 구조체에 대한 pointer.
  • probe는, 이 driver가 지원하는 device가 detected (이는 곧 device를 지원하는 drivers를 klist_drivers에서 찾아내는 일을 한 것 즉, binded) 될 때마다 불리는 callback function. 이 함수는 driver 자신을 각 device 당 하나 씩 instantiate한 뒤 그 device를 initialize 한다.
  • remove는 이 driver를 그 device로부터 unbind하기 위해 불리는 callback function. Unbinding은 device가 physically removed 되거나 driver가 unloaded 되거나 system이 shutdown 될 때 일어난다.
  • 'drivers/net/phy/'

 

* Class Drivers

  • Class driver는 그것이 표현하는 device class들에 대해 struct class를 instantiate하여  class_register()를 통해 device model core에 등록한다.
  • Devices를 적당한 class에 추가하는 것은 각 해당 device driver의 책임이다.
  • class
    • name (string)
    • !devices (list)
  • devices는 이 class에 속한 device들의 list이다. 이 list는 device driver들에 의해 갱신된다. (그 device driver들이 자기 자신들을 각 device들에 대해 instantiate할 때).

 

* Conclusion

  • 결국 이런 data structure들이 있음으로 해서, device들이 어떻게 tree 구조를 이루고 있는지 알 수 있고, 어떤 종류의 device들이 system에 존재하는지도 알 수 있다.
  • 그 효과는 더 나은 power management, 그리고 system에 연결된 devices에 대한 더 나은 통찰.

 

출처 : 블로그

 

 

2010년 3월 29일 월요일

모듈 프로그래밍 요약

< 모듈 프로그래밍 요약 >

 

  • 디바이스 드라이버 작성은 모듈 프로그래밍을 기반으로 한다.
  • 모듈 프로그래밍으로 커널의 기능들을 필요시 적재하여 사용하고 불필요시 제거하여 효율성을 높일 수 있다.
  • 모듈 프로그램은 커널의 일부로 삽입되어 실행되므로 신중하게 작성해야 한다.
  • 모듈 프로그램은 기본 형태에 준해서 프로그래밍하고 모듈을 생성하기 위해 Makefile 유틸리티를 이용하는 것이 편리하다.
  • 모듈을 적재, 확인, 제거하기 위해 insmode, lsmod, rmmod 명령을 사용한다.
  • 심볼 사이에 의존 관계가 있을 경우 모듈의 삭제시 주의해야 한다.
  • 시스템 관련 정보는 /proc 파일시스템에 표기된다.
  • 커널 심볼 테이블의 내용은 /proc/kallsyms에서 확인 가능하고 외부로 공개할 심볼은 모듈 프로그램에서 EXPORT_SYMBOL()을 반드시 사용한다.
  • /proc 파일 시스템을 이용하여 프로세스 관련 정보를 확인하는 모듈을 작성할 수 있다.

2010년 3월 25일 목요일

모듈 프로그래밍 주의 사항

모듈 프로그래밍 주의 사항

  • 커널과 모듈 간의 이름공간 오염 방지(namespace pollution)
  • 메모리 접근 시 주의
  • 실수 연산 혹은 MMX 명령 사용 금지
  • 스택 크기가 제한되어 있어 재귀 호출 사용 자제
  • 다양한 플랫폼 고려
  • MMU(Memory Management Unit)가 있는 CPU에서만 지원
  • PNP 기능을 지원하려면 반드시 필요

2010년 2월 16일 화요일

Blob 분석

BLOB : Boot Loader OBject

 

(1) 소개

  • 네덜란드에서 개발한 Open Source의 Boot Loader 프로그램으로 Intel SA-1100 Micro-Processor를 사용한 LART(Linux Advanced Radio Terminal)라는 내장형 컴퓨터에 처음 사용됨.
  • blob-2.0.5-pre3 버전 소스 분석
  • ARM 기반에서 사용하는 대표적인 Boot Loader

    1.BLOB 기능

  • 하드웨어 초기화
  • 레지스터 설정을 통한 시스템의 활성화
  • 저장 매체로부터 Kernel을 읽어서 메모리의 적절한 위치로 적재
  • 압축을 풀고 Kernel로 제어를 옮김
  • 그 외 serial이나 ethernet 장치를 통해 Kernel이나 Ramdisk 등의 image를 다운로드

    2.BLOB 흐름도

 

     (1) Start stage : 하드웨어의 기본적인 초기화 및 레지스터 설정을 담당

     (2) Rest stage : Boot Loader의 부가적인 기능을 제공

 

 

 

    3. 단계별 분석

      3.1 Start Stage

      3.1.1 Boot Loader 시작

      3.1.2 start.S

      3.1.3 rest

      3.1.3.1 Disable All Interrupt

      3.1.3.2 CPU Speed Setup

      3.1.3.3 Memory Setup

      3.1.3.3.1 DRAM Configuration Register

      3.1.3.3.2 DRAM CAS Waveform Shift Register

      3.1.3.3.3 DRAM refresh Controller Register

      3.1.3.3.4 Enable SDRAM BANKS

      3.1.3.3.5 Static Memory Register Configuration

      3.1.3.3.6 SMROM Register Configuration

 

      3.1.3.4 LED Conguration( GPIO )

 

kkkkk

kkkk

 

2010년 2월 9일 화요일

하드웨어 통신 제어 및 인터럽트 처리

(1) 예외처리
  • 외부의 정상적인 요청이나 비정상적인 오류의 발생에 의해서 프로그램을 중지하고 발생된 요청이나 오류를 처리하는 것
  • 예외처리가 발생하면 처리해야 할 프로그램의 위치가 메모리의 특정한 위치에 지정
  • 예외 벡터 테이블


(2) 인터럽트
  • 디바이스는 프로세서와는 다른 시간 간격, 정확하게는 훨씬 느린 시간으로 수행됨.
    • 프로세서가 무작정 외부 이벤트를 기다리는 것은 바람직하지 못하므로 프로세서에게 뭔가 발생했다고 알릴 방법의 필요


(3) 인터럽트 처리
  • 인터럽트 핸들러(인터럽트 서비스 루티 - ISR)
    • 인터럽트를 처리하는 커널 함수
    • 디바이스 드라이버의 일부분
    • 인터럽트 컨텍스트에서 실행
  • 인터럽트 처리를 두 단계로 분리
    • Top half
      • 인터럽트 핸들러
      • 인터럽트가 발생하는 즉시 실행되는 타임 크리티컬한 작업들
    • Bottom half
      • 나중에 해도 무관한 작업들
      • 모든 인터럽트를 활성화시킨 상태에서 실행
        • (보통 인터럽트 핸들러가 리턴되면 실행)

(4) IRQ 인터럽트 서비스 처리 흐름
  • 처리 흐름
    • 프로세서마다 인터럽트 처리 방식이 다름
      • 발생된 IRQ 번호를 획득하여 do_IRQ() 함수 호출
    • 리눅스 커널에서는 동일한 처리를 위해 IRQ 인터럽트는 모두 do_IRQ() 함수를 호출하여 처리
  • request_irq() 함수를 이용하여 처리하고자 하는 IRQ 번호와 서비스 함수 주소를 등록
    • Ex) linux/include/asm-arm/arch-pxa/irqs.h
  • 인터럽트 발생 후
    • 아키텍처마다 고유의 IRQ 검출 루틴을 이용
    • do_IRQ() 함수는 irq_desc 전역변수에서 IRQ 번호에 맞게 등록된 인터럽트 서비스 함수를 찾고, 있으면 호출
    • 참조된 데이터의 주소나 값들은 인터럽트 서비스 함수의 매개변수인 dev_id에 전달
    • 인터럽트 처리가 필요없는 경우에는 free_irq() 함수 호출
      • irq_desc 전역변수에 등록된 인터럽트 서비스 함수를 제거


(5) 인터럽트 서비스 함수의 형식
  • irqreturn_t int_interrupt(int irq, void *dev_id, struct pt_regs *regs)
  • 커널 2.4 - 반환 값은 void
  • 커널 2.6 - 반환 값은 IRQ_HANDLED
  • 매개변수
    • int irq - 인터럽트 번호(irqs.h에 정의)
    • void *dev_id - 인터럽트 서비스 함수를 수행할 때 필요한 정보가 저장된 메모리 주소
    • struct pt_regs *regs - 인터럽트가 발생했을 당시의 레지스터 값(디버깅용)

(6) 인터럽트 서비스 함수 내의 메모리 할당
  • 주로 사용하는 메모리 할당 및 해제
    • kmalloc()
      • GFP_ATOMIC 인자를 사용한 방식만을 사용
      • vmalloc() 함수로 인터럽트가 발생하기 전에 미리 할당한 메모리는 아무런 제약 사항이 없음.
      • kmalloc 할당 후 리턴값 확인 필수

irqreturn_t int_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
char *data;
...
data = kmalloc(128, GFP_ATOMIC);
if( data != NULL ){
...
kfree(data);
}
...
return IRQ_HANDLED;
}


(7)  인터럽트 서비스 함수 등록
  • #include <linux/interrupt.h>를 포함
int request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *),
unsigned long flags, const char *device, void *dev_id);

  • 매개변수
    • irq - 인터럽트 번호
    • (*handler) - 해당 인터럽트 번호를 위한 인터럽트 서비스 함수 포인터
    • flags - 인터럽트 공유나 빠른 인터럽트 처리 등의 속성 지정
      • SA_INTERRUPT - 다른 인터럽트를 허용하지 않음
      • SA_SHIRQ - 동일한 인터럽트 번호를 공유
      • SA_SAMPLE_RANDOM - 랜덤 값 처리에 영향을 줌
    • device - 디바이스 이름(/proc/interrupt 에 쓰임)
    • dev_id - 인터럽트 공유시 구분인자, handler 함수가 참조하는 데이터의 주소 지정
  • request_irq() 함수
    • 정상적 수행시 0 리턴
    • 비정상적 수행시 음수 값 리턴
    • 인터럽트 함수를 등록하는 예
irqreturn_t xxx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
return IRQ_HANDLED;
}

int xxx_interrupt(struct inode *inode, struct file *filp)
{
if( ! request_irq(XXX_IRQ, xxx_ineterrupt, SA_INETRRUPT, "xxx", NULL) )
{
// 정상 등록 후 처리
}

return 0;
}


(8) 인터럽트 서비스 함수 해제
  • free_irq() 함수
    • 커널 2.4와 2.6 사용 동일
    • 등록되어 있던 인터럽트 서비스 함수를 제거
void free_irq(unsigned int irq, void *dev_id);

    • 인터럽트 서비스 함수를 제거하는 예
int xxx_release(struct inode *inode, struct file *filp)
{
// 하드웨어 인터럽트 금지 처리 루틴
...
free_irq(XXX_IRQ, NULL);
return 0;
}



(7) 인터럽트 서비스 등록과 해제 시점
  • 하나의 응용 프로그램만이 디바이스 파일을 사용하는 경우
    • 모듈 초기화, open() 함수 모두 ISR 등록 가능
  • 두 개 이상의 응용 프로그램이 디바이스 파일을 사용하는 경우
    • 모듈 초기화에서 ISR 등록을 주로 함
    • 이유
      • open()에서 등록할 경우 동일한 인터럽트 서비스 루틴이 두 번 등록 -> 구현이 복잡해지며, 에러 처리 고려
      • open()에서 등록할 경우 먼저 해제를 시도한 쪽에서 인터럽트 서비스 함수를 제거하는 경우 다른 쪽 응용 프로그램에서 사용하는 디바이스 드라이버는 인터럽트 서비스 함수가 동작하지 않음.
  • 결론
    • PC 같은 범용 시스템에 사용되는 디바이스 드라이버
      • open()과 close()에서 처리하는 것이 효율적
    • Embedded System에 사용되는 디바이스 드라이버
      • 모듈 초기화 및 모듈 해제 시점에서 처리하는 것이 효율적


(8) 인터럽트 함수와 디바이스 드라이버 간 데이터 공유
  • 인터럽트 서비스 함수는 프로세스 문맥과 별개로 동작하므로 인터럽트 서비스 함수와 디바이스 드라이버 함수 간에 데이터를 공유하는 방법이 필요함.
  • 공유 방법
    • 전역 변수
      • 인터럽트 하나에 인터럽트 서비스 함수 하나가 동작하는 경우
      • 동일한 인터럽트 서비스 함수로 여러 디바이스를 제어할 경우엔 사용 못함.
    • devi_id 매개 변수
      • 여러 디바이스를 하나의 인터럽트 서비스 함수에서 사용 가능
      • 다중 프로세스 환경에 매우 적합함.
/* dev_id를 이용한 데이터 공유 */
typedef struct {
unsigned long ioaddress;
unsigned long count;
} __attribute__((packed)) R_INT_INFO;

irqreturn_t count_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
R_INT_INFO *ptrInfo;
ptrInfo = (R_INT_INFO *)dev_id;
printk("INT READ I/O %02X\n", inb(ptrInfo->ioaddress));
ptrInfo->count++;

return IRQ_HANDLED;
}

int int_open(struct inode *inode, struct file *filp)
{
R_INT_INFO *ptrInfo;

ptrInfo = kmalloc(sizeof(R_INT_INFO), GFP_KERENL);
filp->private_data = ptrInfo;
switch( MINOR(inode->i_rdev) ){
case 0 : ptrInfo->ioaddress = 0x378; break;
case 1 : ptrInfo->ioaddress = 0x278; break;
}

if( ! request_irq(XXX_IRQ, count_interrupt, SA_INTERRUPT, "test", ptrInfo) ){
// 커널 함수가 아니고 임의의 인터럽트 제어 함수
enable_hardware_init(ptrInfo);
}

return 0;
}

int int_release(struct inode *inode, struct file *filp){
R_INT_INFO *ptrInfo = (R_INT_INFO)filp->private_data;

disable_hardware_int(ptrInfo);
free_irq(XXX_IRQ, ptrInfo);
kfree(ptrInfo);
return 0;
}


(9) 인터럽트 공유
  • 같은 인터럽트 번호에 다른 인터럽트 서비스 함수 등록 가능
    • request_irq() 함수의 매개변수에서 flags를 SA_SHIRQ 포함
    • dev_id : 0이 아닌 값 사용
  • 같은 인터럽트 번호에 대해 여러 인터럽트 서비스 함수가 동작할 경우
    • 인터럽트 서비스 함수는 자신이 관리하는 디바이스에서 인터럽트가 발생했는지를 확인하는 과정이 필요
    • 커널 2.6에서는 위의 오류 해결을 위해 인터럽트 서비스 함수의 반환 값을 확인하는 과정을 거침
      • 오류가 발생하면 해당 인터럽트를 금지, IRQ_NONE을 리턴
irqreturn_t xxx_inerrupt(int irq, void *dev_id, struct pt_regs *regs)
{
인터럽트_관리_구조체 * ptrMng = (인터럽트_관리_구조체 *)dev_id;
if( 자신의 인터럽트 처리 함수(ptrMng) )
{
// 인터럽트 처리
...
return IRQ_HANDLED;
}

return IRQ_NONE;
}


(10) 인터럽트 금지와 해제
  • 인터럽트 서비스 함수가 동작 중에 다른 인터럽트가 발생하지 못하게 막는 경우
    • request_irq() 함수의 flags를 SA_INTERRUPT를 사용함.
      • 커널이 프로세서의 인터럽트를 금지 시킨 후 호출
      • 인터럽트 두 개가 동시에 발생하면 SA_INTERRUPT가 설정된 함수 먼저 수행
  • 일반적인 함수 수행 중에 데이터 처리를 보호하기 위해 인터럽트를 강제로 막는 경우
    • #include <asm/irq.h> 포함
    • void disable_irq(int irq) : 인터럽트l 금지
    • void enable-irq(int irq) : 인터럽트 허가
    • void disable_irq_nosync(int irq) : 현재 핸들러가 종료할 때까지 기다리지 않음.
    • synchronize_irq(unsigned int irq) : 특정 인터럽트 핸들러가 실행 중일 경우 기다렸다가 실행이 끝나면 리턴
  • 프로세서 전체의 인터럽트를 금지하고 해제할 경우
    • #include <asm/system.h> 포함
    • local_irq_disable(void) : 프로세서의 인터럽트 처리를 금지
    • local_irq_enable(void) : 프로세서의 인터럽트 처리를 허가
    • local_save_flags(unsigned long flags) : 현재의 프로세스 상태 저장
    • local_restore_flags(unsigned long flags) : 저장된 프로세스 상태 복구
  • 보편적인 인터럽트 방지법
unsigned long flags;

local_save_flags(flags);
local_irq_disable();

// 인터럽트 호출에서 보호하고자 하는 루틴

local_restore_flags(flags);
  • local_save_flags() 함수에 의해 저장된 flags 변수에 이미 인터럽트 허가 상태가 포함되어 있기 때문에 local_resstore_flags() 함수에 의해 local_irq_enable() 호출 효과 발생.


(11) 인터럽트 시스템의 현재 상태 체크
  • irqs_disabled()
    • 로컬 프로세서의 인터럽트가 비활성화된 경우 0이 아닌 값을, 활성화된 경우 0을 리턴.
    • #include <asm/system.h> 포함
  • in_interrupt()
    • 커널이 현재 인터럽트 컨텍스트에 있는 경우 0이 아닌 값을 리턴
    • 커널이 인터럽트 핸들러 혹은 Bottom half 핸들러를 실행중인 상태를 포함
    • #include <asm/hardirq.h> 포함
  • in_irq()
    • 커널이 인터럽트 핸들러를 실행 중일 때만 0이 아닌 값을 리턴
  • 프로세스 컨텍스트인가를 체크해야 할 경우
    • 휴면과 같은 프로세스 컨텍스트에서만 가능한 작업을 수행하기 위해
    • #include <asm/hardirq.h> 포함

디바이스 드라이버의 소개

(1) 장치 파일

 

  • 디바이스 드라이버를 접근하는 통로
  • 장치 파일의 inode는 장치 유형(type), 주번호, 부번호로 구성됨.
  • 장치 파일 생성

    • # mknod /dev/mydev [b|c] 240 0

 

 

(2) 디바이스 드라이버의 구성

  1. 초기화 인터페이스 - init_module() 함수
    • register_chrdev()
    • register_blkdev()
    • request_irq()
    • ...
  2. 시스템 인터페이스 - 문자/블록의 경우 file_operations 이용
    • 문자 드라이버 - open, release, read, write, ioctl
    • 블록 드라이버 - open, release, request, ioctl
    • 네트워크 드라이버 - open, close, transmit, receive, ioctl
  3. 하드웨어 인터페이스
    • in(), out()

 

 

(3) 새로운 디바이스 드라이버 작성 단계

 

  1. 디바이스 드라이버 커널 인터페이스 구현
    • file_operations
  2. 디바이스 드라이버 초기화 인터페이스 구현
    • 주 번호 할당 및 디바이스 드라이버 루틴 등록
  3. 디바이스 하드웨어 인터페이스 구현
    • 레지스터 접근
  4. 장치 파일 생성
    • #mknod /dev/mydev [b|c] major_number minor_number
  5. 응용 프로그램 작성
  6. 커널 컴파일 및 리부팅

 

 

(4) 자원 처리 요청 방법

  • 커널에 자원 처리를 요청하는 방법
    • 응용 프로그램이 커널에게 자원 처리를 요청하는 방법
      • 시스템 호출
      • 파일 입출력 형식을 이용한 디바이스 드라이버 사용

 

  • 시스템 호출 방법
    • Software Interrupt를 이용, 응용 프로그램에서 요청하는 처리를 커널이 수행

 

  •  파일 형식의 디바이스 드라이버
    • 일반 파일을 제어하듯이 디바이스 파일을 통해 하드웨어 입출력 시도
    • 커널 내의 해당 디바이스 파일에 연결된 디바이스 드라이버의 서비스 루틴이 호출되어 디바이스에 대한 처리
    • 모든 처리가 끝나면 커널이 제어 흐름을 다시 응용 프로그램에 넘기는 구조

 

 

(5) 모듈

  • 모듈은 커널이 부팅되어 동작 중인 상태에서 디바이스 드라이버를 동적으로 추가하거나 제거할 수 있게 하는 개념
    • 개발 기간 단축
    • PCI, USB, PCMICIA에 연계된 디바이스의 PNP 기능을 지원하기 위해 모듈 방식이 필수
      • 모듈 방식은 MMU가 있는 CPU에서만 지원
      • 동일한 커널 버전 사용 요구

 

 

(6) 디바이스 파일

  • 리눅스는 모든 하드웨어를 파일로 추상화
    • /dev/ : 디렉토리에 있는 파일들로 실제 하드웨어를 표현
  • 시스템 또는 하드웨어 정보 제공
    • 디바이스 타입정보(문자, 블록), 주번호, 부번호

(7) 디바이스 드라이버의 종류
  1. 문자 디바이스 드라이버 - 버퍼 없음
  2. 블록 디바이스 드라이버 - 버퍼 있음
  3. 네트워크 디바이스 드라이버
    • 커널 내부에 있는 네트워크 프로토콜 스택과 연동


(8) 디바이스 드라이버 계층
  • 시리얼, tty
  • 사운드
  • USB
  • Frame Buffer
  • IDE
  • SCSI
  • PCI


* 원하는 디바이스 드라이버 소스 검색 방법
  • 디바이스 모델명을 찾는다.
    • PCI : lspci
    • USb : lsusb
  • drivers 디렉토리 검색
    • ex) # grep cmd680 * -r
  • Documentation/Configure.help 탐색
    • CONFIG_XXX 변수가 무엇인지 확인
    • 해당 옵션을 사용하는 Makefile 검색

리눅스 디바이스 드라이버 개요

(1) 리눅스 특징

 

  • 모놀리틱 커널 구조(monolithic) - 다양한 컴포넌트로 구성된 거대하고 복잡한 프로그램
  • 모듈 지원 - 동적 로딩 및 제거 가능(디바이스 드라이버)
  • 커널 스레드 제공
  • 다중 프로세서 지원  - SMP(Symmetric Multiprocessing) 지원

 

 

(2) 리눅스의 장점

 

  • 목적에 맞게 컴포넌트 커스터마이징 가능
  • 저가의 하드웨어 플랫폼에서 수행
  • 다른 운영체제와 호환성이 뛰어남 - POSIX 준수

 

 

(3) 리눅스의 단점

 

  • 책임자가 없음 - 개발 및 사후 관리가 어려움

 

 

(4) 임베디드 리눅스를 선택하는 이유

 

  • 코드 품질과 신뢰성
  • 모듈성과 구조, 수정 편의성, 확장성
  • 코드 가용성
  • 하드웨어 지원
  • 통신 프로토콜과 소프트웨어 표준
  • 사용할 수 있는 툴
  • 커뮤니티 지원
  • 가격

 

 

(5) 임베디드 리눅스 시스템 구성

 

  1. 부트 소프트웨어를 포팅하고 설정
  2. 시스템 컴포넌트를 결정
  3. 커널을 설정하고 빌드
  4. 루트 파일시스템을 빌드

 

 

(6) 임베디드 리눅스 시스템 구축 시 고려사항

 

  • 부트로더의 선택은 어떤 것으로 할 것인가?
  • 최신 커널을 사용할 것인가? 충분히 검증된 커널 사용
  • 루트 파일 시스템에 포함할 것은 무엇인가?
    • 파일 시스템의 크기 고려
    • 전체 시스템 가동에 필요한 최소한의 파일만 포함