리눅스 드라이버 "는"-------- 드라이버 프로파일을 배울 수

1.  리눅스 드라이브 학습

운전을 배우고 싶은 학생들을위한 리눅스 커널 드라이버의 수백, 및 기타 지식 포인트, 당신은 신속하게 기초를 파악 할 필요가있다 : 기본 사용 등의 개발 보드, 하드웨어 기본, 개발 환경을 구축으로, 리눅스 일반적으로 사용되는 도구, 커널 컴파일 및 프로그래밍, 리눅스 쉘 명령, C 언어 기초, 리눅스 커널 단순 절단 및 구성, 리눅스 시스템 프로그래밍 등

위의 어떤 기본 지식, 의심의 여지가, 공중에 빌드 성을 학습하지 구동된다.

리눅스 운영 체제, "공"의 동등한 프로그래머 할 필요는 볼이 어디 갈 곳에서 회전 관리 할 수없는, 특정 기능을 달성하기 위해이 영역에 드라이브를 추가합니다. 이해하기 쉽게, 아니 감독은 당신에게 같은 "바로 주변의 스티어링 휠을 돌려"과 같은 몇 가지 지침을 줄 것이다, 엔진의 원리를 설명하기 시작 것, 리눅스는 단지 도구, 차를 운전을 배우는 것처럼, 그것을 사용하는 방법을 배우게은 "스티어링 휠 왼쪽 혁명 ""핸드 브레이크 ""변화 "등이있다.

배우는 물론 가장 좋은 방법 중 리눅스 커널을 읽어이지만, 사물의 핵심을 연구하는 너무 많이 전에 근거가 없다.

리눅스 드라이버를 작동하는 임베디드 엔지니어, 드라이버는 커널 소스에 관심이 있다면 드라이브에 어떻게 이식에 배운 기술을 마스터해야 이식 후 적절한 일자리를 찾을 수 있습니다뿐만 아니라, 시간의 흑자, 당신은 좀 걸릴 수 있습니다 읽을 수있는 순수 이익을 가능한 한 커널 "아름다운"코드는하지만, 훨씬 더 직접적인 도움을 일을하지 않습니다.

2.  리눅스 디바이스 드라이버 분류

주로 지속적으로 풍부하게 드라이버 코드, 소스 코드의 길이를 증가 큰 비율의 리눅스 커널 소스 코드의 소지 리눅스 디바이스 드라이버. 지속적으로 리눅스 커널을 업그레이드 구조의 드라이버는 상대적으로 안정적이다.

자 장치 (CHAR 장치), 블록 디바이스 (블록 장치) 및 네트워크 장치 (네트워크 장치) 3 개로 리눅스 시스템 장치. 장치에 액세스 할 때 캐시되지 않은 캐릭터 장치. 쓰기 캐시 블록 장치가 지원해야하고, 장치가 랜덤 액세스 (랜덤 액세스)를 차단할 수 있어야합니다,이 요구 사항은 문자 장치가 아닙니다. 일반적인 문자 장치는 마우스, 키보드, 시리얼 포트 등을 포함한다. 하드 디스크를 플로피 디스크 장치, CD-ROM 등을 포함하여 차단 장치. 파일 시스템은 운영 체제 (산) 블록 장치를 설치한다.

네트워크 장비는 리눅스에 특별한 거래를 할 수 있습니다. 리눅스 네트워크 시스템은 주로 BSD 유닉스 소켓 메커니즘을 기반으로합니다. 그것은 시스템 사이에 형성되고, 드라이버는 데이터 전송을위한 특정 데이터 구조 (sk_buff에)을 갖는다. 데이터를 송수신하는 데이터를 캐싱에 대한 지원 시스템은 여러 프로토콜에 대한 지원을 제공하는 흐름 제어 메커니즘을 제공합니다.

3 구동 모듈의 형태로 컴파일

모듈로드 기능

로드 기능 모듈은 "module_init ()라는이 (기능)", 성공적으로 실행되면 정수 형이 0이 반환됩니다 반환합니다. 그렇지 않으면 오류 메시지를 반환합니다.

때로는 칩 업체들은 칩 기반의 소스 코드를 제공하지 않습니다 단지 드라이브 모듈 코 파일, 드라이버를로드하기 위해 호출 request_module (모듈 이름)에 대한 필요성이 시간을 제공합니다.

 

