= Kernel API = -- [김도집] [[DateTime(2005-09-22T05:20:31)]] [[TableOfContents]] == 드라이버 등록 및 해제 == === 관련 자료형 === driver_register/device_unregister 함수에서 사용하는 자료형은 에 선언되어 있다. {{{ struct device_driver { const char *name; struct bus_type *bus; struct completion unloaded; struct kobject kobj; struct klist klist_devices; struct klist_node knode_bus; struct module *owner; int (*probe) (struct device *dev); int (*remove) (struct device *dev); int (*shutdown) (struct device *dev); int (*suspend) (struct device *dev, pm_message_t state, u32 level); int (*resume) (struct device *dev, u32 level); }; }}} ||필드||설명|| ||name||디바이스 드라이버의 이름을 문자열 형으로 지정한다 (필수)|| ||bus||보통은 &platform_bus_type으로 지정한다 (필수)|| ||unloaded|||| ||kobj||내부적으로 드라이버 객체를 관리하기 위한 것으로 직접적으로 사용하지 않는다 (임의 지정하지 않는다)|| ||klist_devices|||| ||knode_bus|||| ||owner|||| ||probe()||디바이스의 초기화 루틴이다 (필수)|| ||remove()||디바이스가 제거될 때 호출되는 루틴이다 (필수)|| ||shutdown()|||| ||suspend()||절전모드로 들어갈 때 호출된다 (필수)|| ||resume()||절점모들 빠져나올 때 호출된다 (필수)|| /!\ 위 테이블에서 foo()와 같이 ()가 붙은 필드는 함수(포인터)를 의미한다. === driver_register === 버스를 갖는 드라이버를 등록할 때 사용하는 함수이다. 함수의 원형은 다음과 같다: {{{ int driver_register(struct device_driver *drv); }}} 관련함수: driver_unregister {{{ static struct device_driver foo_driver = { .name = "foo”, .bus = &platform_bus_type, .probe = foo_probe, .remove = foo_remove, .suspend = foo_suspend, .resume = foo_resume, }; static int __init foo_init(void) { int err; err = driver_register(&foo_driver); return err; } }}} === driver_unregister === driver_register()를 통해 등록된 드라이버를 해제할 때 사용한다. 함수의 원형은 다음과 같다: {{{ void driver_unregister(struct device_driver *drv) }}} 관련함수: driver_register == 메모리 == === 사용자/커널 공간 === 메모리 영역은 사용자 영역과 커널 영역으로 나뉜다. 일반적으로 사용자 영역의 경우 page out(swap out)된 경우가 있을 수 있다. 이런 메모리 공간을 커널 영역에서 직접 접근하는 경우 page fault 등이 생길 수 있는데, 커널 공간의 일부 처리 중에는 이러한 것이 문제가 될 수 있다. 반대로 커널 영역의 메모리는 사용자 영역의 프로세스에서 직접 접근할 수 없다. 따라서 서로 다른 영역을 메모리를 접근하기 위해서는 이에 필요한 적절한 API를 이용해야 한다. ==== copy_from_user ==== 사용자 영역의 메모리에 있는 데이터를 커널 영역의 메모리 영역으로 복사할 때 사용하는 함수이다. 이 함수는 아키텍처에 의존적인 함수로 헤더 파일에 선언되어 있다. {{{ unsigned long copy_from_user(void *to, const void __user *from, unsigned long n) }}} ||매개변수||설명|| ||to||커널 영역의 메모리 주소|| ||from||사용자 영역의 메모리 주소|| ||n||바이트 단위의 데이터 크기|| 성공하면 0을 반환하고 실패하면 0이 아닌 값을 반환한다. 관련함수: copy_to_user /!\ 함수 내부적으로 access_ok를 통해 사용자의 메모리 영역을 검사하므로 별도의 access_ok를 호출할 필요는 없다. ==== copy_to_user ==== {{{ unsigend long copy_to_user(void __user *to, const void *from, unsigned long n) }}}==== get_user ==== 사용자 영역의 데이터를 커널 영역으로 복사할 때 사용한다. 이는 아키텍처 의존적인 함수로 에 선언되어 있다. {{{ int get_user(void *to, void *from) }}} ==== put_user ==== 커널 영역의 데이터를 사용자 영역으로 복사한다. 이는 아키텍처 의존적인 함수로 에 선언되어 있다. {{{ int put_user(void *from, void *to) }}}==== access_ok ==== 사용자 영역의 메모리가 유효한지 검사한다. 에 선언되어 있다. {{{ int access_ok(int type, void *addr, unsigned long size); }}} ||매개변수||설명|| ||type||어떤 유효 검사를 할지를 결정한다. 다음 표를 참조|| ||addr||유효 검사를 시작할 주소|| ||size||유효 검사를 할 영역의 바이트 단위 크기|| type 매개 변수는 매크로로 선언되어 있는데, 다음과 같다: ||type||설명|| ||VERIFY_READ||읽기에 대한 유효 검사|| ||VERIFY_WRIT||쓰기에 대한 유효 검사|| /!\ 다른 함수와 달리 유효하다면 0이 아닌 값을 반환하고 유효하지 않다면 0을 반환한다. copy_from_user/copy_to_user 또는 get_user/put_user 등의 함수는 access_ok를 사용할 필요가 없다. __get_user 등과 같이 더 저 수준의 함수를 직접 호출하여 사용할 때만 사용하게 된다. 다음은 access_ok를 사용한 예이다. {{{ static inline unsigned long copy_from_user(void *to, const void __user *from, unsigned long n) { if (access_ok(VERIFY_READ, from, n)) n = __arch_copy_from_user(to, from, n); else memzero(to, n); return n; } }}} == 사운드(Sound) == === ALSA === ==== 자료 구조 ==== snd_card_t는 에 정의 되어 있다. 이는 strcut _snd_card 의 typedef형이다. {{{ struct _snd_card { char driver[16]; /* 드라이버 이름 */ char shortname[32]; /* 사운드 카드의 짧은 이름 */ char longname[80]; /* 사운드 카드의 이름 */ void *private_data; /* 사운드 카드에 대한 추가 정보 */ void (*private_free) (snd_card_t *card); /* 추가 정보을 위해 할당받은 자원 반환을 */ /* 위한 콜백 */ }}} /!\ 위 구조체의 필드는 위 명시된 내용 외에도 무수히 많다. 사용자가 꼭 알아야 하는 것들만 나열했다. ==== snd_card_new ==== ==== snd_card_register ==== ==== snd_card_set_pm_callback ====