Linux 중급 - '드라이버' 하드웨어 제어를 위해 배워야 하는 낮은 수준의 지식

WBOY
풀어 주다: 2024-02-12 15:21:13
앞으로
1245명이 탐색했습니다.
Linux中级——“驱动” 控制硬件必须学会的底层知识

인식 제고

1. 드라이버란 무엇인가

드라이버는 기본 하드웨어 장치의 작동을 캡슐화하고 상위 계층에 기능 인터페이스를 제공합니다.

장치 분류: Linux 시스템은 장치를 문자 장치, 블록 장치 및 네트워크 장치의 3가지 범주로 나눕니다.

  • 문자 장치: 바이트 단위로만 읽고 쓸 수 있는 장치를 말합니다. 장치 메모리에 있는 특정 데이터를 임의로 읽을 수는 없습니다. 데이터를 순서대로 읽어야 합니다. 문자 장치는 스트림 지향 장치입니다. 일반적인 문자 장치에는 마우스, 키보드, 직렬 포트, 콘솔 및 LED 장치가 포함됩니다. 문자 장치 드라이버는 일반적으로 최소한 열기, 닫기, 읽기 및 쓰기, 문자 터미널 시스템 호출을 구현합니다. (/dev/console) 및 직렬 포트(/dev/ttyS0 및 유사한 장치)는 "스트림"이라는 추상적인 개념을 잘 설명할 수 있는 두 개의 문자 장치입니다.
  • 블록 장치: 장치의 어느 위치에서나 특정 길이의 데이터를 읽을 수 있는 장치를 말합니다. 블록 장치에는 하드 드라이브, 디스크, USB 플래시 드라이브, SD 카드 등이 포함됩니다.
  • 네트워크 장치: 네트워크 장치는 네트워크 카드와 같은 하드웨어 장치일 수도 있지만 루프백 인터페이스(lo)와 같은 순수한 소프트웨어 장치일 수도 있습니다. . Linux中级——“驱动” 控制硬件必须学会的底层知识

전체 통화 과정을 설명하기 위해 예를 들어보겠습니다

  1. 상위 계층에서는 C 언어 열기 함수 open("/dev/pin4",O_RDWR);를 호출하고 /dev 아래의 pin4를 호출하여 읽기 및 쓰기 가능한 방식으로 엽니다. **== 상위 계층 열기가 커널에 호출되면 소프트 인터럽트가 발생합니다. 인터럽트 번호는 0X80으로, 커널 공간==**
  2. 에서 입력됩니다.
  3. open은 system_call(커널 기능)을 호출하고 system_call은 /dev/pin4 장치 이름을 기반으로 원하는 장치 번호를 찾습니다.
  4. 그런 다음 가상 파일 VFS로 조정합니다(상위 계층 호출을 위한 정확한 하드웨어를 통합하기 위해 ). VFS에서 sys_open를 호출하면 sys_open이 드라이버 목록에서 발견되고 를 기반으로 드라이버를 찾습니다. 메이저 장치 번호와 마이너 장치 번호 4번 핀의 오픈 기능은 4번 핀의 오픈 기능은 레지스터를 동작시키는 것입니다

여기에 이미지 설명을 삽입하세요

드라이버를 작성할 때 우리는 드라이버 추가: 드라이버 추가는 무엇을 합니까?

  1. 기기 이름
  2. 기기번호
  3. 장치 드라이버 기능(IO 포트를 구동하기 위한 작동 레지스터)

==요약== dev 아래pin4 핀, 프로세스는 다음과 같습니다: dev下面的pin4引脚,过程是:用户态调用open“/de/pin4”,O_RDWR),对于内核来说,上层调用open函数会触发一个软中断(系统调用专用,中断号是0x80,0x80代表发生了一个系统调用),系统进入内核态,并走到system_call,可以认为这个就是此软中断的中断服务程序入口,然后通过传递过来的系统调用号来决定调用相应的系统调用服务程序(在这里是调用VFS中的sys_open)。sys_open会在内核的驱动链表里面根据设备名和设备号查找到相关的驱动函数每一个驱动函数是一个节点사용자 모드 호출 열기

("/de/pin4",O_RDWR), 커널용 예를 들어, 상위 계층에서 open 함수를 호출하면 소프트 인터럽트가 발생합니다(시스템 호출의 경우 특별하며 인터럽트 번호는 0x80, 0x80은 시스템 호출이 발생했음을 의미함).

