2006. 3. 22. 13:17
[본문스크랩] register_chrdev()상세 설명
2006. 3. 22. 13:17 in Embedded System/Device Driver
register_chrdev()상세 설명 |
글쓴이 : 박철 (2002년 12월 28일 오후 12:25) 읽은수: 1,996 [ 임베디드강좌/박철 ] |
이번 강좌는 커널 함수인 register_chrdev()를 다루고자 한다. 이 함수의 기능은 커널 내부에 등록된 문자장치를 관리하는 chrdev[] 배열구조체에서 하나의 배열을 할당을 받고, 그 배열 안의 필드에 각각의 문자장치의 이름과 파일 오퍼레이션을 연결하는 것이다. 이렇게 함으로써 해당하는 커널내부에 문자장치로 등록이 되며 이 장치를 사용하고자 하는 어플리케이션이 있을 때 이를 사용할 수 있도록 한다. 아래는 커널 내에서 정의된 chrdevs[]에 관련된 구조체와 관련된 내용이다. 문자 장치는 256개 배열의 형태로 등록이 될 수 있으며 이러한 배열의 각각은 문자장치의 이름을 나타내는 포인터와 이문자 장치를 사용할 수 있는 파일 오퍼레이션의 포인터를 포함한다. http://lxr.hybus.net/source/fs/devices.c?a=arm#L39 39 static struct device_struct chrdevs[MAX_CHRDEV]; http://lxr.hybus.net/source/include/linux/major.h?a=arm#L15 15 #define MAX_CHRDEV 255 http://lxr.hybus.net/source/fs/devices.c?a=arm#L33 33 struct device_struct { 34 const char * name; 35 struct file_operations * fops; 36 }; 보통 register_chrdev() 함수는 모듈이 적재될 때 실행되는init_module()함수내부에 있어서 커널이 부팅되거나, 모듈로 적재될 때 커널내부에 있는 배열 구조체인 chrdev[]에 등록되도록 하는 것이다. 여기서 예로든 파일은 gpio.c이며 다음과 같이 init_module()내부에서 사용되었다. http://www.hybus.net/lecture/lecture_2.php result = register_chrdev(gpio_major, "GPIO", &gpio_fops); 여기서 첫번째 인자인 gpio_major는 배열chrdev[]의 순서를 결정하는 major번호를 의미하며, 두번째 인자는 등록될 문자장치의 이름을 의미한다. 그리고 마지막 인자는 사용되어질 파일 오퍼레이션을 위한 함수 포인터를 의미한다. 이 세 번째 인자는 gpio.c에 있는 아래의 자료구조에 사용되어질 함수의 주소 값이 등록된다. struct file_operations gpio_fops = { // 파일 구조체 정의 read: gpio_read, write: gpio_write, open: gpio_open, release: gpio_release, }; 아래는 커널함수인 register_chrdev()의 원형을 나타낸 것이다. http://lxr.hybus.net/source/fs/devices.c?a=arm#L98 98 int register_chrdev(unsigned int major, const char * name, struct file_operations *fops) 99 { 1. 첫번째 인자, major가 0이면 자동 할당을 의미한다. 100 if (major == 0) { 101 write_lock(&chrdevs_lock); 2. major번호가 높은 순서로 할당되지 않은 chrdev[]배열 구조체를 찾아서 찾은 배열의 구조체의 필드인 chrdevs[major].name은 두번째 인자인 name의 값을 받으며, chrdevs[major].fops은 세번째 인자인 fops의 주소 값을 받는다. 그리고 리턴 값으로 할당된 major를 돌려 준다. Gpio.c에 정의된 내용과 같은 경우에는 major가 0이므로 자동할당 시에 큰 번호(255)부터 스캔을 해나가면서 등록되지 않은 배열의 값을 major로 할당하며 이값을 리턴한다. 이때 등록되는 문자장치의 이름은 GPIO이며, 등록되는 문자장치를 위한 파일 오퍼레이션은 gpio_fops이 되는 것이다. 102 for (major = MAX_CHRDEV-1; major > 0; major--) { 103 if (chrdevs[major].fops == NULL) { 104 chrdevs[major].name = name; 105 chrdevs[major].fops = fops; 106 write_unlock(&chrdevs_lock); 107 return major; 108 } 109 } 110 write_unlock(&chrdevs_lock); 111 return -EBUSY; 112 } 3. major값이 MAX_CHRDEV(255)보다 큰 경우에는 에러처리한다. 113 if (major >= MAX_CHRDEV) 114 return -EINVAL; 115 write_lock(&chrdevs_lock); 4. 아래는 major값이 0 보다 크고 MAX_CHRDEV(255)보다 작은 경우에 실행되는 코드이다. chrdevs[major].fops가 0이 아니거나, chrdevs[major].fops가 세번째 인자인fops 같지 않은 경우에는 -EBUSY를 가지고 반환한다. 116 if (chrdevs[major].fops && chrdevs[major].fops != fops) { 117 write_unlock(&chrdevs_lock); 118 return -EBUSY; 119 } 5. chrdev[]배열 구조체의 해당하는 major번호와 일치하는 배열의 구조체의 필드인 chrdevs[major].name은 두번째 인자인 name의 값을 받으며, chrdevs[major].fops은 세번째 인자인 fops의 주소 값을 받는다. 그리고 리턴 값으로 0을 돌려 준다. 120 chrdevs[major].name = name; 121 chrdevs[major].fops = fops; 122 write_unlock(&chrdevs_lock); 123 return 0; 124 } 첨부 파일: register_chrdev.JPG (100 KiB(102,357 Bytes)) |
'Embedded System > Device Driver' 카테고리의 다른 글
리눅스에서의 시리얼 통신(I) (0) | 2006.04.05 |
---|---|
임베디드 리눅스로 I2C 버스에 접근하자 (1) | 2006.03.28 |
[본문스크랩] Linux kernel 2.6.13 platform device driver 분석 (0) | 2006.03.28 |
[본문스크랩] net_device구조체 (0) | 2006.03.28 |
[본문스크랩] Q: get_user() 함수와 put_user() 함수는 어떻게 사용.. (0) | 2006.03.28 |