Linux 드라이버에서 IO 프로세스를 차단하는 처리 메커니즘

王林
풀어 주다: 2024-02-11 16:45:03
앞으로
578명이 탐색했습니다.

운전기사가 요청을 즉시 이행할 수 없는 상황에 직면했을 때 어떻게 대응할지 고려해야 합니다. 일반적으로 호출 프로세스는 드라이버의 상태에 관심이 없으므로 드라이버에서 그에 따라 처리해야 합니다. 일반적인 접근 방식은 프로세스에 대한 요청을 차단하는 것입니다.

Blocking I/O는 장치 작업을 수행할 때 필요한 리소스를 얻을 수 없는 경우 작업이 수행되기 전에 작동 가능한 조건이 충족될 때까지 현재 프로세스가 일시 중지된다는 의미입니다. 일시중단된 프로세스는 대기 상태가 되며 대기 조건이 충족될 때까지 스케줄러의 실행 큐에서 제거됩니다. 이에 비해 비차단 I/O는 장치 작업을 수행할 수 없을 때 프로세스를 일시 중지하지 않고 작업을 수행할 수 있을 때까지 폴링을 포기하거나 계속하도록 선택합니다.

대기 대기열은 차단 I/O를 처리하는 고전적인 메커니즘입니다.

1. 드라이버의 I/O 처리 흐름 차단

요약하면 블로킹 I/O 처리 흐름은 4가지 부분으로 구성됩니다. 먼저, 차단해야 하는 프로세스를 저장하는 대기 대기열 목록을 초기화합니다. 그런 다음 대기 큐를 초기화하고 현재 차단해야 하는 프로세스를 대기 큐 연결 목록에 추가합니다. 그런 다음 프로세스를 중단 가능하도록 설정하고 프로세스가 휴면 상태가 되지 않도록 차단합니다. 마지막으로 특정 조건이 충족되면, 즉 리소스를 사용할 수 있게 되면 대기 대기열에 있던 프로세스가 깨어납니다.
다음 그림은 차단 I/O 처리 흐름을 설명합니다.

Linux 드라이버에서 IO 프로세스를 차단하는 처리 메커니즘

2.대기목록 초기화

대기 대기열 연결 목록을 초기화하기 전에 먼저 초기화 작업을 위한 wait_queue_head_t的变量。例如在RK3399的ISP驱动中数据结构struct rkisp1_stream包含了wait_queue_head_t done;。通过调用调用init_waitqueue_head(&stream->done);을 정의해야 합니다.

으아악

wait_queue_head_t变量的原型是__wait_queue_head, 아래와 같이:

으아악

init_waitqueue_head()真正执行的函数是__init_waitqueue_head() 해당 기능은 다음과 같이 정의됩니다.

void __init_waitqueue_head(wait_queue_head_t *q, const char *name, struct lock_class_key *key)
{
 spin_lock_init(&q->lock);
 lockdep_set_class_and_name(&q->lock, key, name);
 INIT_LIST_HEAD(&q->task_list);
}
로그인 후 복사

3. 等待队列处理

调用DECLARE_WAITQUEUE(wait, current)将当前进程初始化为等待队列。注意,这里的等待队列和等待队列链表头可不是一个东东。

#define DECLARE_WAITQUEUE(name, tsk)     \
 wait_queue_t name = __WAITQUEUE_INITIALIZER(name, tsk)
로그인 후 복사

等待队列的定义如下:

struct __wait_queue {
 unsigned int  flags;
 void   *private;
 wait_queue_func_t func;
 struct list_head task_list;
};
로그인 후 복사

等待队列和等待队列链表头是通过add_wait_queue()结合到一起的。

init_waitqueue_head(&delay_wait);
add_wait_queue(&delay_wait, &wait);
로그인 후 복사

以上代码是将等待队列进程加入到等待队列链表中:

static inline void __add_wait_queue(wait_queue_head_t *head, wait_queue_t *new)
{
 list_add(&new->task_list, &head->task_list);
}
로그인 후 복사

4. 阻塞进程处理

阻塞进程处理包括两部分内容,首先设置进程的睡眠状态,包括TASK_INTERRUPTIBLETASK_UNINTERRUPTIBLE两种。前者用于可中断睡眠,后者用于不可中断睡眠。然后,将当前进程退出调度器让出CPU的使用权。

set_current_state(TASK_INTERRUPTIBLE);
schedule();
로그인 후 복사

5. 唤醒处理

唤醒处理通常位于中断处理函数或某些动作成功执行之后,特定条件满足时,唤醒通过阻塞队列睡眠的进程。例如:

void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors,
       int success, int behind)
{
 if (!bitmap)
  return;
 if (behind) {
  if (atomic_dec_and_test(&bitmap->behind_writes))
   wake_up(&bitmap->behind_wait);
  pr_debug("dec write-behind count %d/%lu\n",
    atomic_read(&bitmap->behind_writes),
    bitmap->mddev->bitmap_info.max_write_behind);
 }
...
}
로그인 후 복사

위 내용은 Linux 드라이버에서 IO 프로세스를 차단하는 처리 메커니즘의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

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