= 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_t *snd_card_new(int idx, const char *xid, struct module *module, int extra_size) }}} ||매개변수||설명|| ||idx||카드의 인덱스(주소),0에서 (SNDRV_CARDS-1)|| ||xid||카드 이름 (문자열)|| ||module||locking을 소유한 상위 모듈|| ||extra_size||사운드카드 구조체 이후 추가 할당받을 메모리 크기|| 성공하면 snd_card_t형의 포인터를 반환하고 실패하면 NULL을 반환한다. {{{ snd_card_t *card; card = snd_card_new(-1, id, THIS_MODULE, sizeof(foo_bar)); if (card == NULL) return -ENOMEM; }}}==== snd_card_register ==== 사운드 카드를 등록한다. {{{ int snd_card_register(snd_card_t *card) }}} 성공하면 0을 반환하고, 실패하면 0이 아닌 값을 반환한다. 관련함수: snd_card_free ==== snd_card_free ==== 사운드카드 구조체의 자원을 반환한다. {{{ int snd_card_free(snd_card_t *card) }}} 성공하면 0을 반환하고, 실패하면 0이 아닌 값을 반환한다. ==== snd_card_set_pm_callback ==== 전원 관리를 위한 콜백을 등록한다. {{{ int snd_card_set_pm_callback(snd_card_t *card, int (*suspend)(snd_card_t *, pm_message_t), int (*resume)(snd_card_t *), void *private_data) }}} ||필드||설명|| ||card||사운드카드 구조체|| ||suspend||절전 모드 진입시 호출되는 콜백|| ||resume||절전 모드 해제시 호출되는 콜백|| ||private_data||콜백에 넘길 매개 변수의 포인터|| 항상 0을 반환한다. 이 함수는 매개변수 card의 필드 중 pm_suspend, pm_resume, pm_private_data 를 넘겨주는 매개 변수의 값으로 설정한다. {{{ snd_card_set_pm_callback(card, snd_foo_suspend, snd_foo_resume, foo); }}}