Vietnamese (machine translation)

Lưu ý

Mục đích của file này là để độc giả tiếng Việt có thể đọc và hiểu tài liệu nhân kernel dễ dàng hơn, không phải để tạo ra một nhánh tài liệu riêng. Nếu bạn có bất kỳ nhận xét hoặc cập nhật nào cho file này, vui lòng thử cập nhật file tiếng Anh gốc trước. Nếu bạn thấy có sự khác biệt giữa bản dịch và bản gốc, hoặc có vấn đề về bản dịch, vui lòng gửi góp ý hoặc patch cho người dịch của file này, hoặc nhờ người bảo trì và người review tài liệu tiếng Việt giúp đỡ.

Bản gốc:

Writing Virtio Drivers

Người dịch:

Google Translate (machine translation)

Phiên bản gốc:

8541d8f725c6

Cảnh báo

Tài liệu này được dịch tự động bằng máy và chưa được review bởi người dịch. Nội dung có thể không chính xác hoặc khó hiểu ở một số chỗ. Khi có sự khác biệt với bản gốc, bản gốc luôn là chuẩn. Bản dịch chất lượng cao (được review) được đặt trong thư mục vi_VN/.

Viết trình điều khiển Virtio

Giới thiệu

Tài liệu này phục vụ như một hướng dẫn cơ bản cho các lập trình viên điều khiển cần hack một trình điều khiển virtio mới hoặc hiểu những điều cơ bản của những cái hiện có. Xem ZZ0000ZZ để biết thông tin chung tổng quan về đức hạnh

Bản soạn sẵn trình điều khiển

Ở mức tối thiểu, người lái xe tài năng cần phải đăng ký trên xe buýt tài năng và định cấu hình hàng đợi cho thiết bị theo thông số kỹ thuật của nó, cấu hình của các đức tính ở phía trình điều khiển phải phù hợp với định nghĩa Virtqueue trong thiết bị. Bộ xương trình điều khiển cơ bản có thể trông như thế này:

#include <linux/virtio.h>

#include <linux/virtio_ids.h> #include <linux/virtio_config.h> #include <linux/module.h>

/* dữ liệu riêng tư của thiết bị (mỗi thiết bị một dữ liệu) */
cấu trúc virtio_dummy_dev {

struct virtqueue *vq;

};

static void virtio_dummy_recv_cb(struct virtqueue *vq)
{

struct virtio_dummy_dev *dev = vq->vdev->priv; char *buf; int len ​​không dấu;

while ((buf = virtqueue_get_buf(dev->vq, &len)) != NULL) {

/*xử lý dữ liệu nhận được */

}

}

int tĩnh virtio_dummy_probe(struct virtio_device *vdev)
{

struct virtio_dummy_dev *dev = NULL;

/*khởi tạo dữ liệu thiết bị */

dev = kzalloc(sizeof(struct virtio_dummy_dev), GFP_KERNEL); nếu (!dev)

trả về -ENOMEM;

/* thiết bị có một hàng đợi duy nhất */

dev->vq = virtio_find_single_vq(vdev, virtio_dummy_recv_cb, “đầu vào”); nếu (IS_ERR(dev->vq)) {

kfree(dev); trả về PTR_ERR(dev->vq);

}

vdev->priv = dev;

/* từ thời điểm này trở đi, thiết bị có thể thông báo và nhận lệnh gọi lại */

virtio_device_ready(vdev);

trả về 0;

}

static void virtio_dummy_remove(struct virtio_device *vdev)
{

struct virtio_dummy_dev *dev = vdev->priv;

/*
  • vô hiệu hóa ngắt vq: tương đương với

  • vdev->config->đặt lại(vdev)

*/

virtio_reset_device(vdev);

/* loại bỏ các bộ đệm không sử dụng */
while ((buf = virtqueue_detach_unused_buf(dev->vq)) != NULL) {

kfree(buf);

}

/* loại bỏ hàng đợi đức hạnh */

vdev->config->del_vqs(vdev);

kfree(dev);

}

const tĩnh struct virtio_device_id id_table[] = {

{VIRTIO_ID_DUMMY, VIRTIO_DEV_ANY_ID }, { 0 },

};

cấu trúc tĩnh virtio_driver virtio_dummy_driver = {

.driver.name = KBUILD_MODNAME, .id_table = id_table, .probe = virtio_dummy_probe, .remove = virtio_dummy_remove,

};

