Transcript Document

Linux Device Driver
리눅스 디바이스 드라이버 개요
-1-
Device Driver
 디바이스 드라이버의 정의

정의
 디바이스의 정의
LCD, USB, Ethernet, CF, AUDIO 등과 같이 스스템 이외의 주변장치들을 의미
 드라이버의 정의
하드웨어 장치를 제어하고 관리하는 방법의 컴퓨터 시스템
 디바이스 드라이버의 정의
 물리적인 하드웨어 장치를 다루고 관리하는 소프트웨어로 커널의 일부분
 리눅스에서는 모든 장치를 파일로 관리하며 해당 장치는 주번호와 부번호로 구분
 표준화된 호출 방법을 이용하여 디바이스와 어플리케이션간의 정보를 주고 받을 수 있도록 함
(system call)

디바이스 드라이버와 커널





리눅스는 어플리케이션 영역과 커널영역의 구분이 있다.
어플리케이션은 어플리케이션 영역에서만 구동됨
제어해야할 디바이스는 커널이 관리하고 있으므로 커널 영역을 통해야 사용이 가능
어플리케이션 영역에서 커널 영역의 드라이버를 이용하려면 시스템 콜을 발생시켜야 함.
어플리케이션 영역과 커널영역은 독립적인 메모리 공간을 이용
copy_from_user,copy_to_user등과 같은 시스템 함수를 통해 데이터를 전달
-2-
Huins. R&D Center
2
Device Driver

디바이스 드라이버의 종류
 문자 디바이스 드라이버



일반적인 하드웨어 제어에 이용
작고 빈번한 데이터의 송수신에 이용됨
GPIO, PWM, i2C와 같은 장치를 이용하는 디바이스
 블록 디바이스 드라이버



한번에 많은 데이터를 송수신 하는 디바이스
데이터 통신을 위해서 버퍼를 이용함
HDD, Optical Disc와 같이 통상적으로 저장 장치들이 해당
 네트워크 디바이스 드라이버


네트워크와 관련된 장치들을 제어
일반적인 장치들과는 다르게 네트워크 서브 시스템을 통해서 실제 장치와 연결
 어플리케이션에서 하드웨어 제어를 위한 전체 구조
-3-
Huins. R&D Center
3
Device Driver

커널 모듈





리눅스는 모놀리틱커널 이지만 마이크로 커널의 장점인 모듈 기능을 가지고 있다
모듈은 리눅스 시스템이 부팅 된 이후에 동적으로 load 및 unload 할 수 있는 커널의 요소
모듈을 이용하면 커널 요소의 일부분을 별도의 컴파일 없이 교체할 수 있다
커널은 의존성이라는 특성이 있으며, 커널의 버전 정보등은 컴파일된 모듈에 삽입된다.
리눅스 커널 모듈에 대한 정보는 커널소스/include/linux/module.h에 정의되어 있다.
-4-
Huins. R&D Center
4
Device Driver

커널 링크




해당 모듈을 커널에 등록하려면 insmod 명령을 제거하려면 rmmod 명령을 이용
Insmod를 이용해서 모듈을 올리면 버전검사를 하게 된다.
드라이버는 main 함수가 존재하지 않는다.
거널에 등록하기 위한 별도의 함수가 존재한다.


int init_module : insmod를 호출하여 커널에 모듈을 등록할 때 호출
void cleanup_module : 커널에서 모듈을 제거할 때 호출
 커널에 모듈이 링크되는 개념도
-5-
Huins. R&D Center
5
Device Driver

모듈 관련 명령
명령어
용도
insmod
module을 커널에 등록 (load)
rmmod
실행중인 modules을 커널에서 제거(unload)
lsmod
Load된 module들의 정보를 표시
depmod
modprobe
modinfo
커널 내부에 적재된 모듈간의 의존성을 검사
모듈간 의존성을 검사하여 그 결과 누락된 다른 모듈을 찾아서 적재
목적 파일을 검사해서 관련된 정보를 표시
-6-
Huins. R&D Center
6
Device Driver
 Character Device Driver


문자 디바이스는 바이트 스트림 형태로 참조
open, close, read, write 시스템 호출을 구현
ex) /dev/console, /dev/ttySn

