목차
模板" >模板
IO多路复用的实现" >IO多路复用的实现
模板" >模板
其他API" >其他API
시스템 튜토리얼 리눅스 Linux 드라이버 기술 상세 설명(5)_장치 차단/비차단 읽기 및 쓰기

Linux 드라이버 기술 상세 설명(5)_장치 차단/비차단 읽기 및 쓰기

Feb 15, 2024 pm 04:00 PM
linux 리눅스 튜토리얼 리눅스 시스템 리눅스 명령 쉘 스크립트 typedef overflow 임베디드리눅스 리눅스 시작하기 리눅스 학습

Linux 드라이버를 작성하는 과정에서 장치 차단/비차단 읽기 및 쓰기는 매우 중요한 기술입니다. 효율적인 데이터 전송 및 이벤트 처리를 달성하여 시스템 성능과 응답 속도를 향상시킬 수 있습니다. 이번 글에서는 리눅스 드라이버 기술(5)_장치 차단/비차단 읽기 및 쓰기 구현 원리와 관련 기술에 대해 알아보겠습니다.

详解Linux驱动技术(五) _设备阻塞/非阻塞读写

대기 대기열은 프로세스 예약을 위한 커널의 매우 중요한 데이터 구조입니다. 연결 목록의 각 노드는 PCB(프로세스 제어 블록)입니다. 대기 대기열의 모든 프로세스는 특정 깨우기 조건이 발생할 때까지 잠자기 상태로 예약됩니다. Linux I/O 다중화 기사에서 애플리케이션 계층에서 차단 IO 및 비차단 IO 사용에 대해 이미 논의했습니다. 이 기사에서는 드라이버에서 장치 IO의 차단 및 비차단 읽기 및 쓰기를 구현하는 방법을 주로 설명합니다. 분명히 이 차단 관련 메커니즘을 구현하려면 대기 대기열 메커니즘이 필요합니다. 이 글의 커널 소스 코드는 버전 3.14.0을 사용합니다.

IO 차단 장치 구현

장치 파일의 IO를 읽고 쓸 때 드라이버의 해당 인터페이스가 결국 호출되고 이러한

인터페이스는 읽기 및 쓰기 장치 프로세스의 프로세스(커널) 공간에도 나타납니다. 조건이 충족되지 않으면 인터페이스 기능으로 인해 프로세스가 절전 상태로 전환됩니다. 장치를 읽고 쓰는 사용자 프로세스가 절전 모드에 들어가더라도 흔히 차단된다고 말하는 것입니다. 한마디로, 장치 파일 읽기 및 쓰기 차단의 본질은 드라이버가 장치 파일 차단을 드라이버에서 구현한다는 것입니다. 읽기 및 쓰기 프로세스는 다음과 같이 요약할 수 있습니다.

1. 정의 - 대기 대기열 헤드 초기화 으아악

위 옵션 중 마지막 옵션은 대기 헤더를 직접 정의하고 초기화하지만, 전역 변수를 사용하여 모듈 내에서 매개변수를 전달하는 경우 필요에 따라 어떤 것을 사용할지 불편합니다.

소스 코드를 추적하고 위 줄의 기능을 확인할 수 있습니다.
으아악

wait_queue_head_t –36–>이 대기열에서 사용하는 스핀 잠금
–27–>전체 대기열을 함께 "연결"하는 링크

그런 다음 초기화 매크로를 살펴보겠습니다.

으아악

DECLARE_WAIT_QUEUE_HEAD() –60–>수신 문자열 이름을 기반으로 name이라는 대기 대기열 헤드를 생성합니다
–57–>위 task_list 필드를 초기화하기 위해 커널 표준 초기화 매크로가 사용되지 않습니다. . .

2. 이 프로세스를 대기 대기열에 추가하세요

대기 대기열에 이벤트를 추가합니다. 즉, 프로세스는 절전 상태에 들어가고 조건이 true가 될 때까지 반환되지 않습니다. **_interruptible

버전은 절전 모드가 중단될 수 있음을 의미하고, _timeout** 버전은 시간 초과 후 반환되는 시간 초과 버전을 의미하며 이 명명 규칙은 커널 API의 모든 곳에서 볼 수 있습니다. 으아악

대기줄의 핵심입니다. 살펴보겠습니다

wait_event
└── wait_event
└──
_wait_event
├── abort_exclusive_wait
├── finish_wait
├── prepare_to_wait_event
└── ___wait_is_interruptible

