当前位置:   article > 正文

vmware+ubuntu18+qemu调试kernel-arm64-vsock_vmware运行arm系统

vmware运行arm系统


环境:win11 + vmware17 + ubuntu18.04

一、环境搭建

1.qemu-8.0.2

https://download.qemu.org/
参考资料: https://wiki.qemu.org/Hosts/Linux

cd
mkdir kernel && cd kernel
wget -c https://download.qemu.org/qemu-8.0.2.tar.xz
tar xvJf qemu-8.0.2.tar.xz
cd qemu-8.0.2
mkdir compile_result && cd compile_result #编译后的目录
sudo apt-get install libpixman-1-dev
sudo apt install ninja-build
sudo apt-get install libglib2.0-dev
sudo apt install flex
../configure --prefix=$(pwd)  --enable-debug
make -j8 && sudo make install
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

2.buildroot

https://buildroot.org/download.html

 git clone git://git.busybox.net/buildroot
 sudo apt install libncurses-dev  -y
 make menuconfig

#配置好后编译
 make -j8
#编译好的结果会在output目录 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

配置

在弹出的配置界面中,
设置
Target option ---> Target Architecture为
AArch64 (little endian);
设置
Toolchain ---> Toolchain type为
External toolchain,这时我们可以看到
Toolchain ---> Toolchain的值为
linaro AArch64 xxxx.xx;
设置
System configuration ---> Enable root login with password开启,并设置
System configuration ---> Root password为
xxxx(任意的你喜欢的密码);
设置
System configuration ---> Run a getty (login prompt) after boot ---> TTY port的值为
#按i编辑
ttyAMA0(这一条非常重要,不然虚拟机可能启动不了);
表示使用树莓派上的串口设备ttyAMA0作为终端设备
设置
Target packages ---> Show packages that are also provided by busybox开启;设置
Target packages ---> Debugging, profiling and benchmark ---> strace开启(应用程序和系统调用的信息追踪);设置
Filesystem images ---> cpio the root filesystem开启(生成cpio格式的根文件系统镜像)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

3.编译工具链gcc-linaro-7.2.1

下载交叉编译工具链

https://releases.linaro.org/components/toolchain/binaries/

wget -c https://releases.linaro.org/components/toolchain/binaries/7.2-2017.11/aarch64-linux-gnu/gcc-linaro-7.2.1-2017.11-x86_64_aarch64-linux-gnu.tar.xz
sudo mkdir /home/toolchain
sudo tar xvJf gcc-linaro-7.2.1-2017.11-x86_64_aarch64-linux-gnu.tar.xz  -C /home/toolchain
  • 1
  • 2
  • 3

4.linux kernel 5.16

https://www.kernel.org/
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/snapshot/linux-5.16.tar.gz

#下载内核源码:
wget -c https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.16.tar.xz
tar xvJf linux-5.16.tar.xz
  • 1
  • 2
  • 3

config_kernel.sh

BUILD_DIR=$(pwd)/linux-5.16   

if [ ! -z $1 ]
then
                BUILD_DIR=$1
fi

export ARCH=arm64
export CROSS_COMPILE=/home/toolchain/gcc-linaro-7.2.1-2017.11-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
cd $BUILD_DIR
make menuconfig
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

配置内核

#运行config_kernel.sh后进行设置
设置
Boot options ---> (console=ttyAMA0) Default kernel command string
设置其值为console=ttyAMA0

设置
General setup  ---> [*] Initial RAM filesystem and RAM disk (initramfs/initrd) support                       
                        (/home/yyh/kernel/buildroot/output/images/rootfs.cpio) Initramfs source file(s)                       
设置其值为
$BUILD_ROOT_PATH/output/images/rootfs.cpio(注意,这里要自己展开变量BUILD_ROOT_PATH);
设置支持virtio-vsock
 [*] Networking support  --->  
                  Networking options  --->   
                                      <*> Virtual Socket protocol                                                                                            x x  
                                                <*>   Virtual Sockets monitoring interface (NEW)                                                                       x x  
                                                <*>   Virtual Sockets loopback transport (NEW)                                                                         x x  
                                                 <*>   virtio transport for Virtual Sockets   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

build_kernel.sh

#! /bin/bash

BUILD_DIR=$(pwd)/linux-5.16

if [ ! -z $1 ]
then
    BUILD_DIR=$1
fi

export ARCH=arm64
export CROSS_COMPILE=/home/toolchain/gcc-linaro-7.2.1-2017.11-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
cd $BUILD_DIR
make -j8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

5.启动虚拟机

(1)创建磁盘镜像文件

$(pwd)/qemu-8.0.2/compile_result/qemu-img create -f qcow2 test-qcow2.img  10G
  • 1

(2)拷贝内核镜像和根文件系统到指定目录