문자디바이스와 일반파일의 사용상 차이점
 파일 : 파일의 시작과 끝 사이의 위치에 임으로 접근이 가능
 디바이스 : 일반적으로 순차적으로 참조함
(메모리를 참조하는 드라이버의 경우 파일과 유사한 조작이 가능 ex, framebuffer)
-7-
Huins. R&D Center
7
Device Driver

문자디바이스의 노드를 만드는 방법
mknod /dev/ttySAC0 c 204

디바이스를 커널에 등록 및 해제 하는 함수 (커널 소스/include/linux/fs.h)
 extern int register_chrdev(unsigned int, const char *, struct file_operations *)
○ 첫 번째 인수 : Major 번호로 만약 ‘0’값을 주면 Major 번호 중 사용하지 않는 번호로 동적 할당한다.
○ 두 번째 인수 : 디바이스 name 즉 장치 이름이며, /proc/devices에 나타난다.
○ 세 번째 인수 : 파일연산 함수 (다음에 자세히 설명할 것이다.)
○ 리턴하는 값 : 0이나 양수이면 정상, 음수이면 실패.
 extern int unregister_chrdev(unsigned int, const char *)
○ 첫 번째 인자 : 해제하고자 하는 장치 주 번호(Major nuber)
○ 두 번째 인자 : 해제하고자 하는 장치 이름(Device name)

파일의 연산과 관련된 함수
 loff_t (*llseek) (struct file *, loff_t, int)

장치에서 데이터를 읽거나 쓰는 경우 이용
ssize_t (*read, *write) (struct file *, char *, size_t, loff_t *);
장치에서 데이터를 읽는 경우에 이용
-8-
Huins. R&D Center
8
Device Driver
 unsigned int (*poll) (struct file *, struct poll_table_struct *);



현재 실행중인 프로세스를 대기 queue에 넣음
int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
디바이스에 종속적인 함수나 프로그래머의 임의의 커맨드를 만듦.
int (*mmap) (struct file *, struct vm_area_struct *);
디바이스의 메모리를 응용 프로세스의 메모리에 매핑
int (*open) (struct inode *, struct file *);
디바이스를 열고자 할때 이용
 int (*release) (struct inode *, struct file *);
디바이스를 닫을 때 이용
 Block Device Driver








문자 디바이스와 마찬가지로 /dev/ 디렉터리의 노드를 통해 접근
파일 시스템을 수용할 수 있는 디바이스 드라이버
응용 프로그램이 블록 디바이스를 문자 디바이스 처럼 사용할 수 있음
한번에 전송할 데이터의 크기의 제한이 없음
버퍼 캐시를 통하여 랜덤 액세스가 가능
문자디바이스와의 차이는 드라이버 소프트웨어 인터페이스에서만 차이가 남
문자디바이스와 별개로 관리되므로 문자디바이스와 동일한 주번호 및 부번호 이용가능
문자 디바이스 드라이버의 등록과 해제에 이용되는 함수
-9-
Huins. R&D Center
9
Device Driver
 extern int register_blkdev(unsigned int, const char *, struct block_device_operations *);
○ 첫 번째 인자 : Major 번호, 0이면 동적 할당
○ 두 번째 인자 : 블록 디바이스 이름
○ 세 번째 인자 : 블록 디바이스 장치에 대한 파일 연산 함수
○ 리턴 값 : 0이나 양수이면 정상, 음수이면 에러
 extern int unregister_blkdev(unsigned int, const char *);
○ 첫 번째 인자 : Major 번호
○ 두번째 인자 : 블록 디바이스 이름

블록 디바이스의 파일 연산
 Read, write, fsync 함수는 별도로 구현하지 않고 제공되는 함수를 이용
 Open과 release는 문자 디바이스 드라이버 처럼 구현
 Ioctl은 많은 장치들이 사용할 것이라 예상하는 공통적인 커맨드를 지원
- BLKGETSIZE : 장치의 크기를 섹터의 개수로 환산해 리턴
- BLKFLSBUF : 버퍼 캐시를 flush
- BLKRAGET : 미리 읽어올 데이터 크기
- BLKRASET : 미리 읽어올 데이터 셋팅
- BLKROGET : flag 얻어오기
- HDIO_GETGEO : 하드 디스크의 구조 읽어오기 등이 바로 그것이다.
- 10 -
Huins. R&D Center
10
Device Driver
 Floppy 드라이버의 예시
 버퍼 캐시의 상태
