Rumah > Tutorial sistem > LINUX > teks badan

Mekanisme pemprosesan untuk menyekat proses IO dalam pemacu Linux

王林
Lepaskan: 2024-02-11 16:45:03
ke hadapan
560 orang telah melayarinya

Kita perlu mempertimbangkan cara untuk bertindak balas apabila berhadapan dengan situasi di mana pemandu tidak dapat memenuhi permintaan dengan segera. Biasanya, proses panggilan tidak mengambil berat tentang status pemandu, jadi kami perlu mengendalikannya dengan sewajarnya dalam pemandu. Pendekatan biasa ialah menyekat permintaan kepada proses tersebut.

Menyekat I/O bermakna apabila melakukan operasi peranti, jika sumber yang diperlukan tidak dapat diperoleh, proses semasa akan digantung sehingga syarat kendalian dipenuhi sebelum melakukan operasi. Proses yang digantung pergi ke tidur dan dialih keluar daripada baris gilir larian penjadual sehingga syarat menunggu dipenuhi. Sebaliknya, I/O tanpa sekatan tidak menggantung proses apabila operasi peranti tidak dapat dilakukan, tetapi memilih untuk menyerah atau meneruskan pengundian sehingga operasi boleh dilakukan.

Barisan menunggu ialah mekanisme klasik untuk mengendalikan penyekatan I/O.

1. Menyekat aliran pemprosesan I/O dalam pemandu

Ringkasnya, aliran pemprosesan I/O yang menyekat termasuk 4 bahagian. Mula-mula, mulakan senarai giliran menunggu, yang menyimpan proses yang perlu disekat. Kemudian mulakan baris gilir menunggu dan tambahkan proses yang pada masa ini perlu disekat ke senarai terpaut baris gilir menunggu. Kemudian tetapkan proses menjadi terganggu dan sekat proses daripada tidur. Akhirnya, apabila syarat-syarat tertentu dipenuhi, iaitu, sumber tersedia, proses dalam barisan menunggu dibangkitkan.
Rajah berikut menerangkan aliran pemprosesan I/O yang menyekat:

Mekanisme pemprosesan untuk menyekat proses IO dalam pemacu Linux

2 Mulakan senarai giliran menunggu

Sebelum memulakan senarai terpaut baris gilir menunggu, terlebih dahulu kita perlu menentukan wait_queue_head_t的变量。例如在RK3399的ISP驱动中数据结构struct rkisp1_stream包含了wait_queue_head_t done;。通过调用调用init_waitqueue_head(&stream->done);untuk operasi permulaan.

void rkisp1_stream_init(struct rkisp1_device *dev, u32 id)
{
 struct rkisp1_stream *stream = &dev->stream[id];

 memset(stream, 0, sizeof(*stream));
 stream->id = id;
 stream->ispdev = dev;

 INIT_LIST_HEAD(&stream->buf_queue);
 init_waitqueue_head(&stream->done);
 spin_lock_init(&stream->vbq_lock);
 ...
}
Salin selepas log masuk

wait_queue_head_t变量的原型是__wait_queue_head, seperti yang ditunjukkan di bawah:

struct __wait_queue_head {
 spinlock_t  lock;
 struct list_head task_list;
};
Salin selepas log masuk

init_waitqueue_head()真正执行的函数是__init_waitqueue_head(), fungsinya ditakrifkan seperti berikut:

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);
}
Salin selepas log masuk

3. 等待队列处理

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

#define DECLARE_WAITQUEUE(name, tsk)     \
 wait_queue_t name = __WAITQUEUE_INITIALIZER(name, tsk)
Salin selepas log masuk

等待队列的定义如下:

struct __wait_queue {
 unsigned int  flags;
 void   *private;
 wait_queue_func_t func;
 struct list_head task_list;
};
Salin selepas log masuk

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

init_waitqueue_head(&delay_wait);
add_wait_queue(&delay_wait, &wait);
Salin selepas log masuk

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

static inline void __add_wait_queue(wait_queue_head_t *head, wait_queue_t *new)
{
 list_add(&new->task_list, &head->task_list);
}
Salin selepas log masuk

4. 阻塞进程处理

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

set_current_state(TASK_INTERRUPTIBLE);
schedule();
Salin selepas log masuk

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);
 }
...
}
Salin selepas log masuk

Atas ialah kandungan terperinci Mekanisme pemprosesan untuk menyekat proses IO dalam pemacu Linux. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:lxlinux.net
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan
Tentang kita Penafian Sitemap
Laman web PHP Cina:Latihan PHP dalam talian kebajikan awam,Bantu pelajar PHP berkembang dengan cepat!