mkdir img_space && cd img_space
mv ../test-qcow2.img .
cp /home/yyh/kernel/buildroot/output/images/rootfs.cpio .
cp /home/yyh/kernel/linux-5.16/arch/arm64/boot/Image .
  • 1
  • 2
  • 3
  • 4

(3)配置和管理虚拟机网络接口

参考:https://blog.csdn.net/chengbeng1745/article/details/81271024
https://www.jianshu.com/p/110b60c14a8b
/etc/qemu-ifup脚本在启动虚拟机的网络接口时运行,用于配置虚拟机的IP地址、子网掩码、网关等

sudo vim /etc/qemu-ifup
#添加如下内容

#!/bin/sh
switch=br0
interface=ens33
if [ -n "$1" ]; then
    switch_exit=`sudo ifconfig -a | grep $switch`
    interface_switch=`sudo brctl show | grep $interface`
    if [ "$switch_exit" = "" ] ; then
        sudo brctl addbr $switch
    fi
   if [ "$interface_switch" = "" ] ; then
       sudo ifconfig $interface 0.0.0.0 promisc up
       sudo brctl addif $switch $interface
    fi
    sudo ifconfig $1 0.0.0.0 promisc up
    sudo brctl addif $switch $1
    sudo dhclient $switch
else
   echo "Error: no interface specified"
   exit
fi
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

/etc/qemu-ifdown脚本在关闭虚拟机的网络接口时运行,用于清除虚拟机的网络配置

sudo vim /etc/qemu-ifdown
#添加如下内容
#! /bin/sh

switch=br0
if [ -n "$1" ]; then

#    sudo tunctl -d $1
    sudo brctl delif $switch $1
    sudo ifconfig $1 down
else
    echo "error: no interface specified"
    exit 1
fi
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

在Linux中创建一个桥接接口br0,并将物理接口eth0添加到该桥接接口上。这样虚拟机可以通过eth0与宿主机进行网络通信。配置好后重启系统sudo reboot

sudo chmod +x /etc/qemu-*
sudo apt-get install uml-utilities bridge-utils 
sudo vim /etc/network/interfaces
#添加如下内容
auto eth0
iface eth0 inet manual

auto br0
iface br0 inet dhcp
    bridge_ports eth0
    bridge_stp off
    bridge_fd 0

#创建一个名为br0的桥接接口,并使用DHCP协议自动分配IP地址
#bridge_ports eth0表示将物理接口eth0添加到桥接接口br0上
#bridge_stp off表示关闭STP(Spanning Tree Protocol)
#bridge_fd 0表示禁用桥接接口的转发延迟
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

(4)虚拟机启动脚本start_qemu_arm64_vsock.sh

#!/bin/sh

QEMU_PATH=$(pwd)/qemu-8.0.2/compile_result/aarch64-softmmu/qemu-system-aarch64
KERNEL_IMG_PATH=$(pwd)/img_space/Image
DISK_IMG_PATH=$(pwd)/img_space/test-qcow2.img
ROOTFS_IMG_PATH=$(pwd)/img_space/rootfs.cpio

MEM_SIZE="4G"
CPU_CORES="4"
NETDEV_TYPE="tap"
NETDEV_ID="net0"
NETDEV_IFNAME="tap0"
NETDEV_SCRIPT="/etc/qemu-ifup"
NETDEV_DOWNSCRIPT="/etc/qemu-ifdown"

sudo \
    $QEMU_PATH \
    -machine virt,accel=tcg \
    -m $MEM_SIZE \
    -smp $CPU_CORES \
    -kernel $KERNEL_IMG_PATH \
    -initrd $ROOTFS_IMG_PATH \
    -append "console=ttyAMA0" \
    -drive file=$DISK_IMG_PATH,format=qcow2,if=virtio,id=hdw \
    -netdev $NETDEV_TYPE,id=$NETDEV_ID,ifname=$NETDEV_IFNAME,script=$NETDEV_SCRIPT,downscript=$NETDEV_DOWNSCRIPT \
    -device virtio-net-pci,netdev=$NETDEV_ID \
    -device vhost-vsock-device,guest-cid=3 \
    -cpu cortex-a57 \
    -serial stdio \
    -display none
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

qemu相关参数


-machine指定虚拟机的架构和加速器,这里使用了virt和tcg

-m指定虚拟机的内存大小

-smp指定虚拟机的CPU核心数

-kernel指定内核镜像文件的路径

-initrd指定根文件系统镜像文件的路径

-append指定内核的启动参数

-drive指定磁盘镜像文件、格式、接口和ID

-netdev指定网络设备类型、ID、名称、启动脚本和关闭脚本

-device指定设备类型和ID

-cpu指定CPU类型

-serial指定串行控制台

-display指定显示设备类型
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

二、测试vsock

参考:http://www.manongjc.com/detail/20-yjvqsrjykkxqwfq.html

1.运行start_qemu_arm64_vsock.sh启动虚拟机

在这里插入图片描述

2.编译代码

