赞
踩
qemu 编译版本 7.0.0
gdb --args ./build/qemu-system-x86_64 \
-m 2G -smp 2 \
--enable-kvm \
-boot order=c \
-name plr1 \
-drive file=/home/ostest/linux-test/run-test/ubuntu1.img,index=0,media=disk,format=qcow2 \
-drive file=/home/ostest/new/disk.raw,index=1,media=disk,format=raw \
-nic none\
-vnc :1
位于 disk.raw
上
#define _GNU_SOURCE #include <errno.h> #include <fcntl.h> #include <malloc.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/mman.h> #include <sys/types.h> #include <unistd.h> int main(void) { char hello_str[] = "Hello World!"; void *write_buffer; void *read_buffer; int fd; int ret = 0; fd = open("direct_write.log", O_RDWR | O_CREAT | O_DIRECT, 0644); if (fd < 0) { perror("Failed to open file\n"); return fd; } /* allocate a 1024 bytes buffer memalign分配指定地址对齐的资源接口 */ write_buffer = memalign(512, 512 * 2); // align by 512 if (!write_buffer) { perror("Failed to alloc write buffer\n"); ret = -ENOMEM; goto bad_write_buffer; } memcpy(write_buffer, hello_str, sizeof(hello_str)); ret = write(fd, write_buffer, 512 * 2); if (ret < 0) { perror("Failed to write file\n"); goto bad_write; } // 文件同步 if (fsync(fd) < 0) { perror("fysnc:"); goto bad_write; } lseek(fd, 0, SEEK_SET); // read previous write data read_buffer = memalign(512, 512 * 2); if (!read_buffer) { perror("Failed to alloc read buffer\n"); ret = -ENOMEM; goto bad_read_buffer; } ret = read(fd, read_buffer, 512 * 2); if (ret < 0) { perror("Failed to read file\n"); goto bad_read; } printf("read from file : %s\n", (char *)read_buffer); bad_read: free(read_buffer); bad_read_buffer: bad_write: free(write_buffer); bad_write_buffer: close(fd); return ret; }
参考 QEMU(4) q35
可以在命令后面添加 -monitor stdio
(qemu) info qtree bus: main-system-bus type System dev: hpet, id "" gpio-in "" 2 gpio-out "" 1 gpio-out "sysbus-irq" 32 mmio 00000000fed00000/0000000000000400 dev: kvm-ioapic, id "" gpio-in "" 24 gsi_base = 0 (0x0) mmio 00000000fec00000/0000000000001000 dev: i440FX-pcihost, id "" pci-hole64-size = 2147483648 (2 GiB) bypass-iommu = false bus: pci.0 type PCI dev: PIIX4_PM, id " class Bridge, addr 00:01.3, pci id 8086:7113 (sub 1af4:1100) bus: i2c type i2c-bus dev: smbus-eeprom, id "" address = 87 (0x57) dev: piix3-ide, id "" addr = 01.1 class IDE controller, addr 00:01.1, pci id 8086:7010 (sub 1af4:1100) bar 4: i/o at 0xc000 [0xc00f] bus: ide.1 type IDE dev: ide-cd, id "" drive = "ide1-cd0" bus: ide.0 type IDE dev: ide-hd, id "" drive = "ide0-hd1" backend_defaults = "auto" logical_block_size = 512 (512 B) physical_block_size = 512 (512 B) discard_granularity = 512 (512 B) write-cache = "auto" share-rw = false serial = "QM00002" model = "" unit = 1 (0x1) dev: ide-hd, id "" drive = "ide0-hd0" unit = 0 (0x0) dev: VGA, id "" dev: PIIX3, id "" class ISA bridge, addr 00:01.0, pci id 8086:7000 (sub 1af4:1100) bus: isa.0 type ISA dev: port92, id "" gpio-out "a20" 1 dev: vmmouse, id "" dev: vmport, id "" dev: i8042, id "" dev: isa-fdc, id "" bus: floppy-bus.0 type floppy-bus dev: floppy, id "" unit = 0 (0x0) drive = "floppy0" dev: isa-parallel, id "" chardev = "parallel0" dev: isa-serial, id "" dev: i8257, id "" dev: i8257, id "" dev: isa-pcspk, id "" dev: kvm-pit, id "" dev: mc146818rtc, id "" dev: kvm-i8259, id "" dev: kvm-i8259, id "" dev: i440FX, id "" class Host bridge, addr 00:00.0, pci id 8086:1237 (sub 1af4:1100) dev: fw_cfg_io, id "" dev: kvmclock, id "" dev: kvmvapic, id ""
(qemu) info block ide0-hd0 (#block163): /home/ostest/new/ubuntu3.img (qcow2) Attached to: /machine/unattached/device[24] Cache mode: writeback ide0-hd1 (#block307): /home/ostest/new/disk3.raw (raw) Attached to: /machine/unattached/device[25] Cache mode: writeback ide1-cd0: [not inserted] Attached to: /machine/unattached/device[26] Removable device: not locked, tray closed floppy0: [not inserted] Attached to: /machine/unattached/device[18] Removable device: not locked, tray closed sd0: [not inserted] Removable device: not locked, tray closed (qemu) info chardev parallel0: filename=vc compat_monitor0: filename=stdio serial0: filename=vc info irq -- show the interrupts statistics (if available)
知道 qemu 是通过协程 异步处理io 处理函数 handle_aiocb_rw
, 先通过断点这个查看函数栈,再往前进行分析
#0 handle_aiocb_rw (opaque=0x7fff51fcc4e0) at ../block/file-posix.c:1549 #1 0x00005555560fabbb in worker_thread (opaque=0x555556b16000) at ../util/thread-pool.c:104 #2 0x00005555560d297d in qemu_thread_start (args=0x555556c447f0) at ../util/qemu-thread-posix.c:556 // 通过qemu 源码搜索,发现 static int coroutine_fn raw_co_prw(...) { return raw_thread_pool_submit(bs, handle_aiocb_rw, &acb); } #0 raw_co_prw (bs=0x555556c3df60, offset=10019602432, bytes=65536, qiov=0x7fff51fcc8e0, type=1) at ../block/file-posix.c:2124 #1 0x0000555555f444c9 in raw_co_preadv (bs=0x555556c3df60, offset=10019602432, bytes=65536, qiov=0x7fff51fcc8e0, flags=0) at ../block/file-posix.c:2173 #2 0x0000555555ed29d0 in bdrv_driver_preadv (bs=0x555556c3df60, offset=10019602432, bytes=65536, qiov=0x7fff51fcc8e0, qiov_offset=0, flags=0) at ../block/io.c:1220 #3 0x0000555555ed3b55 in bdrv_aligned_preadv (child=0x555556bfd790, req=0x7fff51fcc720, offset=10019602432, bytes=65536, align=1, qiov=0x7fff51fcc8e0, qiov_offset=0, flags=0) at ../block/io.c:1608 #4 0x0000555555ed45aa in bdrv_co_preadv_part (child=0x555556bfd790, offset=10019602432, bytes=65536, qiov=0x7fff51fcc8e0, qiov_offset=0, flags=0) at ../block/io.c:1881 #5 0x0000555555ed43a1 in bdrv_co_preadv (child=0x555556bfd790, offset=10019602432, bytes=65536, qiov=0x7fff51fcc8e0, flags=0) at ../block/io.c:1830 #6 0x0000555555e9556d in bdrv_preadv (child=0x555556bfd790, offset=10019602432, bytes=65536, qiov=0x7fff51fcc8e0, flags=0) at block/block-gen.c:348 #7 0x0000555555ed26c2 in bdrv_pread (child=0x555556bfd790, offset=10019602432, buf=0x7ffff4a36000, bytes=65536) at ../block/io.c:1125 #8 0x0000555555eeb4c8 in qcow2_cache_do_get (bs=0x555556c368a0, c=0x555556c438f0, offset=10019602432, table=0x7fff51fcca48, read_from_disk=true) at ../block/qcow2-cache.c:382 #9 0x0000555555eeb5b0 in qcow2_cache_get --Type <RET> for more, q to quit, c to continue without paging-- (bs=0x555556c368a0, c=0x555556c438f0, offset=10019602432, table=0x7fff51fcca48) at ../block/qcow2-cache.c:406 #10 0x0000555555eecc0e in l2_load (bs=0x555556c368a0, offset=22488797184, l2_offset=10019602432, l2_slice=0x7fff51fcca48) at ../block/qcow2-cluster.c:215 #11 0x0000555555eee0ad in get_cluster_table (bs=0x555556c368a0, offset=22488797184, new_l2_slice=0x7fff51fccad0, new_l2_index=0x7fff51fccac4) at ../block/qcow2-cluster.c:802 #12 0x0000555555eefeab in handle_copied (bs=0x555556c368a0, guest_offset=22488797184, host_offset=0x7fff51fccb90, bytes=0x7fff51fccb98, m=0x7fff51fccc30) at ../block/qcow2-cluster.c:1519 #13 0x0000555555ef08db in qcow2_alloc_host_offset (bs=0x555556c368a0, offset=22488797184, bytes=0x7fff51fccc14, host_offset=0x7fff51fccc28, m=0x7fff51fccc30) at ../block/qcow2-cluster.c:1854 #14 0x0000555555f055d5 in qcow2_co_pwritev_part (bs=0x555556c368a0, offset=22488797184, bytes=4096, qiov=0x7fff586bfb80, qiov_offset=0, flags=0) at ../block/qcow2.c:2629 #15 0x0000555555ed2ca9 in bdrv_driver_pwritev (bs=0x555556c368a0, offset=22488797184, bytes=4096, qiov=0x7fff586bfb80, qiov_offset=0, flags=0) at ../block/io.c:1281 #16 0x0000555555ed53d6 in bdrv_aligned_pwritev (child=0x555556c10490, req=0x7fff51fcce00, offset=22488797184, bytes=4096, align=1, qiov=0x7fff586bfb80, qiov_offset=0, flags=0) at ../block/io.c:2157 #17 0x0000555555ed5ce5 in bdrv_co_pwritev_part (child=0x555556c10490, offset=22488797184, bytes=4096, qiov=0x7fff586bfb80, qiov_offset=0, flags=0) at ../block/io.c:2349 #18 0x0000555555ec2357 in blk_co_do_pwritev_part (blk=0x555556c36550, offset=22488797184, bytes=4096, qiov=0x7fff586bfb80, qiov_offset=0, fl--Type <RET> for more, q to quit, c to continue without paging-- ags=0) at ../block/block-backend.c:1365 #19 0x0000555555ec294c in blk_aio_write_entry (opaque=0x7fff580f40b0) at ../block/block-backend.c:1556 #20 0x00005555560e859a in coroutine_trampoline (i0=1477213776, i1=32767) at ../util/coroutine-ucontext.c:173 // 再搜索blk_aio_write_entry BlockAIOCB *blk_aio_pwritev(BlockBackend *blk, int64_t offset, QEMUIOVector *qiov, BdrvRequestFlags flags, BlockCompletionFunc *cb, void *opaque) { IO_CODE(); assert((uint64_t)qiov->size <= INT64_MAX); return blk_aio_prwv(blk, offset, qiov->size, qiov, blk_aio_write_entry, flags, cb, opaque); } BlockAIOCB *blk_aio_pwrite_zeroes(BlockBackend *blk, int64_t offset, int64_t bytes, BdrvRequestFlags flags, BlockCompletionFunc *cb, void *opaque) { IO_CODE(); return blk_aio_prwv(blk, offset, bytes, NULL, blk_aio_write_entry, flags | BDRV_REQ_ZERO_WRITE, cb, opaque); } #0 blk_aio_pwritev (blk=0x555556c36550, offset=22488797184, qiov=0x7fff586bfb80, flags=0, cb=0x5555559f5fdf <dma_blk_cb>, opaque=0x7fff586bfb20) at ../block/block-backend.c:1640 #1 0x00005555559f6a68 in dma_blk_write_io_func (offset=22488797184, iov=0x7fff586bfb80, cb=0x5555559f5fdf <dma_blk_cb>, cb_opaque=0x7fff586bfb20, opaque=0x555556c36550) at ../softmmu/dma-helpers.c:379 #2 0x00005555559f64d9 in dma_blk_cb (opaque=0x7fff586bfb20, ret=0) at ../softmmu/dma-helpers.c:238 #3 0x00005555559f6768 in dma_blk_io (ctx=0x555556a06020, sg=0x5555576aa310, offset=22488797184, align=512, io_func=0x5555559f6824 <dma_blk_write_io_func>, io_func_opaque=0x555556c36550, cb=0x555555b0fb78 <ide_dma_cb>, opaque=0x5555576a9fe8, dir=DMA_DIRECTION_TO_DEVICE) at ../softmmu/dma-helpers.c:317 #4 0x00005555559f6ac9 in dma_blk_write (blk=0x555556c36550, sg=0x5555576aa310, offset=22488797184, align=512, cb= 0x555555b0fb78 <ide_dma_cb>, opaque=0x5555576a9fe8) at ../softmmu/dma-helpers.c:386 #5 0x0000555555b0ff4a in ide_dma_cb (opaque=0x5555576a9fe8, ret=0) at ../hw/ide/core.c:986 #6 0x0000555555b18c2b in bmdma_cmd_writeb (bm=0x5555576ab140, val=1) at ../hw/ide/pci.c:355 #7 0x0000555555b194bf in bmdma_write (opaque=0x5555576ab140, addr=0, val=1, size=1) at ../hw/ide/piix.c:76
#0 bmdma_setup_bar (d=0x5555576a9560) at ../hw/ide/piix.c:93 #1 0x0000555555b19903 in pci_piix_ide_realize (dev=0x5555576a9560, errp=0x7fffffffdae8) at ../hw/ide/piix.c:164 #2 0x0000555555ba0783 in pci_qdev_realize (qdev=0x5555576a9560, errp=0x7fffffffdb60) at ../hw/pci/pci.c:2192 #3 0x0000555555e5ed7e in device_set_realized (obj=0x5555576a9560, value=true, errp=0x7fffffffdc70) at ../hw/core/qdev.c:531 #4 0x0000555555e6789d in property_set_bool (obj=0x5555576a9560, v= 0x5555576abcb0, name=0x55555625f251 "realized", opaque=0x555556a08870, errp=0x7fffffffdc70) at ../qom/object.c:2273 #5 0x0000555555e65808 in object_property_set (obj=0x5555576a9560, name=0x55555625f251 "realized", v= 0x5555576abcb0, errp=0x7fffffffdc70) at ../qom/object.c:1408 #6 0x0000555555e69d6e in object_property_set_qobject (obj=0x5555576a9560, name=0x55555625f251 "realized", value=0x5555576a9510, errp=0x55555694b720 <error_fatal>) at ../qom/qom-qobject.c:28 #7 0x0000555555e65b83 in object_property_set_bool (obj=0x5555576a9560, name=0x55555625f251 "realized", value=true, errp=0x55555694b720 <error_fatal>) at ../qom/object.c:1477 #8 0x0000555555e5e612 in qdev_realize (dev=0x5555576a9560, bus=0x555556dafee0, errp=0x55555694b720 <error_fatal>) at ../hw/core/qdev.c:333 #9 0x0000555555e5e643 in qdev_realize_and_unref (dev=0x5555576a9560, bus=0x555556dafee0, errp=0x55555694b720 <error_fatal>) at ../hw/core/qdev.c:340 #10 0x0000555555ba0a72 in pci_realize_and_unref (dev=0x5555576a9560, bus=0x555556dafee0, errp=0x55555694b720 <error_fatal>) at ../hw/pci/pci.c:2259 #11 0x0000555555ba0ac2 in pci_create_simple_multifunction (bus=0x555556dafee0, devfn=9, multifunction=false, name=0x55555621c151 "piix3-ide") at ../hw/pci/pci.c:2267 #12 0x0000555555ba0afa in pci_create_simple (bus=0x555556dafee0, devfn=9, name=0x55555621c151 "piix3-ide") at ../hw/pci/pci.c:2273 #13 0x0000555555c852f0 in pc_init1 (machine=0x555556bd50c0, host_type=0x55555621c1a4 "i440FX-pcihost", pci_type=0x55555621c19d "i440FX") at ../hw/i386/pc_piix.c:247 #14 0x0000555555c8592c in pc_init_v7_0 (machine=0x555556bd50c0) at ../hw/i386/pc_piix.c:427 #15 0x0000555555accf0c in machine_run_board_init (machine=0x555556bd50c0) at ../hw/core/machine.c:1189
#0 bmdma_write (opaque=0x5555576ab140, addr=2, val=0, size=1) at ../hw/ide/piix.c:66 #1 0x0000555555d22607 in memory_region_write_accessor (mr=0x5555576ab2b0, addr=2, value=0x7fff675fd688, size=1, shift=0, mask=255, attrs=...) at ../softmmu/memory.c:518 (gdb) p *bm $2 = {dma = {ops = 0x5555566dfbc0 <bmdma_ops>, qiov = {iov = 0x0, niov = 0, {{nalloc = 0, local_iov = { iov_base = 0x0, iov_len = 0}}, {__pad = '\000' <repeats 11 times>, size = 0}}}, aiocb = 0x0}, hit Breakpoint 4, bmdma_cmd_writeb() at ../hw/ide/pci.c:341 // 从这些看不是需要debug的地方 (gdb) p bm->dma_cb $5 = (BlockCompletionFunc *) 0x555555b158f4 <ide_atapi_cmd_read_dma_cb> hit Breakpoint 5, ide_dma_cb() p s->blk->name $12 = 0x555556c44850 "ide0-hd0" (gdb) n 948 if (prep_size < n * 512) { (gdb) p prep_size $18 = 512 (gdb) p n $19 = 1 (gdb) p s->bus->dma->ops->prepare_buf $20 = (DMAInt32Func *) 0x555555b184d9 <bmdma_prepare_buf>
Thread 6 "qemu-system-x86" hit Breakpoint 7, dma_blk_write (blk=0xfe7c075bd59d6200, sg=0x200000, offset=93825027187640, align=0, cb=0x6, opaque=0x7fff675fd4b0) at ../softmmu/dma-helpers.c:389 389 { (gdb) n 390 return dma_blk_io(blk_get_aio_context(blk), sg, offset, align, (gdb) p *blk $24 = {name = 0x555556c64bd0 "ide0-hd1", refcnt = 2, root = 0x555556bf5870, ctx = 0x555556a06020, legacy_dinfo = 0x555556c46570, dev = 0x5555577e0c60, dev_ops = 0x5555566de5c0 <ide_hd_block_ops>, dev_opaque = 0x5555576aa3b8, (gdb) s blk_get_aio_context (blk=) at ../block/block-backend.c:2164 (gdb) n 2168 if (bs) { (gdb) p bs->filename $31 = "/home/ostest/new/disk.raw", '\000' <repeats 4070 times> (gdb) p *bs $33 = {open_flags = 139266, encrypted = false, sg = false, probed = false, force_share = false, implicit = false, drv = 0x5555568f40a0 <bdrv_raw>,walking_aio_notifiers = false, (gdb) p *(bs->file) $35 = {bs = 0x555556c5e550, name = 0x555556c64d50 "file", klass = 0x5555567f60c0 <child_of_bds>, role = 20, // 指向是不一样的 (gdb) p bs $36 = (BlockDriverState *) 0x555556c57200 (gdb) s dma_blk_io ()at ../softmmu/dma-helpers.c:288 p *dbs $43 = {common = {aiocb_info = 0x5555566cddc0 <dma_aiocb_info>, bs = 0x0, cb = 0x555555b0fb8b <ide_dma_cb>, opaque = 0x5555576aa3b8, refcnt = 1}, ctx = 0x555556a06020, acb = 0x0, sg = 0x5555576aa6e0, align = 512, offset = 536870912, dir = DMA_DIRECTION_TO_DEVICE, sg_cur_index = 0, sg_cur_byte = 0, iov = { iov = 0x7fff6017a500, niov = 0, {{nalloc = 1, local_iov = {iov_base = 0x0, iov_len = 0}}, {__pad = "", size = 0}}}, bh = 0x0, io_func = <dma_blk_write_io_func>, io_func_opaque = 0x555556c466d0}
函数调用关系
static void ide_dma_cb(void *opaque, int ret) { IDEState *s = opaque; s->bus->dma->aiocb = dma_blk_write(s->blk, &s->sg, offset, BDRV_SECTOR_SIZE, ide_dma_cb, s); } BlockAIOCB *dma_blk_write(BlockBackend *blk, QEMUSGList *sg, uint64_t offset, uint32_t align, void (*cb)(void *opaque, int ret), void *opaque) { // opaque -> IDEState return dma_blk_io(blk_get_aio_context(blk), sg, offset, align, dma_blk_write_io_func, blk, cb, opaque, DMA_DIRECTION_TO_DEVICE); } BlockAIOCB *dma_blk_io(AioContext *ctx, QEMUSGList *sg, uint64_t offset, uint32_t align, DMAIOFunc *io_func, void *io_func_opaque, BlockCompletionFunc *cb, void *opaque, DMADirection dir) { // io_func_opaque->blk; opaque->IDEState DMAAIOCB *dbs = qemu_aio_get(&dma_aiocb_info, NULL, cb, opaque); dbs->acb = NULL; dbs->sg = sg; dbs->ctx = ctx; dbs->offset = offset; dbs->align = align; dbs->sg_cur_index = 0; dbs->sg_cur_byte = 0; dbs->dir = dir; dbs->io_func = io_func; dbs->io_func_opaque = io_func_opaque; dbs->bh = NULL; qemu_iovec_init(&dbs->iov, sg->nsg); dma_blk_cb(dbs, 0); // 即调用dma_blk_write_io_func dbs->acb = dbs->io_func(dbs->offset, &dbs->iov, dma_blk_cb, dbs, dbs->io_func_opaque); return &dbs->common; } static BlockAIOCB *dma_blk_write_io_func(int64_t offset, QEMUIOVector *iov, BlockCompletionFunc *cb, void *cb_opaque, void *opaque) { // cb_opaque->DMAAIOCB BlockBackend *blk = opaque; return blk_aio_pwritev(blk, offset, iov, 0, cb, cb_opaque); }
gdb 调试过程
Thread 6 "qemu-system-x86" hit Breakpoint 2, dma_blk_write_io_func () at ../softmmu/dma-helpers.c:269 (gdb) p blk->name $2 = 0x555556d03cb0 "ide0-hd1" (gdb) s blk_aio_pwritev (blk=0x555556ce33a0, offset=138412032, qiov=0x7fff580052b0, flags=0, cb=0x5555558b7f0a <dma_blk_cb>, opaque=0x7fff58005250 ) at ../block/block-backend.c:1638 1638 { (gdb) n 1640 assert((uint64_t)qiov->size <= INT64_MAX); (gdb) n 1641 return blk_aio_prwv(blk, offset, qiov->size, qiov, (gdb) p *qiov $3 = {iov = 0x7fff58049bf0, niov = 1, {{nalloc = 1, local_iov = {iov_base = 0x0, iov_len = 1024}}, {, size = 1024}}} (gdb) p *(qiov->iov) $4 = {iov_base = 0x7fff7868f200, iov_len = 1024} (gdb) p *(qiov->iov->iov_base) Attempt to dereference a generic pointer. (gdb) p (char *)(qiov->iov->iov_base) // 此时是已经获取到数据的,猜测是在dma_blk_cb函数里 $5 = 0x7fff7868f200 "Hello World!" (gdb) s blk_aio_prwv (blk=0x555556ce33a0, offset=138412032, bytes=1024, iobuf=0x7fff580052b0, co_entry= <blk_aio_write_entry>, flags=0, cb= <dma_blk_cb>, opaque=0x7fff58005250 ) at ../block/block-backend.c:1509
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。