블록 디바이스는 버퍼 캐시를 이용하여 데이터를 주고 받는다
- BH_Uptodate 현재 버퍼는 유효한 데이터를 가지고 있다.
- BH_Dirty 디스크에 있는 데이터와 버퍼의 데이터는 다르다.
- BH_Lock 현재 버퍼가 Lock되어 있다. (처리 중에 있다)
- BH_Req 해당하는 블록이 데이터를 요청.
- BH_Mapped 버퍼가 현재 디스크에 mapping 되어 있다.
- BH_New 버퍼가 새로운 것이며 아직 write 되지 않았다.
- BH_Protected 버퍼가 보호되고 있는 상태. 이 버퍼는 free 되지 않는다.
- 11 -
Huins. R&D Center
11
Device Driver
 네트워크 디바이스
 모든 네트워크 트랜잭션은 다른 호스트와 데이터를 교환해주는 디바이스를 거침
 네트워크 디바이스의 데이터 패킷 전송은 커널에 포함된 네트워크 서브시스템에 의한다.
 네트워크 인터페이스는 스트림 형태의 디바이스가 아니라 스페셜 파일이 생성되지 않는다

( lo, eth, wlan0 등과 같은 고유한 이름을 할당 받아 참조하지만, 파일 시스템에 포함되진 않음)
어플리케이션에서 read나 write 함수를 이용하는 경우 드라이버 상의 fos의 read,write가 아닌
패킷 전송에 관련된 함수를 호출하여 처리한다
 Achro4210에서 이용되는 문자 드라이버 소개

Framebuffer
 Linux 시스템에서 그래픽을 표현할 수 있는 하드웨어
 Framebuffer는 LCD에 표시할 정보를 저장해놓는 버퍼
 LCD 컨트롤러는 DMA를 이용하여 Framebuffer의 내용을 주기적으로 LCD로 보냄
- 12 -
Huins. R&D Center
12
Device Driver
 리눅스에서 연결하는 디바이스 노드
[root@uclibc /dev]# ls -al fb0
crw-rw-rw- 1 root root 29, 0 Jan 1 09:00 fb0

SD/MMC (rivers/mmc/core/, drivers/mmc/host)
 SD Host controller



Achro-4210에서 SD interface를 제공함
WiFi 등과 같은 SD인터페이스를 이용하는 다양한 장비를 사용할 수 있음
일반적으로 MMC등과 같은 메모리를 연결하여 사용
 리눅스에서 연결하는 디바이스 노드 (일반적인 상황)
/dev/ mmcblk0
/dev/ mmcblk0p1
/dev/ mmcblk0p2
/dev/ mmcblk1
/dev/ mmcblk1p1

Audio
 Audio Subsystem을 포함
 오디오 하드웨어 코덱에 따라 다 채널의 I2S 인터페이스를 지원
 칩 컨트롤은 I2C 통신을 통하고, 데이터는 I2S로 처리
- 13 -
Huins. R&D Center
13
Device Driver
 오디오 관련 소스



arch/arm/plat-s5p/dev-audio.c,
Driver/sound 관련 전체에 전반적으로 존재
코덱은 ound/soc/codecs에 위치
 오디오와 관련된 디바이스 노드 (기본적인 노드)
/dev/dsp
/dev/dsp0
/dev/dsp1
/dev/mixer
/dev/mixer0
/dev/mixer1

터치 스크린 인터페이스





터치 스크린은 임베디드 디바이스에서 주로 사용되는 입력 장치이다.
일반적으로 감압식과 정전식으로 크게 나눌 수 있다.
감압식은 터치 위의 패널을 눌러서 발생되는 저항값을 통해 포인팅 함
정전식은 화면에 누른 사람이나 물체에 흐르는 미세한 전류를 이용하여 포인팅 함
Achro-4210의 경우 I2C를 이용하여 장치와 통신을 함.
- 14 -
Huins. R&D Center
14
Device Driver
 터치 관련된 디바이스 노드 (일반적인 노드)
터치와 관련된 노드는 해당 드라이버를 설정할 때의 위치에 따라 이름과 장치가 변경됨
/dev/ts
/dev/ts0
/dev/input/event0
/dev/input/event1