리눅스에서 _init 리눅스에서 시작하거나 초기화 모듈이로드 된 후, 메모리 용량을 초기화 기능이 _ 표시 기능, 그것은 밖으로 해제됩니다. 기능에 더하여, 데이터는 데이터 리눅스 또는 로딩 또는 모듈 초기화 후에 시작 "_ _ 데이터"로 정의 할 수 있고, 또한 방출한다. 뒷면의이 부분에 대한 지식은 점차적으로 사용할 수 있습니다.

제거 기능 모듈

모듈은 모듈이 상대적으로 쉽게 이해하기 "역 과정을"로드 언로드.

제거 기능 모듈 "module_init ()라는 (기능)"반환 값이 없음.

일반적으로, 우리는 제거 기능과로드 기능을 반대 기능을 완료 예를 들어, 시스템 또는 하드웨어 리소스, 다음 제거 함수를 호출해야합니다, 당신은 해제해야합니다.

모듈 컴파일 과정

리눅스 모듈은 일반적으로 스크립트 언어의 종류가 매우 큰, 풍부한 구문은 컴파일 스크립트 언어를 사용하지만, 우리가 사용하는 방법을 배우게 할 필요에 쓰여진로 모델링 할 수있다, 이것은 우리의 개발에 영향을주지 않습니다.

상기 흐름도 블록은 아래 컴파일.

그림은 리눅스 모듈을 컴파일하기 위해 Makefile을 호출, 컴파일러, 실행 후 make 명령으로 볼 수 있습니다.

리눅스 컴파일 된 모듈은 두 개의 라인으로 나누어 져 있습니다.

레드 라인 : 리눅스 소스 코드를 입력 아니라 헤더 파일 등의 몇 가지로 버전 정보를 문의하십시오.

이는 전체 리눅스 소스 코드 파일을 통해 라인입니다.

오렌지 라인 : 리눅스 소스 트리 정보 수집을 완료 한 후, 메이크 파일, 소스 파일, 여기 .KO 파일을 컴파일 mini_linux_module.c이 "iTop4412_Kernel_3.0"전체 소스 코드입니다 전화를 계속합니다.

그들이 원하지만,이 소스도 해당 소스 비록이 줄은 mini_linux_module.c을하고있다.

 

정보를 수집하여, 두 라인 위를 수행하여 메이크는 최종 모듈은 컴파일 .KO

여기에 우리의 초점은 커널 버전, 헤더와 관련된, 또한 사용되어야 배우고 이해, 커널 모듈 소스 코드를 컴파일하는 것입니다. 잘못된 버전의 경우, 모듈로드 및 실행할 수 없습니다 수 있으므로, 헤더 파일, 컴파일러는 통과하지 않습니다.

메이크 스크립트 파일  

는 MCU 또는 PC 프로그램에서, 우리는 개발 도구를 통합했다. 규칙 개발 도구를 프로그래머에 따라, 지정된 위치에 코드를 main.c의의가 .c 파일의 많은 보통 파일, 코드, 자동을 제공하기 위해 컴파일 된 것을 개발 도구 버튼을 작성 바이너리 파일.

리눅스에서 이러한 통합 개발 도구가없는, 또한 컴파일 된 파일 Makefile을 작성이 필요합니다.

컴파일 된 파일은 일반적으로 스크립트 수천 스크립트 언어학가 마무리 학습이 어디에 사용되는 경우 학습의 가장 좋은 스크립트를 배우고, 스크립팅을 사용한다.

메이크는 다음과 다음 "02_HelloDriverModule"을 찾기 위해 리눅스 디렉토리에있는 비디오 파일을 구동 할 수 있습니다, 다음의 서류를 컴파일합니다.

#! / 빈 / bash는

# 어떤 소스는 우리의 모듈을 컴파일하는 컴파일러를 알려줍니다

다음은이 파일은 중간 파일 mini_linux_module.o로 컴파일 # itop4412_hello.c 편집이다

OBJ-m + = mini_linux_module.o

 

사용자가 실제 상황의 경로를 선택해야합니다 # 소스 디렉토리 변수

리눅스 소스 코드의 # 디렉토리에 복사하고 /home/topeet/android4.0를 추출한다

수단 : = hometopeetandroid40iTop4412Kernel30

 

# 변수 현재 디렉토리

PWD? = $ (쉘 PWD)

 

#make 기본 명명 첫 번째 목표를 찾고

#make -C 통화 경로의 실행을 지칭

# $은 (KDIR) 리눅스 소스 코드 디렉토리, 저자는 여기 /home/topeet/android4.0/iTop4412_Kernel_3.0을 말한다

