Linux 드라이버 기술 상세 설명(5)_장치 차단/비차단 읽기 및 쓰기
Linux 드라이버를 작성하는 과정에서 장치 차단/비차단 읽기 및 쓰기는 매우 중요한 기술입니다. 효율적인 데이터 전송 및 이벤트 처리를 달성하여 시스템 성능과 응답 속도를 향상시킬 수 있습니다. 이번 글에서는 리눅스 드라이버 기술(5)_장치 차단/비차단 읽기 및 쓰기 구현 원리와 관련 기술에 대해 알아보겠습니다.
대기 대기열은 프로세스 예약을 위한 커널의 매우 중요한 데이터 구조입니다. 연결 목록의 각 노드는 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 중국어 웹사이트의 기타 관련 기사를 참조하세요!

핫 AI 도구

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

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

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

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

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

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

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

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

뜨거운 주제











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

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

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

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

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

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

Linux 터미널에서 Python 사용 ...

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