244 #define wait_event(wq, condition)                                       \
245 do {                                                                    \
246         if (condition)                                                  \
247                 break;                                                  \
248         __wait_event(wq, condition);                                    \ 
249 } while (0)
로그인 후 복사

wait_event
–246–>如果condition为真,立即返回
–248–>否则调用__wait_event

194 #define ___wait_event(wq, condition, state, exclusive, ret, cmd)        \       
195 ({                                                                      \
206         for (;;) {                                                      \
207                 long __int = prepare_to_wait_event(&wq, &__wait, state);\
208                                                                         \  
209                 if (condition)                                          \       
210                         break;                                          \
212                 if (___wait_is_interruptible(state) && __int) {         \
213                         __ret = __int;                                  \
214                         if (exclusive) {                                \
215                                 abort_exclusive_wait(&wq, &__wait,      \
216                                                      state, NULL);      \
217                                 goto __out;                             \
218                         }                                               \
219                         break;                                          \
220                 }                                                       \
222                 cmd;                                                    \
223         }                                                               \
224         finish_wait(&wq, &__wait);                                      \
225 __out:  __ret;                                                          \
226 })
로그인 후 복사

___wait_event
–206–>死循环的轮询
–209–>如果条件为真,跳出循环,执行finish_wait();进程被唤醒
–212–>如果进程睡眠的方式是interruptible的,那么当中断来的时候也会abort_exclusive_wait被唤醒
–222–>如果上面两条都不满足,就会回调传入的schedule(),即继续睡眠

模板

struct wait_queue_head_t xj_waitq_h;
static ssize_t demo_read(struct file *filp, char __user *buf, size_t size, loff_t *offset)
{
    if(!condition)    //条件可以在中断处理函数中置位
        wait_event_interruptible(&xj_waitq_h,condition);
}
static file_operations fops = {
    .read = demo_read,
};
static __init demo_init(void)
{
    init_waitqueue_head(&xj_waitq_h);
}
로그인 후 복사

IO多路复用的实现

对于普通的非阻塞IO,我们只需要在驱动中注册的read/write接口时不使用阻塞机制即可,这里我要讨论的是IO多路复用,即当驱动中的read/write并没有实现阻塞机制的时候,我们如何利用内核机制来在驱动中实现对IO多路复用的支持。下面这个就是我们要用的API

int poll(struct file *filep, poll_table *wait);
void poll_wait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p)  
로그인 후 복사

当应用层调用select/poll/epoll机制的时候,内核其实会遍历回调相关文件的驱动中的poll接口,通过每一个驱动的poll接口的返回值,来判断该文件IO是否有相应的事件发生,我们知道,这三种IO多路复用的机制的核心区别在于内核中管理监视文件的方式,分别是数组链表,但对于每一个驱动,回调的接口都是poll。

模板

struct wait_queue_head_t waitq_h;
static unsigned int demo_poll(struct file *filp, struct poll_table_struct *pts)
{
    unsigned int mask = 0;
    poll_wait(filp, &wwaitq_h, pts);
    if(counter){
        mask = (POLLIN | POLLRDNORM);
    }
    return mask;
}

static struct file_operations fops = {
    .owner  = THIS_MODULE,
    .poll   = demo_poll,
};
static __init demo_init(void)
{
    init_waitqueue_head(&xj_waitq_h);
}
로그인 후 복사

其他API

刚才我们讨论了如何使用等待队列实现阻塞IO,非阻塞IO,其实关于等待队列,内核还提供了很多其他API用以完成相关的操作,这里我们来认识一下

//在等待队列上睡眠
sleep_on(wait_queue_head_t *wqueue_h);
sleep_on_interruptible(wait_queue_head_t *wqueue_h);

//唤醒等待的进程
void wake_up(wait_queue_t *wqueue);
void wake_up_interruptible(wait_queue_t *wqueue);
로그인 후 복사

总之,设备阻塞/非阻塞读写是Linux驱动程序编写过程中不可或缺的一部分。它可以实现高效的数据传输和事件处理,提高系统的性能和响应速度。希望本文能够帮助读者更好地理解Linux驱动技术(五) _设备阻塞/非阻塞读写的实现原理和相关技术。

위 내용은 Linux 드라이버 기술 상세 설명(5)_장치 차단/비차단 읽기 및 쓰기의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 아무도들을 수없는 경우 오디오를 수정하는 방법
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25 : Myrise에서 모든 것을 잠금 해제하는 방법
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