module_virtio_driver(virtio_dummy_driver);

MODULE_DEVICE_TABLE(virtio, id_table); MODULE_DESCRIPTION(“Trình điều khiển giả”); MODULE_LICENSE(“GPL”);

Id thiết bị ZZ0000ZZ ở đây là trình giữ chỗ, trình điều khiển virtio chỉ nên thêm cho các thiết bị được xác định trong thông số kỹ thuật, xem bao gồm/uapi/linux/virtio_ids.h. Id thiết bị ít nhất phải được đặt trước trong thông số virtio trước khi được thêm vào tệp đó.

Nếu trình điều khiển của bạn không phải làm gì đặc biệt trong ZZ0000ZZ của nó và ZZ0001ZZ, bạn có thể sử dụng trình trợ giúp module_virtio_driver() để giảm số lượng mã soạn sẵn.

Phương pháp ZZ0000ZZ thực hiện thiết lập trình điều khiển tối thiểu trong trường hợp này (cấp phát bộ nhớ cho dữ liệu thiết bị) và khởi tạo đức hạnh. virtio_device_ready() được sử dụng để kích hoạt virtqueue và để thông báo cho thiết bị driver đã sẵn sàng để quản lý thiết bị (“DRIVER_OK”). Dù sao thì các đức tính cũng được kích hoạt tự động bởi lõi sau khi ZZ0001ZZ trở lại.

Trong mọi trường hợp, hàng đợi ảo cần phải được kích hoạt trước khi thêm bộ đệm vào họ.

Gửi và nhận dữ liệu

Lệnh gọi lại virtio_dummy_recv_cb() trong đoạn mã trên sẽ được kích hoạt khi thiết bị thông báo cho trình điều khiển sau khi xử lý xong một bộ mô tả hoặc chuỗi mô tả, để đọc hoặc viết. Tuy nhiên, đó mới chỉ là nửa sau của quá trình giao tiếp giữa trình điều khiển thiết bị virtio quá trình, vì giao tiếp luôn được khởi động bởi trình điều khiển bất kể về hướng truyền dữ liệu.

Để định cấu hình chuyển bộ đệm từ trình điều khiển sang thiết bị, trước tiên bạn phải thêm bộ đệm -- được đóng gói dưới dạng ZZ0000ZZ -- vào virtqueue thích hợp bằng cách sử dụng bất kỳ virtqueue_add_inbuf() nào, virtqueue_add_outbuf() hoặc virtqueue_add_sgs(), tùy thuộc vào việc bạn cần thêm một đầu vào ZZ0001ZZ (để thiết bị điền vào), một xuất ra ZZ0002ZZ (để thiết bị tiêu thụ) hoặc nhiều ZZ0003ZZ, tương ứng. Sau đó, khi hàng đợi được thiết lập, một cuộc gọi tới virtqueue_kick() gửi thông báo sẽ được phục vụ bởi trình ảo hóa triển khai thiết bị:

danh sách phân tán cấu trúc sg[1];

sg_init_one(sg, bộ đệm, BUFLEN); virtqueue_add_inbuf(dev->vq, sg, 1, bộ đệm, GFP_ATOMIC); virtqueue_kick(dev->vq);

Sau đó, sau khi thiết bị đã đọc hoặc ghi bộ đệm được chuẩn bị bởi trình điều khiển và thông báo lại, trình điều khiển có thể gọi virtqueue_get_buf() để đọc dữ liệu do thiết bị tạo ra (nếu Virtqueue được thiết lập với bộ đệm đầu vào) hoặc đơn giản là lấy lại bộ đệm nếu chúng đã thiết bị tiêu thụ:

Các cuộc gọi lại hàng đợi có thể bị vô hiệu hóa và kích hoạt lại bằng cách sử dụng virtqueue_disable_cb() và nhóm hàm virtqueue_enable_cb() tương ứng. Xem driver/virtio/virtio_ring.c để biết thêm chi tiết:

Nhưng lưu ý rằng một số lệnh gọi lại giả vẫn có thể được kích hoạt trong những kịch bản nhất định. Cách để vô hiệu hóa cuộc gọi lại một cách đáng tin cậy là đặt lại thiết bị hoặc virtqueue (virtio_reset_device()).

Tài liệu tham khảo

_ZZ0000ZZ Virtio Spec v1.2: ZZ0001ZZ

Kiểm tra các phiên bản sau của thông số kỹ thuật.