시스템이 커널 상태로 진입하고 system_call, 이렇게 생각하시면 됩니다. 소프트 인터럽트의 인터럽트 서비스 프로그램에 진입한 후, 전달된 시스템 콜 번호(여기서는 <code style="font-size: 14px;padding: VFS에서 2px 4px ;border-radius: 4px;margin: 0 2px;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;color: #10f5d6c">sys_open ). sys_open는 장치 이름과 장치 번호(<code style="font-size: 14px;padding: 2px 4px; border-radius: 4px; margin: 0 2px ; Font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;color: #10f5d6c">각 드라이버 함수는 노드입니다), **==드라이버 함수에는 레지스터를 통해 IO 포트를 제어하기 위한 코드가 포함되어 있습니다. 그런 다음 IO 포트를 제어하여 관련 기능 ==**을 구현할 수 있습니다.

2. 각 구성요소에 대한 자세한 설명

사용자 프로필:

  • 사용자가 프로그램을 작성하고 프로그램을 실행하는 수준을 말합니다. 사용자 모드는 개발 중에 C 및 C 라이브러리에 대한 기초가 필요합니다. C 라이브러리에서는 파일, 프로세스, 프로세스 간 통신, 스레드, 네트워크 및 인터페이스( GTk)open,read,write,fork,pthread,socket. C 라이브러리(Linux 표준 라이브러리에 포함되어야 함): 커널 작업을 제어하기 위한 프로그램용 인터페이스를 제공하는 Clibary입니다. 호출 은 여기에 캡슐화되어 구현되며 작성된 애플리케이션에 의해 호출됩니다.
  • C 라이브러리의 다양한 API 커널이 작동하도록 제어하는 ​​커널 상태를 호출합니다
.

커널 상태:

🎜”🎜🎜
  • 사용자가 특정 하드웨어 장치를 사용하려면 커널 모드 장치 드라이버가 필요하고,하드웨어가 작동하도록 구동합니다. 이전 기사wiringPi库에서 언급했듯이 사용자가 하드웨어 장치를 제어할 수 있는 인터페이스를 제공합니다 , WiringPi 라이브러리가 없으면 WiringPi 라이브러리의 기능을 직접 구현해야 합니다. 즉, 장치 드라이버를 직접 작성해야 합니다. 이런 식으로 다른 유형의 보드를 얻으면 개발을 완료할 수도 있습니다.

  • 리눅스의 모든 것은 파일입니다 모든 종류의 파일과 장치(예: 아래 그림과 같이 마우스, 키보드, 화면, 플래시, 메모리, 네트워크 카드)는 모두 파일이므로파일입니다. 파일 작업 기능을 사용하여 이러한 장치를 작동할 수 있습니다 . Linux中级——“驱动” 控制硬件必须学会的底层知识

  • 질문이 있습니다. 열기, 읽기 등의 파일 작업 기능은 열린 파일이 어떤 하드웨어 장치인지 어떻게 알 수 있나요? open 함수에 해당 파일명을 입력하면 해당 기기를 제어할 수 있습니다. ②패스 ==장치번호(주장치번호, 부장치번호)==. 또한 이러한 드라이버의 위치와 구현 방법도 이해해야 합니다. 각 하드웨어 장치는 서로 다른 드라이버에 해당합니다(이러한 드라이버는 자체적으로 구현됩니다).

  • Linux 장치 관리는 파일 시스템과 긴밀하게 통합되어 있습니다. 다양한 장치는 ==device files==*라는 파일 형식으로 /dev 디렉터리에 저장됩니다. 애플리케이션은 이러한 장치 파일을 열고, 닫고, 읽고 쓸 수 있으며 일반 데이터 파일을 작동하는 것처럼 장치에서 작업을 완료할 수 있습니다. **이러한 장치를 관리하기 위해 시스템은 장치에 번호를 매깁니다**,*각 장치 번호는 ==주 장치 번호== 및 ==부 장치 번호==*로 구분됩니다(아래 그림 참조). ). **Linux中级——“驱动” 控制硬件必须学会的底层知识***주 장치 번호**는 서로 다른 유형의 장치를 구분하는 데 사용되며, **부 장치 번호는 동일한 유형의 여러 장치를 구분하는 데 사용됩니다. 일반적으로 사용되는 장치의 경우 Linux에는 일반적인 숫자가 있습니다. 예를 들어 하드 디스크의 주요 장치 번호는 3입니다. ****문자 디바이스 또는 블록 디바이스에는 메이저 디바이스 번호와 마이너 디바이스 번호가 있습니다. ==주 장치 번호와 부 장치 번호를 합쳐서 장치 번호라고 합니다==**.

    주요 장치 번호는 특정 드라이버를 나타내는 데 사용됩니다.
    부 장치 번호는 이 드라이버를 사용하는 각 장치를 나타내는 데 사용됩니다.

    예를 들어 임베디드 시스템에는 두 개의 LED 표시기가 있으며 LED 조명은 독립적으로 켜거나 꺼야 합니다. 그런 다음 LED 조명용 문자 장치 드라이버를 작성하고 주 장치 번호를 장치 번호 5로 등록하고 부 장치 번호를 각각 1과 2로 등록하면 됩니다. 여기서 보조 장치 번호는 각각 두 개의 LED 조명을 나타냅니다.

