Linux 플랫폼 드라이버 개발이란 무엇입니까?
배우기 전에는 드라이버 개발이 너무 낯설고 뭔가 신비로운 느낌이 들었어요. 드라이버 개발과 일반 프로그램 개발의 차이점이 무엇인지, 개발 환경의 특별한 점, 작성하기 전에 간단한 문자 장치 드라이버를 컴파일하고 로드하는 방법을 설명하겠습니다. 이러한 문제를 하나씩 소개하겠습니다.
1. 드라이버의 기본 프레임워크
1. 그렇다면 드라이버란 정확히 무엇이고 그 용도는 무엇입니까?
l 드라이버는 하드웨어 장치와 애플리케이션 사이의 중간 소프트웨어 계층입니다.
l 특정 하드웨어가 응답할 수 있도록 해줍니다. 장치의 작업 세부 정보를 완전히 숨기면서 잘 정의된 내부 프로그래밍 인터페이스에
l 사용자는 특정 장치와 독립적인 일련의 표준화된 호출을 통해 해당 작업을 완료합니다
l 드라이버의 임무는 이러한 표준화된 시스템 호출을 실제 하드웨어에 있는 특정 장치의 특정 작업에 매핑하는 것입니다.
l 드라이버는 커널의 일부이며 인터럽트, DMA 및 기타 작업을 사용할 수 있습니다.
l 드라이버는 사용자 모드와 커널 모드 사이에서 데이터를 전송합니다
2. Linux 드라이버의 기본 프레임워크
3. Linux에서의 장치 드라이버는 일반적으로 다음 세 가지 범주로 나눌 수 있습니다.
1) 문자 장치
a) 바이트 스트림처럼 접근할 수 있는 모든 장치는 문자 장치를 통해 구현됩니다.
b) 파일 시스템의 노드, 일반적으로 /dev/ 디렉터리에 매핑됩니다.
c) 일반적으로 open read write close와 같은 시스템 호출 구현을 포함합니다.
2) 블록 장치
d) 일반적으로 파일 시스템을 수용할 수 있는 디스크, 메모리, 플래시 등의 저장 장치를 말합니다.
e) 블록 장치도 파일 시스템을 통해 액세스됩니다. 문자 장치와의 차이점은 커널이 데이터를 관리하는 방식이 다르다는 것입니다.
f) 바이트 스트림을 허용합니다. 문자 장치처럼 액세스하면 한 번에 원하는 수의 바이트를 전달할 수도 있습니다.
3) 네트워크 인터페이스 장치
g) 일반적으로 하드웨어 장치를 의미하지만 때로는 소프트웨어 장치(예: 루프백 인터페이스 루프백)에 의해 제어될 수도 있습니다. 데이터 패킷 전송 및 수신을 담당하는 커널의 네트워크 하위 시스템입니다.
h) 데이터 전송이 스트림 지향적이지 않은 경우가 많으므로 파일 시스템 노드에 매핑하기가 어렵습니다.
2. 드라이버 개발 환경을 구축하는 방법
드라이버는 커널에 컴파일되어야 하기 때문에 커널이 시작되거나 컴파일될 때 하드웨어 장치가 구동됩니다. .o 파일, 애플리케이션에 필요할 때 커널 공간에 동적으로 로드되어 실행됩니다. 따라서 드라이버 컴파일은 커널 소스 트리에 연결되어야 합니다. 따라서 환경 구축의 첫 번째 단계는 물론 커널 소스 트리를 구축하는 것입니다
1. 커널 소스 트리 구축 방법
a) 먼저 시스템에 소스가 있는지 확인하십시오. lib/ 모듈 디렉토리에는 커널 정보가 있습니다. 예를 들어 현재 시스템에는 두 가지 버전이 있습니다:
#ls /lib/ 모듈
2.6 .15-rc7 2.6.21- 1.3194.fc7
소스 코드 위치 보기:
## ll /lib/modules/2.6.15-rc7/build
lrwxrwxrwx 1 루트 루트 27 2008 -04-28 19:19 /lib/modules/2.6.15-rc7/build -> /root/xkli/linux-2.6.15-rc7
찾음 해당 빌드는 링크 파일이며, 디렉토리는 소스 트리의 디렉토리입니다. 그러나 이제 대상 디렉터리가 유효하지 않습니다.
따라서 직접 다시 다운로드해야 합니다.
b) 소스 트리를 다운로드하고 컴파일하세요.
다운로드할 수 있는 웹사이트가 많지만 공식 웹사이트는 다음과 같습니다:
http://www .kernel.org/pub/linux/kernel/v2.6/
물론 다운로드 후 압축을 풀고 컴파일하세요
# tar – xzvf linux-2.6.16.54.tar.gz
#cd linux-2.6.16.54
## make menuconfig (커널 옵션을 구성합니다. 구성이 없으면 컴파일할 수 없습니다. 다음 단계에서는 아무것도 변경할 필요가 없습니다.)
#make
…
컴파일에 오류가 없는 경우. 축하합니다.
개발 환경이 설정되었습니다.
3. 드라이버의 기본 지식을 이해하세요.
1. 장치 번호
1) 장치 번호는 무엇입니까? 시스템에 들어가서 기존 장비를 기준으로 설명해보자:
#ls -l /dev/
crwxrwxrwx 1 root root 1, 3 2009-05-11 16:36 null
crw--------- 1 루트 루트 4, 0 2009-05-11 16:35 systty
crw-rw-rw- 1 루트 tty 5, 0 2009- 05-11 16:36 tty
crw-rw---- 1 root tty 4, 0 2009-05-11 16:35 tty0
앞의 두 문자 date 숫자(예를 들어 첫 번째 열은 1,3)는 표시되는 장치 번호입니다. 첫 번째는 주요 장치 번호이고, 두 번째는 슬레이브 장치 번호입니다.
2) 무엇입니까? 장치 번호의 사용?
l 전통적으로 메이저 번호는 장치가 연결된 드라이버를 식별합니다. 예를 들어 /dev/null 및 /dev/zero는 모두 드라이버 1에 의해 관리되는 반면 가상 콘솔과 직렬 터미널은 관리됩니다. 둘 다 드라이버 4에 의해 관리됩니다.
l 번호는 커널에서 참조할 장치를 결정하는 데 사용됩니다. 이는 드라이버 작성 방법에 따라 다릅니다.
3) 장치 번호 구조 유형 및 응용 방법
l 커널에서 dev_t 유형(정의됨)은 장치 번호를 보유하는 데 사용됩니다. 2.6.0 커널의 경우 dev_t는 32비트 수량이며 12비트가 사용됩니다. 메이저 번호, 그리고 20비트가 마이너 번호로 사용됩니다.
l은 dev_t의 메이저 또는 마이너 번호 매기기 방법을 얻을 수 있습니다:
MAJOR(dev_t dev) //Major
MINOR(dev_t dev);//Minor
l 하지만 메이저 번호와 마이너 번호가 있는 경우 이를 dev_t로 변환해야 합니다. MKDEV(int major, int 마이너);
4) 프로그램에서 장치 번호를 할당하고 해제하는 방법
캐릭터 드라이버를 구축할 때 가장 먼저 해야 할 일은 해당 장치에 대한 하나 이상의 장치 번호를 얻는 것입니다. 이 기능을 수행할 수 있는 두 가지 기능이 있습니다:
l 하나는 장치 번호를 미리 알고 있다는 것입니다.
register_chrdev_region, 선언:
int Register_chrdev_region(dev_t first, unsigned int count, char *name);
first는 할당하려는 시작 장치 번호입니다. first의 보조 번호 부분은 항상 0이고, count는 연속된 총 개수입니다. 요청한 장치 번호입니다. name은 이 번호 범위에 연결되어야 하는 장치의 이름입니다. 이는 /proc/devices 및 sysfs에 표시됩니다.
l 두 번째는 장치 번호를 동적으로 할당하는 것입니다. /p>
int alloc_chrdev_region(dev_t *dev, unsigned int firstminor, unsigned int count, char * name);
이 함수를 사용하면 dev는 첫 번째 숫자를 보유하는 출력 전용 매개변수입니다. 함수가 성공적으로 완료되면 할당 범위는 fisetminor가 가장 먼저 요청해야 하며 일반적으로 0입니다. count 및 name 매개변수는 request_chrdev_region과 동일합니다.
5) 장치 해제 숫자
기기 번호 할당 방법에 관계없이 사용하세요.
다음과 같이 사용 후 해제해야 합니다:
void unregister_chrdev_region(dev_t first, unsigned int count);
6)
2. 중요한 데이터 구조
1) file_Operation
예를 들어, 문자 장치 스컬의 일반적인 정의는 다음과 같습니다:
struct file_Operations scull_fops = {
.owner = THIS_MODULE,
.llseek = scull_llseek,
.read = scull_read,
.write = scull_write,
.ioctl = scull_ioctl,
.open = scull_open,
.release = scull_release,
};
file_Operation도 장치 드라이버 인터페이스
는 함수 포인터 모음인 에 정의되어 있습니다. 열려 있는 각 파일(내부적으로 파일 구조로 표시됨)은 자체 함수 집합과 연결됩니다. file_Operations 구조를 가리킴) 이러한 작업의 대부분은 시스템 호출 구현을 담당하므로 이름은 open, read 등으로 지정됩니다.
2) 파일
정의는 다음 위치에 있습니다. include/fs .h
드라이버와 관련된 구조체 파일 구조의 멤버
l mode_t f_mode는 파일의 읽기 및 쓰기 권한을 식별합니다.
l loff_t f_pos 현재 읽기 및 쓰기 위치
l unsigned int_f_flag 파일 플래그, 주로 차단/비차단 작업 중에 확인됩니다.
l struct file_Operation * f_op 파일 작업의 구조 포인터
l void * private_data 드라이버 일반적으로 할당된 데이터를 가리킨다
l struct dentry* f_dentry 파일에 해당하는 디렉토리 항목 구조
캐릭터 장치 등록
1) 커널은 내부입니다. 커널이 장치 작업을 호출하기 전에 struct cdev 유형의 구조를 사용하여 이러한 구조 중 하나 이상을 할당하고 등록해야 합니다. 그리고 이들 구조 중 하나를 초기화합니다.
l 런타임에 독립적인 cdev 구조를 얻으려면 다음과 같이 사용할 수 있습니다:
struct cdev *my_cdev = cdev_alloc();
my_cdev->ops = &my_fops;
l cdev 구조를 자신의 장치별 구조에 포함하려면 다음을 사용하여 할당한 구조를 초기화해야 합니다. :
void cdev_init(struct cdev *cdev, struct file_Operations *fops);
2) cdev 구조가 생성되면 마지막 단계는 이를 커널에 알리는 것입니다. :
int cdev_a
dd(struct cdev *dev, dev_t num, unsigned int count);
설명: dev는 cdev 구조이고, num은 이 장치가 응답한 첫 번째 장치 번호이며, count는 연결되어야 하는 장치 번호입니다. 일반적으로 개수는 1이지만 특정 장치에 해당하는 장치 번호가 여러 개 있는 경우도 있습니다.
3) 시스템에서 문자 장치를 제거하려면 다음을 호출하세요.
void cdev_del(struct cdev *dev);
4 열기 및 해제