UART




일반적으로 시리얼 통신을 할 수 있는 포트를 의미한다.
Achro-4210에서 외부와 통신할 수 있는 UART는 2개이며, 한 포트는 디버그 포트로 이용
UART로 설정하여 사용할 때에는 /dev/ttyS로 시작하는 노드를 갖게 된다.
UART 관련된 디바이스 노드
/dev/ttySAC0
UART 0
/dev/ttySAC1
UART 1
/dev/ttySAC2
UART 2
/dev/ttySAC3
UART 3
- 15 -
Huins. R&D Center
15
Device Driver
 Ioremap과 mmap()

Mmap()은 응용프로그램의 가상 주소에 커널의 해당 디바이스의 메모리 영역을 매핑
 장점 : 매핑된 이후로 시스템 콜을 사용하지 않고 해당 장치의 메모리 영역을 이용
(커널 영역에서 발생하는 많은 시간적 비용이 줄어들어 빠른 처리가 가능)
 단점 : 매핑할 메모리 공간이 많이 필요한 다수의 장치를 모두 이용하는데 여러 고려사항 필요

Ioremap() 커널의 가상 주소에 디바이스의 메모리 영역을 매핑
 장점 : 크지 않은 메모리 크기에 대해서 할당 받아 사용이 가능
(메모리를 할당 받기 위해서 전 처리 해야 되는 부분이 쉬움)
 단점 : 프로그램이 지속적인 참조를 할 경우 반복되는 시간만큼 커널 내 처리시간이 늘어남
- 16 -
Huins. R&D Center
16
Device Driver

Iormap과 mmap의 동일 하드웨어 제어 코드 비교 예시
// ioremap – kernel module
… 생략 …
#include <linux/ioport.h>
#define IOM_LED_MAJOR 246
// led device major number
#define IOM_LED_NAME “led_driver” // led device name
#define IOM_LED_ADDRESS 0xA8000000 // physical address
// mmap.c – linux application
… 생략 …
#include <sys/mman.h>
/* 페이지 크기(4096)의 정수배 */
#define MAP_SIZE 0x1000
/* led의 physical address */
struct file_operations iom_led_fops = {
open:
iom_led_open,
write:
iom_led_write,
release:
iom_led_release,
};
#define MAP_PHYS 0xA8000000
#define LED (*((volatile unsigned short *)(map_base + 0)))
void *map_base;
ssize_t iom_led_write(struct file *inode, const char *gdata, size_t length,
loff_t *off_what) {
unsigned short value;
const char *tmp = gdata;
if (copy_from_user(&value, tmp, 2))
return -EFAULT;
outw(value,(unsigned int)iom_led_addr);
return length;
}
int main (int argc, char *argv[]) {
int fd = open( "/dev/led_driver", O_RDWR | O_SYNC );
…
map_base = mmap( NULL, MAP_SIZE, PROT_READ |
PROT_WRITE, MAP_SHARED, fd, MAP_PHYS );
if (map_base == MAP_FAILED) {
perror("mmap()");
exit(2);
}
…
int __init iom_led_init(void) {
int result =
register_chrdev(IOM_LED_MAJOR, IOM_LED_NAME, &iom_led_fops);
…
iom_led_addr = ioremap(IOM_LED_ADDRESS, 0x2);
return 0;
}
void __exit iom_led_exit(void) {
iounmap(iom_led_addr);
unregister_chrdev(IOM_LED_MAJOR, IOM_LED_NAME);
}
/* 할당받았던 매핑 영역을 해제한다. */
if (munmap(map_base, MAP_SIZE) == -1) {
perror("munmap()");
exit(3);
}
close(fd);
return 0;
module_init(iom_led_init);
module_exit(iom_led_exit);
}
- 17 -
Huins. R&D Center
17
Device Driver

전체 수행 구조 비교
ioremap은 커널에 모듈로 등록이 되므로 해당 모듈을 참조하여 값을 전송하는 어플리케이션이 필요
 mmap으로 애플리케이션에서 매핑한 경우 시스템 콜 없이 디바이슬 제어할 수 있다.
 ioremap으로 드라이버를 만든후 하드웨어를 제어할 경우 시스템 콜을 이용한다.
- 18 -
Huins. R&D Center
18