==운전자 연결 목록==

모든 장치의 드라이버 관리, 추가 또는 찾기
추가添加是发生在我们编写完驱动程序,加载到内核
查找는 드라이버 작성을 마치고 커널에 로드한 후에 발생합니다. 찾기

는 드라이버를 호출하고 있으며 애플리케이션 계층 사용자 공간은 이를 찾기 위해 open 함수를 사용합니다

. 링크된 목록에 드라이버가 삽입되는 순서는 장치 번호로 검색됩니다. 즉, 주 장치 번호와 부 장치 번호는 다른 유형의 장치와 다른 유형의 장치를 구분할 수 있을 뿐만 아니라 아래에 소개된 드라이버 코드의 개발은 드라이버 추가(장치 번호, 장치 이름 및 장치 드라이버 기능 추가)와

호출에 지나지 않습니다. 운전사

.

  • system_call 함수는 어떻게 상세한 시스템 콜 서비스 루틴을 찾아내나요? 시스템 호출 테이블 sys_call_table을 시스템 호출 번호로 찾아보세요! 소프트 인터럽트 명령 INT 0x80이 실행되면 시스템 호출 번호는 eax 레지스터
  • 에 배치됩니다. system_call 함수는 eax 레지스터를 읽어 이를 얻은 다음 4를 곱하여 오프셋 주소를 생성할 수 있습니다. sys_call_table을 기본 주소로 사용합니다. 오프셋 주소에 기본 주소를 더하면 상세한 시스템 콜 서비스 루틴의 주소를 얻을 수 있습니다! 그런 다음 시스템 서비스 루틴을 호출할 차례입니다.

추가됨:
  1. 각 시스템 호출은 시스템 호출 번호에 해당하며 시스템 호출 번호는 커널의 해당 처리 기능에 해당합니다.
  2. 모든 시스템 호출은 인터럽트 0x80을 통해 트리거됩니다.
  3. 시스템 호출을 사용할 때 시스템 호출 번호는 eax 레지스터를 통해 커널에 전달되고, 시스템 호출의 입력 매개변수는 ebx, ecx...를 통해 차례로 커널에 전달됩니다
  4. 함수와 마찬가지로 시스템 호출의 반환 값은 eax에 저장되며 모두 eax

에서 가져와야 합니다.

3. 캐릭터 장치 드라이버의 작동 원리

문자 장치 드라이버 작동 원리 Linux 세계에서는 모든 것이 파일이며 모든 하드웨어 장치 작업은 애플리케이션 계층에서 파일 작업으로 추상화됩니다. 애플리케이션 계층이 하드웨어 장치에 액세스하려면 하드웨어에 해당하는 드라이버를 호출해야 한다는 것을 알고 있습니다. Linux 커널에는 드라이버가 너무 많습니다. 애플리케이션이 기본 드라이버를 어떻게 정확하게 호출할 수 있습니까?

==꼭 알아야 할 지식:==🎜🎜
  1. Linux 파일 시스템에서 각 파일은 struct inode 구조로 설명됩니다. 이 구조는 파일 형식, 액세스 권한 등과 같은 파일의 모든 정보를 기록합니다.
  2. Linux 운영 체제에서 각 드라이버는 애플리케이션 계층의 /dev目录或者其他如/sys 디렉터리에 해당 파일을 갖습니다.
  3. Linux 운영 체제에서는 각 드라이버에 장치 번호가 있습니다.
  4. Linux 운영 체제에서 파일이 열릴 때마다 Linux 운영 체제는 열린 파일을 설명하기 위해 VFS 계층에 ****struct file구조를 할당합니다.