Linux 터미널에서 Python 버전을 볼 때 발생하는 권한 문제를 해결하는 방법은 무엇입니까? Linux 터미널에서 Python 버전을 볼 때 발생하는 권한 문제를 해결하는 방법은 무엇입니까? Apr 01, 2025 pm 05:09 PM

Linux 터미널에서 Python 버전을 보려고 할 때 Linux 터미널에서 Python 버전을 볼 때 권한 문제에 대한 솔루션 ... Python을 입력하십시오 ...

Bitget 공식 웹 사이트 설치 (2025 초보자 안내서) Bitget 공식 웹 사이트 설치 (2025 초보자 안내서) Feb 21, 2025 pm 08:42 PM

Bitget은 스팟 거래, 계약 거래 및 파생 상품을 포함한 다양한 거래 서비스를 제공하는 Cryptocurrency 교환입니다. 2018 년에 설립 된이 교환은 싱가포르에 본사를두고 있으며 사용자에게 안전하고 안정적인 거래 플랫폼을 제공하기 위해 노력하고 있습니다. Bitget은 BTC/USDT, ETH/USDT 및 XRP/USDT를 포함한 다양한 거래 쌍을 제공합니다. 또한 Exchange는 보안 및 유동성으로 유명하며 프리미엄 주문 유형, 레버리지 거래 및 24/7 고객 지원과 같은 다양한 기능을 제공합니다.

시스템 재시작 후 UnixSocket의 권한을 자동으로 설정하는 방법은 무엇입니까? 시스템 재시작 후 UnixSocket의 권한을 자동으로 설정하는 방법은 무엇입니까? Mar 31, 2025 pm 11:54 PM

시스템이 다시 시작된 후 UnixSocket의 권한을 자동으로 설정하는 방법. 시스템이 다시 시작될 때마다 UnixSocket의 권한을 수정하려면 다음 명령을 실행해야합니다.

Gate.io 설치 패키지를 무료로 받으십시오 Gate.io 설치 패키지를 무료로 받으십시오 Feb 21, 2025 pm 08:21 PM

Gate.io는 사용자가 설치 패키지를 다운로드하여 장치에 설치하여 사용할 수있는 인기있는 cryptocurrency 교환입니다. 설치 패키지를 얻는 단계는 다음과 같습니다. Gate.io의 공식 웹 사이트를 방문하고 "다운로드"를 클릭하고 해당 운영 체제 (Windows, Mac 또는 Linux)를 선택하고 컴퓨터에 설치 패키지를 다운로드하십시오. 설치 중에 항 바이러스 소프트웨어 또는 방화벽을 일시적으로 비활성화하여 원활한 설치를 보장하는 것이 좋습니다. 완료 후 사용자는 GATE.IO 계정을 만들려면 사용을 시작해야합니다.

Docker 환경에서 PECL을 사용하여 확장자를 설치할 때 오류가 발생하는 이유는 무엇입니까? 그것을 해결하는 방법? Docker 환경에서 PECL을 사용하여 확장자를 설치할 때 오류가 발생하는 이유는 무엇입니까? 그것을 해결하는 방법? Apr 01, 2025 pm 03:06 PM

Docker 환경을 사용할 때 Docker 환경에 Extensions를 설치하기 위해 PECL을 사용하여 오류의 원인 및 솔루션. 종종 일부 두통이 발생합니다 ...

램프 아키텍처에서 Node.js 또는 Python 서비스를 효율적으로 통합하는 방법은 무엇입니까? 램프 아키텍처에서 Node.js 또는 Python 서비스를 효율적으로 통합하는 방법은 무엇입니까? Apr 01, 2025 pm 02:48 PM

많은 웹 사이트 개발자는 램프 아키텍처에서 Node.js 또는 Python 서비스를 통합하는 문제에 직면 해 있습니다. 기존 램프 (Linux Apache MySQL PHP) 아키텍처 웹 사이트 요구 사항 ...

Windows 및 Linux 파일을 동기화 할 때 비교할 수없는 비교가 사례 감도에 실패하면 어떻게해야합니까? Windows 및 Linux 파일을 동기화 할 때 비교할 수없는 비교가 사례 감도에 실패하면 어떻게해야합니까? Apr 01, 2025 am 08:06 AM

비교 및 동기화의 문제점을 넘어서는 파일을 비교하고 동기화하는 문제 : Beyond를 사용할 때의 경우 민감도 실패 ...

See all articles