https://chromium.googlesource.com/chromiumos/platform2/+/9e91613d2da1b3d6cfb1c77681444e688ce99cf4/vm_tools/docs/vsock.md
在这里插入图片描述

v_cli目录下的makefile

CC =/home/toolchain/gcc-linaro-7.2.1-2017.11-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc 
#CC = gcc
CFLAGS = #-Wall -Werror
INCLUDES = 
LDFLAGS = 
LIBS = 
SRCS = vsock_client.c
OBJS = $(SRCS:.c=.o)
TARGET = cli

all: $(TARGET)
$(TARGET): $(OBJS)
    $(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
%.o: %.c
    $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
clean:
    rm -f $(OBJS) $(TARGET)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

v_server目录下的makefile

#CC =/home/toolchain/gcc-linaro-7.2.1-2017.11-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc 
CC = gcc
CFLAGS = #-Wall -Werror
INCLUDES = 
LDFLAGS = 
LIBS = 
SRCS = vsock_server.c
OBJS = $(SRCS:.c=.o)
TARGET = ser

all: $(TARGET)
$(TARGET): $(OBJS)
    $(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
%.o: %.c
    $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
clean:
    rm -f $(OBJS) $(TARGET)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

3.通过tftp将cli文件传输至arm64虚拟机

在这里插入图片描述

windows启动tftp服务器,将编译好的cli放在设置好的共享目录

#arm64虚拟机通过tftp获取cli文件
tftp -gr cli 192.168.11.29
chmod +x cli
3.运行测试
#ubnutu18.04运行ser
./ser
#arm64虚拟机运行cli
./cli
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

在这里插入图片描述

4.多线程并发测试

ser

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <linux/vm_sockets.h>

void* pthread_fun(void* arg)
{
    int c = *(int*)arg;
    free(arg);

    while (1)
    {
        char buff[128] = {0};
        int n = recv(c, buff, 127, 0);
        if (n <= 0)
        {
            break;
        }
        printf("recv(%d)=%s\n", c, buff);
        send(c, "OK", 2, 0);
    }

    close(c);
    pthread_exit(NULL);
}

int main()
{
    int sockfd = socket(AF_VSOCK, SOCK_STREAM, 0);
    assert(sockfd != -1);

    struct sockaddr_vm saddr, caddr;
    memset(&saddr, 0, sizeof(saddr));
    saddr.svm_family = AF_VSOCK;
    saddr.svm_cid =  VMADDR_CID_HOST;
    saddr.svm_port = 9999;

    int res = bind(sockfd, (struct sockaddr*)&saddr, sizeof(saddr));
    assert(res != -1);

    listen(sockfd, 5);

    while (1)
    {
        struct sockaddr_vm caddr;
        memset(&caddr, 0, sizeof(caddr));
        int len = sizeof(caddr);
        int* c = (int*)malloc(sizeof(int));
        *c = accept(sockfd, (struct sockaddr*)&caddr, &len);
        if (*c < 0)
        {
            free(c); 
            continue;
        }
        printf("accept = %d\n", *c);
        pthread_t id;
        pthread_create(&id, NULL, pthread_fun, (void*)c);
    }

    close(sockfd);
    exit(0);
}


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69

cli

#include <sys/socket.h>
#include <stdio.h>
#include <unistd.h>
#include <linux/vm_sockets.h>
#include <string.h>

int main()
{
  		char buf[64];
        int msg_len;
        int s = socket(AF_VSOCK, SOCK_STREAM, 0);

        struct sockaddr_vm addr;
        memset(&addr, 0, sizeof(struct sockaddr_vm));
        addr.svm_family = AF_VSOCK;
        addr.svm_port = 9999;
        addr.svm_cid = VMADDR_CID_HOST;

        connect(s, &addr, sizeof(struct sockaddr_vm));
        send(s, "Hello, world!", 13, 0);
      

        printf("line %d recv from android start\n",__LINE__);
        msg_len = recv(s, &buf, 64, 0);
        printf("Received %d bytes: %s\n", msg_len, buf);
        
        while(1) {
                int ret = send(s, "Hello, world!", 13, 0);
                if(ret < 0) {
                        perror("send break");
                        break;
                }
                sleep(1);
        }
        close(s);
        printf("close !\n");

        return 0;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

5.epoll ser

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#include <linux/vm_sockets.h>

#define MAX_EVENTS  20
#define MAX_CLIENTS 20

int main() {
    int sockfd = socket(AF_VSOCK, SOCK_STREAM, 0);
    assert(sockfd != -1);

    struct sockaddr_vm saddr;
    memset(&saddr, 0, sizeof(saddr));
    saddr.svm_family = AF_VSOCK;
    saddr.svm_cid = VMADDR_CID_HOST;
    saddr.svm_port = 9999;

    int res = bind(sockfd, (struct sockaddr*)&saddr, sizeof(saddr));
    assert(res != -1);

    listen(sockfd, 5);

    int epollfd = epoll_create1(0);
    assert(epollfd != -1);

    struct epoll_event event;
    event.events = EPOLLIN;
    event.data.fd = sockfd;
    res = epoll_ctl(epollfd, EPOLL_CTL_ADD, sockfd, &event);
    assert(res != -1);

    struct epoll_event events[MAX_EVENTS];

    int num_clients = 0;
    int i;

    while (1) {
        int num_ready = epoll_wait(epollfd, events, MAX_EVENTS, -1);
        assert(num_ready != -1);

        for (i = 0; i < num_ready; i++) {
            if (events[i].data.fd == sockfd) {
                struct sockaddr_vm caddr;
                memset(&caddr, 0, sizeof(caddr));
                socklen_t len = sizeof(caddr);
                int c = accept(sockfd, (struct sockaddr*)&caddr, &len);
                if (c < 0) {
                    perror("accept error");
                    continue;
                }

                printf("accept = %d\n", c);
                if (num_clients >= MAX_CLIENTS) {
                    printf("Maximum number of clients reached. Rejecting new connection.\n");
                    close(c);
                    continue;
                }

                event.events = EPOLLIN | EPOLLRDHUP;
                event.data.fd = c;
                res = epoll_ctl(epollfd, EPOLL_CTL_ADD, c, &event);
                assert(res != -1);

                num_clients++;

            } else {
                int clientfd = events[i].data.fd;
                if (events[i].events & EPOLLIN) {
                    char recv_buff[128] = {0};
                    int n = recv(clientfd, recv_buff, sizeof(recv_buff) - 1, 0);
                    if (n <= 0) {
                        res = epoll_ctl(epollfd, EPOLL_CTL_DEL, clientfd, NULL);
                        //assert(res != -1);
                        if(res == -1) {
                             perror("epoll");
                        }

                        close(clientfd);
                        printf("close %d!\n", clientfd);
                        num_clients--;
                    } else {
                        recv_buff[n] = '\0';
                        printf("recv(%d)=%s\n", clientfd, recv_buff);
                        char send_buff[128];
                        sprintf(send_buff, "OK! your number %d", clientfd);
                        send(clientfd, send_buff, strlen(send_buff), 0);
                    }
                }

                if (events[i].events & (EPOLLRDHUP | EPOLLHUP | EPOLLERR)) {
                    res = epoll_ctl(epollfd, EPOLL_CTL_DEL, clientfd, NULL);
                    //assert(res != -1);
                    if(res == -1)
                    {
                        perror("epoll");
                    }

                    close(clientfd);
                    printf("close %d!\n", clientfd);
                    num_clients--;
                }
            }
        }
    }

    close(epollfd);
    close(sockfd);
    exit(0);
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116

6.vsock-perf

// SPDX-License-Identifier: GPL-2.0-only
/*
 * vsock_perf - benchmark utility for vsock.
 *
 * Copyright (C) 2022 SberDevices.
 *
 * Author: Arseniy Krasnov <AVKrasnov@sberdevices.ru>
 */
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <time.h>
#include <stdint.h>
#include <poll.h>
#include <sys/socket.h>
#include <linux/vm_sockets.h>
#include <sys/time.h>
#include <sys/syscall.h>

#define DEFAULT_BUF_SIZE_BYTES	(128 * 1024)
#define DEFAULT_TO_SEND_BYTES	(64 * 1024)
#define DEFAULT_VSOCK_BUF_BYTES (256 * 1024)
#define DEFAULT_RCVLOWAT_BYTES	1
#define DEFAULT_PORT		1234

#define BYTES_PER_GB		(1024 * 1024 * 1024ULL)
#define NSEC_PER_SEC		(1000000000ULL)
#define NSEC_PER_MSEC		(1000000ULL)

static unsigned int port = DEFAULT_PORT;
static unsigned long buf_size_bytes = DEFAULT_BUF_SIZE_BYTES;
static unsigned long vsock_buf_bytes = DEFAULT_VSOCK_BUF_BYTES;

static void error(const char *s)
{
	perror(s);
	exit(EXIT_FAILURE);
}

static time_t current_nsec(void)
{
	struct timespec ts;

	if (clock_gettime(CLOCK_REALTIME, &ts))
		error("clock_gettime");

	return (ts.tv_sec * NSEC_PER_SEC) + ts.tv_nsec;
}

/* From lib/cmdline.c. */
static unsigned long memparse(const char *ptr)
{
	char *endptr;

	unsigned long long ret = strtoull(ptr, &endptr, 0);

	switch (*endptr) {
	case 'E':
	case 'e':
		ret <<= 10;
	case 'P':
	case 'p':
		ret <<= 10;
	case 'T':
	case 't':
		ret <<= 10;
	case 'G':
	case 'g':
		ret <<= 10;
	case 'M':
	case 'm':
		ret <<= 10;
	case 'K':
	case 'k':
		ret <<= 10;
		endptr++;
	default:
		break;
	}

	return ret;
}

static void vsock_increase_buf_size(int fd)
{
	if (setsockopt(fd, AF_VSOCK, SO_VM_SOCKETS_BUFFER_MAX_SIZE,
		       &vsock_buf_bytes, sizeof(vsock_buf_bytes)))
		error("setsockopt(SO_VM_SOCKETS_BUFFER_MAX_SIZE)");

	if (setsockopt(fd, AF_VSOCK, SO_VM_SOCKETS_BUFFER_SIZE,
		       &vsock_buf_bytes, sizeof(vsock_buf_bytes)))
		error("setsockopt(SO_VM_SOCKETS_BUFFER_SIZE)");
}

static int vsock_connect(unsigned int cid, unsigned int port)
{
	union {
		struct sockaddr sa;
		struct sockaddr_vm svm;
	} addr = {
		.svm = {
			.svm_family = AF_VSOCK,
			.svm_port = port,
			.svm_cid = cid,
		},
	};
	int fd;

	fd = socket(AF_VSOCK, SOCK_STREAM, 0);

	if (fd < 0) {
		perror("socket");
		return -1;
	}

	if (connect(fd, &addr.sa, sizeof(addr.svm)) < 0) {
		perror("connect");
		close(fd);
		return -1;
	}

	return fd;
}

static float get_gbps(unsigned long bits, time_t ns_delta)
{
	return ((float)bits / 1000000000ULL) /
	       ((float)ns_delta / NSEC_PER_SEC);
}

static void run_receiver(unsigned long rcvlowat_bytes)
{
	unsigned int recv_cnt,send_cnt;
	time_t begin_ns;
	time_t total_ns;
	time_t in_recv_ns;
	time_t in_send_ns;
	size_t total_recv;
	size_t total_send;
	int client_fd;
	char *data;
	int fd;
	union {
		struct sockaddr sa;
		struct sockaddr_vm svm;
	} addr = {
		.svm = {
			.svm_family = AF_VSOCK,
			.svm_port = port,
			.svm_cid = VMADDR_CID_HOST,
		},
	};
	union {
		struct sockaddr sa;
		struct sockaddr_vm svm;
	} clientaddr;

	socklen_t clientaddr_len = sizeof(clientaddr.svm);

	printf("Run as receiver %d\n",addr.svm.svm_cid);
	printf("Listen port %u\n", port);
	printf("TX buffer %lu bytes\n", buf_size_bytes);
	printf("vsock buffer %lu bytes\n", vsock_buf_bytes);
	printf("SO_RCVLOWAT %lu bytes\n", rcvlowat_bytes);

	fd = socket(AF_VSOCK, SOCK_STREAM, 0);

	if (fd < 0)
		error("socket");
       
	if (bind(fd, &addr.sa, sizeof(addr.svm)) < 0)
		error("bind");

	if (listen(fd, 1) < 0)
		error("listen");

	client_fd = accept(fd, &clientaddr.sa, &clientaddr_len);

	if (client_fd < 0)
		error("accept");

	vsock_increase_buf_size(client_fd);

    if (setsockopt(client_fd, SOL_SOCKET, SO_RCVLOWAT,
		       &rcvlowat_bytes,
		       sizeof(rcvlowat_bytes)))
		error("setsockopt(SO_RCVLOWAT)");

    data = malloc(buf_size_bytes);

	if (!data) {
		fprintf(stderr, "'malloc()' failed\n");
		exit(EXIT_FAILURE);
	}

	recv_cnt = 0;
	send_cnt = 0;
	in_recv_ns = 0;
	in_send_ns = 0;
	total_recv = 0;
	total_send = 0;
	begin_ns = current_nsec();

	while (1) {
		struct pollfd fds = { 0 };

		fds.fd = client_fd;
		fds.events = POLLIN | POLLERR |
			     POLLHUP | POLLRDHUP;

		if (poll(&fds, 1, -1) < 0)
			error("poll");

		if (fds.revents & POLLERR) {
			fprintf(stderr, "'poll()' error\n");
			exit(EXIT_FAILURE);
		}

		if (fds.revents & POLLIN) {

			ssize_t bytes_recv,bytes_send = 0,tmp_bytes_send = 0;
			time_t t;

			t = current_nsec();
			bytes_recv = recv(client_fd, data, buf_size_bytes,0);
			in_recv_ns += (current_nsec() - t);
			recv_cnt++;

			if (!bytes_recv)
				break;

			if (bytes_recv < 0) {
				perror("recv");
				exit(EXIT_FAILURE);
			}

			total_recv += bytes_recv;
			while(tmp_bytes_send < bytes_recv) {
				t = current_nsec();
				bytes_send = send(client_fd, data, bytes_recv,0);
				in_send_ns += (current_nsec() - t);
				send_cnt++;

				if (!bytes_send)
					break;

				if (bytes_send < 0) {
					perror("send");
					exit(EXIT_FAILURE);
				}
				tmp_bytes_send += bytes_send;
				total_send += bytes_send;
			}
		}
		if (fds.revents & (POLLHUP | POLLRDHUP))
		break;
	}

	total_ns = current_nsec() - begin_ns;
	printf("total bytes received: %zu\n", total_recv);
	printf("tx performance: %f Gbits/s\n",
	       get_gbps(total_recv * 8, in_recv_ns));
	printf("total time in 'recv()': %f sec\n", (float)in_recv_ns / NSEC_PER_SEC);
	printf("average time in 'recv()': %f ns\n", (float)in_recv_ns / recv_cnt);
	printf("POLLIN wakeups: %i\n", recv_cnt);

	
	printf("total bytes send: %zu\n", total_send);
	printf("rx performance: %f Gbits/s\n",
	       get_gbps(total_send * 8,in_send_ns));
	printf("total time in 'send()': %f sec\n", (float)in_send_ns / NSEC_PER_SEC);
	printf("average time in 'send()': %f ns\n", (float)in_send_ns / send_cnt);

	printf("total time in 'send recv': %f sec\n",
	       (float)total_ns / NSEC_PER_SEC);
	printf("recv_cnt %d send_cnt %d \n",recv_cnt,send_cnt);

	printf("time-delay %lf ms\n",((double)total_ns / NSEC_PER_MSEC)/(recv_cnt + send_cnt));
	printf("throughput %lf Mbps\n",((double)(total_recv + total_send)*8)/(size_t)((float)total_ns / NSEC_PER_SEC)/(1000000));

	free(data);
	close(client_fd);
	close(fd);
}

static void run_sender(int peer_cid, unsigned long to_send_bytes)
{
	time_t begin_ns;
	time_t total_ns;
	time_t in_recv_ns;
	time_t in_send_ns;
	size_t total_send;
	size_t total_recv;
	size_t send_cnt;
	size_t recv_cnt;
	void *data;
	int fd;

	printf("Run as sender\n");
	printf("Connect to %i:%u\n", peer_cid, port);
	printf("Send %lu bytes\n", to_send_bytes);
	printf("TX buffer %lu bytes\n", buf_size_bytes);

	fd = vsock_connect(peer_cid, port);

	if (fd < 0)
		exit(EXIT_FAILURE);

	data = malloc(buf_size_bytes);

	if (!data) {
		fprintf(stderr, "'malloc()' failed\n");
		exit(EXIT_FAILURE);
	}

	memset(data, 0, buf_size_bytes);
	total_send = 0;
	total_recv = 0;
	in_send_ns = 0;
	in_recv_ns = 0;
	send_cnt = 0;
	recv_cnt = 0;
	begin_ns = current_nsec();
	while (total_send < to_send_bytes) {
		ssize_t sent,tmp_recvd = 0,recvd = 0;
		time_t t;

		t = current_nsec();
		sent = send(fd, data, buf_size_bytes, 0);
		in_send_ns += (current_nsec() - t);
		if (sent <= 0) {
			error("send");
			exit(EXIT_FAILURE);
		}

		send_cnt++;
		total_send += sent;
		while (tmp_recvd < sent)
		{
			t = current_nsec();
			recvd = recv(fd, data, sent, 0);
			in_recv_ns += (current_nsec() - t);
			if (recvd <= 0) {
				error("recv");
				exit(EXIT_FAILURE);
			}
			recv_cnt++;
			tmp_recvd += recvd;
			total_recv += recvd;
		}
	}

	total_ns = current_nsec() - begin_ns;

	printf("total bytes sent: %zu\n", total_send);
	printf("tx performance: %f Gbits/s\n",
	       get_gbps(total_send * 8, in_send_ns));
	printf("total time in 'send()': %f sec\n", (float)in_send_ns / NSEC_PER_SEC);
	printf("average time in 'send()': %f ns\n", (float)in_send_ns / send_cnt);

	printf("total bytes recv: %zu\n", total_recv);
	printf("rx performance: %f Gbits/s\n",
			get_gbps(total_recv * 8, in_recv_ns));
	printf("total time in 'recv()': %f sec\n", (float)in_recv_ns / NSEC_PER_SEC);
	printf("average time in 'recv()': %f ns\n", (float)in_recv_ns / recv_cnt);

	
	printf("total time in 'send recv': %f sec\n",
	       (float)total_ns / NSEC_PER_SEC);
	

	close(fd);
	free(data);
}

static const char optstring[] = "";
static const struct option longopts[] = {
	{
		.name = "help",
		.has_arg = no_argument,
		.val = 'H',
	},
	{
		.name = "sender",
		.has_arg = required_argument,
		.val = 'S',
	},
	{
		.name = "port",
		.has_arg = required_argument,
		.val = 'P',
	},
	{
		.name = "bytes",
		.has_arg = required_argument,
		.val = 'M',
	},
	{
		.name = "buf-size",
		.has_arg = required_argument,
		.val = 'B',
	},
	{
		.name = "vsk-size",
		.has_arg = required_argument,
		.val = 'V',
	},
	{
		.name = "rcvlowat",
		.has_arg = required_argument,
		.val = 'R',
	},
	{},
};

static void usage(void)
{
	printf("Usage: ./vsock_perf [--help] [options]\n"
	       "\n"
	       "This is benchmarking utility, to test vsock performance.\n"
	       "It runs in two modes: sender or receiver. In sender mode, it\n"
	       "connects to the specified CID and starts data transmission.\n"
	       "\n"
	       "Options:\n"
	       "  --help			This message\n"
	       "  --sender   <cid>		Sender mode (receiver default)\n"
	       "                                <cid> of the receiver to connect to\n"
	       "  --port     <port>		Port (default %d)\n"
	       "  --bytes    <bytes>KMG		Bytes to send (default %d)\n"
	       "  --buf-size <bytes>KMG		Data buffer size (default %d). In sender mode\n"
	       "                                it is the buffer size, passed to 'write()'. In\n"
	       "                                receiver mode it is the buffer size passed to 'read()'.\n"
	       "  --vsk-size <bytes>KMG		Socket buffer size (default %d)\n"
	       "  --rcvlowat <bytes>KMG		SO_RCVLOWAT value (default %d)\n"
	       "\n", DEFAULT_PORT, DEFAULT_TO_SEND_BYTES,
	       DEFAULT_BUF_SIZE_BYTES, DEFAULT_VSOCK_BUF_BYTES,
	       DEFAULT_RCVLOWAT_BYTES);
	exit(EXIT_FAILURE);
}

static long strtolx(const char *arg)
{
	long value;
	char *end;

	value = strtol(arg, &end, 10);

	if (end != arg + strlen(arg))
		usage();

	return value;
}

int main(int argc, char **argv)
{
	unsigned long to_send_bytes = DEFAULT_TO_SEND_BYTES;	/*64k*/
	unsigned long rcvlowat_bytes = DEFAULT_RCVLOWAT_BYTES;	
	int peer_cid = -1;
	bool sender = false;

	while (1) {
		int opt = getopt_long(argc, argv, optstring, longopts, NULL);

		if (opt == -1)
			break;

		switch (opt) {
		case 'V': /* Peer buffer size. */
			vsock_buf_bytes = memparse(optarg);
			break;
		case 'R': /* SO_RCVLOWAT value. */
			rcvlowat_bytes = memparse(optarg);
			break;
		case 'P': /* Port to connect to. */
			port = strtolx(optarg);
			break;
		case 'M': /* Bytes to send. */
			to_send_bytes = memparse(optarg);
			break;
		case 'B': /* Size of rx/tx buffer. */
			buf_size_bytes = memparse(optarg);
			break;
		case 'S': /* Sender mode. CID to connect to. */
			peer_cid = strtolx(optarg);
			sender = true;
			break;
		case 'H': /* Help. */
			usage();
			break;
		default:
			usage();
		}
	}

	if (!sender)
		run_receiver(rcvlowat_bytes);
	else
		run_sender(peer_cid, to_send_bytes);

	return 0;
}



  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318
  • 319
  • 320
  • 321
  • 322
  • 323
  • 324
  • 325
  • 326
  • 327
  • 328
  • 329
  • 330
  • 331
  • 332
  • 333
  • 334
  • 335
  • 336
  • 337
  • 338
  • 339
  • 340
  • 341
  • 342
  • 343
  • 344
  • 345
  • 346
  • 347
  • 348
  • 349
  • 350
  • 351
  • 352
  • 353
  • 354
  • 355
  • 356
  • 357
  • 358
  • 359
  • 360
  • 361
  • 362
  • 363
  • 364
  • 365
  • 366
  • 367
  • 368
  • 369
  • 370
  • 371
  • 372
  • 373
  • 374
  • 375
  • 376
  • 377
  • 378
  • 379
  • 380
  • 381
  • 382
  • 383
  • 384
  • 385
  • 386
  • 387
  • 388
  • 389
  • 390
  • 391
  • 392
  • 393
  • 394
  • 395
  • 396
  • 397
  • 398
  • 399
  • 400
  • 401
  • 402
  • 403
  • 404
  • 405
  • 406
  • 407
  • 408
  • 409
  • 410
  • 411
  • 412
  • 413
  • 414
  • 415
  • 416
  • 417
  • 418
  • 419
  • 420
  • 421
  • 422
  • 423
  • 424
  • 425
  • 426
  • 427
  • 428
  • 429
  • 430
  • 431
  • 432
  • 433
  • 434
  • 435
  • 436
  • 437
  • 438
  • 439
  • 440
  • 441
  • 442
  • 443
  • 444
  • 445
  • 446
  • 447
  • 448
  • 449
  • 450
  • 451
  • 452
  • 453
  • 454
  • 455
  • 456
  • 457
  • 458
  • 459
  • 460
  • 461
  • 462
  • 463
  • 464
  • 465
  • 466
  • 467
  • 468
  • 469
  • 470
  • 471
  • 472
  • 473
  • 474
  • 475
  • 476
  • 477
  • 478
  • 479
  • 480
  • 481
  • 482
  • 483
  • 484
  • 485
  • 486
  • 487
  • 488
  • 489
  • 490
  • 491
  • 492
  • 493
  • 494
  • 495
  • 496
  • 497
  • 498
  • 499
  • 500
  • 501
  • 502
  • 503
  • 504
  • 505
  • 506
  • 507
  • 508

三、遇到的问题

问题1:Running postconf script ‘/usr/bin/python3 /home/yyh/kernel/qemu-8.0.2/scripts/symlink-install-tree.py’

NOTICE: You are using Python 3.6 which is EOL. Starting with v0.62.0, Meson will require Python 3.7 or newer

解决方法:

sudo apt-get install python3.7
which python3.7
sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.7 1
python3 --version
  • 1
  • 2
  • 3
  • 4

问题2:Traceback (most recent call last):File “/usr/lib/command-not-found”, line 28, in

from CommandNotFound import CommandNotFound
File “/usr/lib/python3/dist-packages/CommandNotFound/CommandNotFound.py”, line 19, in
from CommandNotFound.db.db import SqliteDatabase
File “/usr/lib/python3/dist-packages/CommandNotFound/db/db.py”, line 5, in
import apt_pkg
ModuleNotFoundError: No module named ‘apt_pkg’
参考:https://blog.csdn.net/qq_35191755/article/details/108199567

解决方法:

sudo apt-get remove --purge python-apt
sudo apt-get install -f -y python-apt

sudo cp /usr/lib/python3/dist-packages/apt_pkg.cpython-36m-x86_64-linux-gnu.so apt_pkg.cpython-37m-x86_64-linux-gnu.so
sudo apt-get update
  • 1
  • 2
  • 3
  • 4
  • 5

问题3:Err:1 http://security.ubuntu.com/ubuntu bionic-security InRelease

Could not resolve ‘security.ubuntu.com’
参考:https://blog.csdn.net/qq_29720657/article/details/109066682

解决方法

#vi /etc/resolv.conf
nameserver 8.8.8.8
nameserver 8.8.4.4
sudo service network-manager restart
  • 1
  • 2
  • 3
  • 4

问题4:qemu-system-aarch64: -device vhost-vsock-device,guest-cid=3: vhost-vsock: failed to open vhost device: No such device

参考:https://blog.csdn.net/kunyus/article/details/106986621

解决方法

运行下面命令,创建配置文件 /etc/modprobe.d/blacklist-vmware.conf。然后重启sudo reboot

sudo tee /etc/modprobe.d/blacklist-vmware.conf << EOF
blacklist vmw_vsock_virtio_transport_common
blacklist vmw_vsock_vmci_transport
EOF
  • 1
  • 2
  • 3
  • 4

原因

这是由于linux 检测到在 vmware 环境中运行时,会加载一些 vmware 的模块并使用 vsock 从而产生了冲突。

可以通过命令lsmod | grep vsock来查看哪些模块产生了冲突。
命令输出:
core@ubuntu20-dev:~$ lsmod | grep vsock
vmw_vsock_virtio_transport_common    32768  0
vmw_vsock_vmci_transport    32768  1
vsock                  36864  3 vmw_vsock_virtio_transport_common,vmw_vsock_vmci_transport
vmw_vmci               69632  2 vmw_balloon,vmw_vsock_vmci_transport
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

问题5:ubuntu设置共享文件夹时不显示解决方案

参考:
https://blog.csdn.net/qq_45953886/article/details/126020253

问题6:python升级

ERROR: Cannot use ‘/usr/bin/python’, Python >= 3.6 is required.
Use --python=/path/to/python to specify a supported Python.
参考:
https://blog.csdn.net/qq_38587510/article/details/104303929?spm=1001.2101.3001.6650.5&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-5-104303929-blog-104701295.235%5Ev38%5Epc_relevant_default_base3&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-5-104303929-blog-104701295.235%5Ev38%5Epc_relevant_default_base3&utm_relevant_index=10

问题7: ERROR: Cannot find Ninja

sudo apt update
sudo apt install ninja-build
#sudo dnf install ninja-build
#sudo pacman -S ninja
  • 1
  • 2
  • 3
  • 4

问题8:ERROR: You need at least GCC v7.4 or Clang v10.0 (or XCode Clang v12.0)

sudo add-apt-repository ppa:ubuntu-toolchain-r/test
sudo apt update

sudo apt install gcc-8
sudo rm /usr/bin/gcc
sudo ln -s /usr/bin/gcc-8 /usr/bin/gcc

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/439758
推荐阅读
相关标签
  

闽ICP备14008679号