Linux中级——“驱动” 控制硬件必须学会的底层知识

(1) open 함수가 디바이스 파일을 열면 해당 디바이스 파일에 해당하는 struct inode 구조에 기술된 정보를 기반으로 다음에 동작할 디바이스의 타입(캐릭터 디바이스 또는 블록 디바이스)을 알 수 있으며, 파일 구조도 할당됩니다.

(2) 구조체 inode 구조에 기록된 장치 번호에 따라 해당 드라이버를 찾을 수 있습니다. 여기서는 문자 장치를 예로 들어보겠습니다. Linux 운영 체제에서 각 문자 장치에는 struct cdev 구조가 있습니다. 이 구조는 캐릭터 디바이스의 모든 정보를 기술하며, 그 중 가장 중요한 것은 캐릭터 디바이스의 동작 기능 인터페이스이다.

(3) struct cdev 구조를 찾은 후 Linux 커널은 struct cdev 구조가 위치한 메모리 공간의 첫 번째 주소를 struct inode 구조의 i_cdev 멤버에 기록하고, struct cdev 구조. struct 파일 구조의 f_ops 멤버에 있습니다.

(4) 작업이 완료되면 VFS 계층은 파일 설명자(fd)를 애플리케이션에 반환합니다. 이 fd는 구조체 파일 구조에 해당합니다. 다음으로 상위 계층 응용 프로그램은 fd를 통해 구조체 파일을 찾은 다음 구조체 파일에서 문자 장치를 작동하기 위한 함수 인터페이스 file_Operation을 찾을 수 있습니다.

그 중 cdev_init와 cdev_add는 드라이버의 진입 함수에서 호출되어 각각 문자 장치와 file_Operation 함수 작업 인터페이스의 바인딩을 완료하고 문자 드라이버를 커널에 등록했습니다.

프레임워크를 기반으로 드라이버 코드 작성:

  • 상위계층 호출 코드 : 연산 구동 상위계층 코드(pin4test.c) :
아아아아

-커널 드라이버 **==가장 간단한 문자 장치 드라이버 프레임워크==**:

문자 장치 드라이버 프레임워크 코드

으아아아

수동으로 장치 이름 만들기

  • 위의 문자 장치 드라이버 코드에는 이 코드를 통해 dev에서 장치를 자동으로 생성할 수 있습니다또한 장치 이름을 수동으로 생성할 수도 있습니다. 지침: sudo mknod +设备名字 +设备类型(c表示字符设备驱动) +主设备号+次设备号 b: 블록(버퍼) 특수 파일을 만듭니다. c, u: 버퍼링되지 않은 문자 특수 파일을 만듭니다. p: FIFO를 생성합니다. 수동으로 생성된 장치 이름을 삭제하려면 rm만 하면 됩니다. 아래 그림과 같이:

드라이버 프레임워크 실행 프로세스:

  • 상위 계층 프로그램을 통해 장치를 엽니다. 드라이버가 없으면 실행 시 오류가 보고됩니다. 커널 드라이버에서는 상위 계층 시스템 호출 , sys_open 및 sys_write가 open,wirte函数会触发sys_call、sys_call会调用sys_open,sys_write주요 장치 번호를 전달합니다. 그리고 커널의 드라이버 목록에 장치를 넣고 드라이버를 찾아 열기를 실행한 뒤 내부에 쓰기를 하게 되면 먼저 드라이버(장치 드라이버 파일)를 준비해야 합니다.

  • 장치 드라이버 파일에는 고정된 프레임이 있습니다:

    1. module_init(pin4_drv_init); //入口 去调用 pin4_drv_init기능
    2. int __init pin4_drv_init(void) //실제 운전자 입장
    3. 운전기사 입장devno = MKDEV(major,minor); // 장치 번호 생성
    4. register_chrdev(major, module_name,&pin4_fops); //드라이버를 등록하고 위에서 준비한 구조를 커널 드라이버의 연결 목록에 추가하도록 커널에 지시합니다
    5. pin4_class=class_create(THIS_MODULE,"myfirstdemo");//dev에서 코드로 장치를 자동으로 생성하고 클래스를 생성합니다
    6. pin4_class_dev =device_create(pin4_class,NULL,devno,NULL,module_name); //디바이스 파일을 생성합니다.
    7. 가장 중요한 것은 /dev상위 레이어를 열 수 있는 추가 파일
    8. 을 만드는 것입니다.
    9. 그렇지 않은 경우 수동으로 장치를 생성할 수도 있습니다sudo mknod +设备名字 +设备类型(c表示字符设备驱动) +主设备号+次设备号