# $ (PWD) 변수 현재 디렉토리

#Modules 동작이 수행 될

모두:

        $ -C (KDIR) M = $ (PWD) 모듈을

 

#Make 청소 작업은 오 접미사 파일을 삭제하기 위해 수행된다

깨끗한:

        RF RM은 * .o 인

위와 같이, mini_linux_module 스크립트 파일을 컴파일됩니다. 각 문장의 의미의 상세한 설명.

#! / 빈 / bash는

이 스크립트를 사용하도록 컴파일러에 지시하는 스크립트 언어입니다

OBJ-m + = mini_linux_module.o

이것은 당신이 다른 파일을 컴파일하기 위해 필요한 경우, 당신은 추가 할 수 있습니다 나중에 mini_linux_module.o 파일로 변환 mini_linux_module.c 문서를 표현하려면, 표준 사용이다.

수단 : = hometopeetandroid40iTop4412Kernel30

이 버전 지원 및 헤더 파일이 부족하기 때문에 다음 모듈이 될 수 없습니다 컴파일, 어떤 커널 소스 코드가없는 경우이 줄은, 디렉토리 커널 코드를 나타냅니다. KDIR는 변수입니다.

PWD? = $ (쉘 PWD)

이 문장은 변수,이 변수에 전달 된 현재 디렉토리에 다음 경로입니다. PWD는 명령, 현재 디렉토리, PWD 변수입니다.

모두:

        $ -C (KDIR) M = $ (PWD) 모듈을

사용 "메이크업"명령 컴파일 스크립트 실행 시간, 그것은이 하나를 찾을 기본값으로, 변수는 커널 소스 디렉토리에 KDIR 경로가, -C 변수 KDIR 인 실행을 호출하는 경로를 나타냅니다합니다.

PWD는 현재 디렉토리를 나타냅니다.

모듈로 컴파일 쇼 드라이브 모듈, 생성 KO 최종 파일입니다.

깨끗한:

        RF RM은 * .o 인

소스 코드를 다시 수정 한 후, 당신이 어떤 쓸모없는 중간 파일을 제거 명령 "깨끗한을"할 수 있습니다, 여기 파일에 "O"접미사의 분명한 선택입니다.

 

#include <linux/init.h>
#include <linux/module.h>

MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Hcamal");

int hello_init(void)
{
    printk(KERN_INFO "Hello World\n");
    return 0;
}

void hello_exit(void)
{
    printk(KERN_INFO "Goodbye World\n");
}

module_init(hello_init);
module_exit(hello_exit);

그러나, C 언어 개발을 사용하여 리눅스에서 운전하고, 우리가 일반적으로 우리가 일반적으로의 libc 라이브러리를 사용하여 C 언어를 쓰기 때문에 C 언어도 다르다 쓸 수 있지만 드라이브가 프로그램의 커널에서 실행되고, 커널은하지 않습니다 라이브러리 존재과 libc, 그래서 커널 라이브러리 기능을 사용할 수 있습니다.

예를 들어, printklibc의 비교 될 수있다 printf커널에 정의 된 출력 기능입니다,하지만 때문에, 더 로거 기능 내부 파이썬 같은 느낌 printk출력이 커널 로그에 인쇄됩니다 당신이 사용할 수있는 dmesg명령보기

드라이버 코드는 드라이버가 커널 수행에로드, 하나의 진입 점과 하나 개의 출구 지점입니다 module_init함수 정의의 기능은, 위의 코드에 hello_init기능. 드라이브가 커널의 통화에서 언로드 될 때 module_exit기능 코드의 함수 정의는 위에있는 hello_exit기능.

위의 코드 드라이버가로드 될 때, 매우 명확 출력 Hello World언로드 구동 출력Goodbye World

PSS는 :  printk결과 출력 버퍼를 플래시하지 않습니다 다른 새로운 라인을 추가하거나하는

드라이버를 컴파일

make 명령으로 컴파일 할 필요가 운전 Makefile은 다음과 같습니다 :

ifneq ($(KERNELRELEASE),)

    obj-m := hello.o

else

    KERN_DIR ?= /usr/src/linux-headers-$(shell uname -r)/
    PWD := $(shell pwd)

default:
    $(MAKE) -C $(KERN_DIR) M=$(PWD) modules

endif


clean:
    rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions

정상적인 상황에서는, 커널 소스 코드 및 존재하는 /usr/src/linux-headers-$(shell uname -r)/디렉토리를

예를 들면 :

$ uname -r
4.4.0-135-generic

/usr/src/linux-headers-4.4.0-135/  --> 该内核源码目录
/usr/src/linux-headers-4.4.0-135-generic/    --> 该内核编译好的源码目录

그리고 우리가 필요로 컴파일 후 좋은 소스 디렉토리 인이다/usr/src/linux-headers-4.4.0-135-generic/

헤더 코드는 디렉토리 검색에서 구동 될 필요가

M=$(PWD)이 매개 변수는 현재 디렉토리에 드라이브 출력 컴파일 결과를 나타냅니다

마지막으로, 명령 obj-m := hello.o을 나타냅니다 hello.o컴파일 hello.ko이 파일을 커널 모듈 파일은 코입니다

커널에 드라이버를로드

당신은 몇 가지 시스템 명령을 사용합니다 :

  • lsmod: 현재 커널 모듈이로드보기
  • insmod: 커널 모듈을로드, 당신은 루트 권한이 필요합니다
  • rmmod: 제거 모듈

예를 들면 :

# insmod hello.ko        // 把hello.ko模块加载到内核中
# rmmod hello            // 把hello模块从内核中移除

 

지식 포인트 1 - 드라이버 분류

세 가지 카테고리, 문자 장치, 네트워크 인터페이스 장치 및 인터페이스 블록으로 분할 드라이브, 상기 코드의 예를 들면 문자 장치이고, 다른 둘은 다음 반복한다.

도에 위에서 도시 된 바와 같이 brw-rw----권한 필드 (B)는 블록 장치 (차단)의 개시는, (C)는 자 디바이스의 시작 (숯)을 나타낸다 나타낸다

지식 포인트 2 - 메이저와 마이너 번호

번호는 일반적으로 드라이버 제어와 같은 주 번호로 표시 메인 드라이브를 구별하는 데 사용됩니다.

드라이버는 구분하기 위해 약간의 번호로 여러 장치를 만들 수 있습니다.

메인 및 보조 번호는 함께 구동 장치를 확인합니다.

도에 도시 된 바와 같이.

brw-rw----  1 root disk      8,   0 Dec 17 13:02 sda
brw-rw----  1 root disk      8,   1 Dec 17 13:02 sda1

장치 sdasda1메인 수가 하나 개의 이러한 번호는이 번호 1 0이고, 8

지식 포인트 3 - 드라이버 API의의를 제공하는 방법입니다

내 개념에서, 인터페이스 드라이브가 제공되는 /dev/xxx리눅스에서, Everything is File장치의 작동이 실제로 파일을 조작하는 구동 있도록 드라이버를 정의하는 데 사용됩니다, 그래서, 개방 / 읽기 / 쓰기 / ... /dev/xxx무엇이 일어날 것, API는 파일 작업의 일련의를 제공하기 위해 구동된다.

어떤 파일 작업? 이들은 커널에서 정의된다 <linux/fs.h>[5] 헤더 파일, file_operations구조

내 예에서 위의 코드 :

struct file_operations scull_fops = {
    .owner =    THIS_MODULE,
    .llseek =   scull_llseek,
    .read =     scull_read,
    .write =    scull_write,
    .open =     scull_open,
    .release =  scull_release,
};

나는 선언뿐만 아니라 구조, 할당하고, 그 owner함수 포인터의 모든의 값이 다른 회원들

내 한 scull_setup_cdev기능을 사용 cdev_add하여 파일 작업 구조를 등록, 각 드라이브 장치에

예를 들어, I는 동작을 수행하기 위해 구동 장치를 열고, 그것을 수행하기 위해 갈 scull_open시스템 호출 후크 동등한 기능 open함수

기술 -4- 일 - / DEV에서 해당 디바이스를 형성

위의 코드를주고 scull.ko, 다음에 서명하기 위해 컴파일 중 마지막으로 사용 된 insmod커널에로드 할

성공적으로로드 있는지 확인하려면 lsmod를을

 

드라이버가 성공적으로로드되었지만, / dev에 디렉토리에 장치 파일을 생성하지 않지만, 우리는 수동으로 사용해야하는 mknod장치 링크

 

 

참조 :

https://paper.seebug.org/779/

https://www.oschina.net/question/2371345_2186010

 

게시 26 개 원래 기사 · 원의 찬양 (34) ·은 90000 +를 볼

추천

출처blog.csdn.net/qq_36662437/article/details/98218434