드라이버 모듈 코드 컴파일

드라이버 모듈 코드 컴파일

드라이브 모듈 코드 컴파일(모듈 컴파일에는 구성된 커널 소스 코드가 필요합니다. 컴파일 및 연결 후 생성된 커널 모듈의 접미사는 **.ko입니다. 컴파일 프로세스는 먼저 커널 소스 코드 디렉터리로 이동하여 최상위 레벨을 읽습니다. Makefile 파일을 만든 다음 모듈 소스 코드가 있는 디렉터리로 돌아갑니다. **

.
  • 使用下面的的代码:(就是上面的驱动架构代码)
#include             //file_operations声明
#include     //module_init  module_exit声明
#include       //__init  __exit 宏定义声明
#include         //class  devise声明
#include    //copy_from_user 的头文件
#include      //设备号  dev_t 类型声明
#include           //ioremap iounmap的头文件


static struct class *pin4_class;
static struct device *pin4_class_dev;

static dev_t devno;                //设备号
static int major =231;                     //主设备号
static int minor =0;                       //次设备号
static char *module_name="pin4";   //模块名

//led_open函数
static int pin4_open(struct inode *inode,struct file *file)
{
        printk("pin4_open\n");  //内核的打印函数和printf类似

        return 0;
}
//read函数
static int pin4_read(struct file *file,char __user *buf,size_t count,loff_t *ppos)
{
        printk("pin4_read\n");  //内核的打印函数和printf类似

        return 0;
}

//led_write函数
static ssize_t pin4_write(struct file *file,const char __user *buf,size_t count, loff_t *ppos)
{

        printk("pin4_write\n");  //内核的打印函数和printf类似
        return 0;
}

static struct file_operations pin4_fops = {

        .owner = THIS_MODULE,
        .open  = pin4_open,
        .write = pin4_write,
        .read  = pin4_read,
};
//static限定这个结构体的作用,仅仅只在这个文件。
int __init pin4_drv_init(void)   //真实的驱动入口
{

        int ret;
        devno = MKDEV(major,minor);  //创建设备号
  ret   = register_chrdev(major, module_name,&pin4_fops);  //注册驱动  告诉内核,把这个驱动加入到内核驱动的链表中

        pin4_class=class_create(THIS_MODULE,"myfirstdemo");//让代码在dev下自动>生成设备
        pin4_class_dev =device_create(pin4_class,NULL,devno,NULL,module_name);  //创建设备文件


        return 0;
}

void __exit pin4_drv_exit(void)
{

        device_destroy(pin4_class,devno);
        class_destroy(pin4_class);
        unregister_chrdev(major, module_name);  //卸载驱动
}
module_init(pin4_drv_init);  //入口,内核加载驱动的时候,这个宏会被调用,去调用pin4_drv_init这个函数
module_exit(pin4_drv_exit);
MODULE_LICENSE("GPL v2");
로그인 후 복사
  • 在导入虚拟机的内核代码中找到字符设备驱动的那一个文件夹:/SYSTEM/linux-rpi-4.19.y/drivers/char将以上代码复制到一个文件中,然后下一步要做的是就是:将上面的驱动代码编译生成模块,再修改Makefile。(你放那个文件下,就改哪个文件下的Makefile)
  • 文件内容如下图所示:(-y表示编译进内核,-m表示生成驱动模块,CONFIG_表示是根据config生成的) 所以只需要将obj-m += pin4drive.o添加到Makefile中即可。下图:Makefile文件图Linux中级——“驱动” 控制硬件必须学会的底层知识
  • 编译生成驱动模块,将生成的**.ko文件发送给树莓派**然后回/SYSTEM/linux-rpi-4.19.y下使用指令:ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make modules进行编译生成驱动模块。然后将生成的.ko文件发送给树莓派:scp drivers/char/pin4driver.ko pi@192.168.0.104:/home/pi编译生成驱动模块会生成以下几个文件:Linux中级——“驱动” 控制硬件必须学会的底层知识
  • .o的文件是object文件,.ko是kernel object,与.o的区别在于其多了一些sections,比如.modinfo.modinfo section是由kernel source里的modpost工具生成的, 包括MODULE_AUTHOR, MODULE_DESCRIPTION, MODULE_LICENSE, device ID table以及模块依赖关系等等。depmod 工具根据.modinfo section生成modules.dep, modules.*map等文件,以便modprobe更方便的加载模块。

  • 컴파일 과정에서 우리는 다음 단계를 거쳤습니다:
  1. 먼저 Linux 커널이 있는 디렉터리로 들어가서 pin4drive.o 파일을 컴파일하세요
  2. MODPOST를 실행하면 임시 pin4drive.mod.c 파일이 생성된 다음 이 파일을 기반으로 pin4drive.mod.o를 컴파일합니다.
  3. 그런 다음 pin4drive.o 및 pin4drive.mod.o 파일을 연결하여 모듈 대상 파일 pin4drive.ko를 가져옵니다.
  4. 마지막으로 Linux 커널이 있는 디렉터리를 그대로 둡니다.

크로스 컴파일 pin4test.c(상위 계층 호출 코드)를 실행하여 Raspberry Pi로 전송하면 아래 그림과 같이 pi 디렉터리 아래에 두 개의 파일이 전송되는 것을 볼 수 있습니다. .ko文件pin4test Linux中级——“驱动” 控制硬件必须学会的底层知识

커널 드라이버 로드

그런 다음 다음 명령을 사용합니다.

장치 드라이버(이것은 코드 줄과 관련됨 static char *module_name=”pin4″; //드라이버 코드의 모듈 이름), 장치 번호도 코드와 관련됩니다.

sudo insmod pin4drive.ko加载内核驱动(相当于通过insmod调用了module_init这个宏,然后将整个结构体加载到驱动链表中) 加载完成后就可以在dev下面看到名字为pin4

드라이버가 설치되었는지 확인할 수 있습니다.

lsmod

    그런 다음 ./pin4test를 실행하여 상위 수준 코드를 실행합니다.
  • 상위 수준 코드를 실행할 때 다음 오류가 발생합니다. 이는 권한이 없음을 의미합니다. 다음 명령을 사용하세요. 모든 사람이 성공적으로 열 수 있도록 pin4에 권한을 부여하세요. . Linux中级——“驱动” 控制硬件必须学会的底层知识sudo chmod 666 /dev/pin4
  • 그런 다음 다시 실행pin4test표면적으로는 정보 출력이 없습니다. 실제로 커널에 인쇄 정보가 있지만 상위 계층에서는 볼 수 없습니다. 커널에서 인쇄된 정보를 보려면 , 다음 명령을 사용할 수 있습니다. dmesg |grep pin4. 아래 그림과 같이 드라이버 호출이 성공했음을 의미합니다

pin4test表面上看没有任何信息输出,其实内核里面有打印信息只是上层看不到如果想要查看内核打印的信息可以使用指令:dmesg |grep pin4드라이버를 설치한 후 다음 명령을 사용하여

(ko를 쓸 필요 없음) 드라이버를 제거할 수 있습니다. Linux中级——“驱动” 控制硬件必须学会的底层知识

생성된 드라이버 모듈을 가상 머신에서 생성해야 하는 이유

  • 생성된 드라이버 모듈을 가상머신에서 생성해야 하는 이유는 무엇인가요? 라즈베리파이는 작동하지 않나요?

    드라이버 모듈을 생성하려면 컴파일 환경이 필요합니다(Linux 소스 코드 및 컴파일, 시스템 버전과 동일한 Linux 커널 소스 코드를 다운로드해야 함). Raspberry Pi에서도 컴파일할 수 있지만 컴파일은 Raspberry Pi는 매우 비효율적이며 매우 오랜 시간이 걸립니다 . 이 문서에서는 Raspberry Pi 드라이버의 로컬 컴파일에 대해 설명합니다.

위 내용은 Linux 중급 - '드라이버' 하드웨어 제어를 위해 배워야 하는 낮은 수준의 지식의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:lxlinux.net
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿
회사 소개 부인 성명 Sitemap
PHP 중국어 웹사이트:공공복지 온라인 PHP 교육,PHP 학습자의 빠른 성장을 도와주세요!