当前位置: 首页 > news >正文

cuda gdb调试

如果cudaDeviceEnablePeerAccess函数不支持或不起作用,您仍然可以尝试其他方法来实现GPU之间的数据交换和通信。以下是一些替代方法:

通过主机内存进行数据传输:
如果GPU之间的数据交换不是非常频繁,您可以将数据从一个GPU复制到主机内存,然后再从主机内存复制到另一个GPU。这可以通过cudaMemcpy函数来实现。

使用Unified Memory:
CUDA的Unified Memory允许多个GPU共享同一块内存。您可以在多个GPU之间创建统一内存分配,并在它们之间共享数据。这可以通过cudaMallocManaged函数来实现。请注意,这种方法可能会引入一些性能开销。

使用NvLink:
如果您的GPU之间支持NvLink连接,您可以通过NvLink通道进行高速数据传输。NvLink是一种高速连接技术,适用于支持的NVIDIA GPU。它通常用于连接同一台服务器上的多个GPU。

使用MPI(Message Passing Interface):
如果您的系统中有多个计算节点,您可以使用MPI库来在不同的计算节点之间进行数据传输和通信。这对于在分布式系统中进行大规模并行计算非常有用。

使用CUDA库:
NVIDIA提供了一些用于GPU之间数据交换的库,如NCCL(NVIDIA Collective Communications Library)。这些库专门用于在多个GPU之间实现高效的数据交换和通信。

使用 Inter-Process Communication (IPC): 如果你的 GPUs 位于不同的进程中,你可以使用 Inter-Process Communication(IPC)机制来实现 GPU 之间的数据交换。CUDA 提供了 IPC 功能,允许不同进程中的 CUDA 上下文之间进行数据传输

Unified Memory

__global__ void initializeData(float* data, int size) {int idx = blockIdx.x * blockDim.x + threadIdx.x;if (idx < size) {data[idx] = static_cast<float>(idx); // Initialize data with some values}
} 
float* unifiedData;cudaMallocManaged(&unifiedData, totalSize * sizeof(float));// Initialize data on all GPUs using Unified Memoryfor (int gpuId = 0; gpuId < NUM_GPUS; ++gpuId) {cudaSetDevice(gpuId);initializeData<<<gridDims, blockDims>>>(unifiedData + gpuId * chunkSize, chunkSize);}

使用CUDA进行并行计算和数据初始化。你先定义了一个名为initializeData的CUDA内核函数,然后使用Unified Memory在多个GPU上初始化数据。

  1. initializeData内核函数:这个内核函数用于在每个线程块中初始化一部分数据。idx表示线程在数据中的索引,根据线程块和线程的索引计算出。只有当idx小于要初始化的数据大小时,线程会将其索引值转化为浮点数并赋值给数据数组中的相应位置。

  2. cudaMallocManaged:使用 cudaMallocManaged 分配的统一内存数组,用于在多个GPU上共享数据。unifiedData将指向这块分配的内存,其大小为totalSize * sizeof(float)字节。

  3. 数据初始化循环:在这个循环中,你使用了多个GPU来执行初始化任务。通过使用cudaSetDevice函数来指定每个GPU,并在每个GPU上使用initializeData内核函数来初始化数据。unifiedData + gpuId * chunkSize 是将数组指针定位到每个GPU对应的位置,以便在统一内存中进行初始化
    为了确保在所有GPU上都初始化数据完成,循环结束后使用cudaDeviceSynchronize来同步所有的GPU。

注意事项:

  • 在使用CUDA进行并行计算时,确保你在代码中正确地处理内存分配、数据传输和同步操作,以避免出现内存泄漏、数据不一致等问题。
  • 在实际应用中,还需要定义和初始化一些NUM_GPUSgridDimsblockDimstotalSizechunkSize等。
  • 下载 Linux 和 Unix 版本

在 Linux 上安装 Git 最简单的方法是使用 Linux 发行版的首选软件包管理器。如果你喜欢从源代码构建,可以在 kernel.org 上找到压缩包。最新版本为 2.41.0。

Debian/Ubuntu
获取您的 Debian/Ubuntu 发行版的最新稳定版本

# apt-get install git

对于 Ubuntu,该 PPA 提供最新稳定的上游 Git 版本

# add-apt-repository ppa:git-core/ppa # apt update; apt install git

Fedora

# yum install git(至 Fedora 21
# dnf install git(Fedora 22 及更高版本)

Gentoo

# emerge --ask --verbose dev-vcs/git

Arch Linux

# pacman -S git

openSUSE

# zypper install git

玛吉娅

# urpmi git

尼克斯/尼克斯操作系统

nix-env -i git

FreeBSD

pkg install git

Solaris 9/10/11 (OpenCSW)

pkgutil -i git

Solaris 11 Express

pkg install developer/versioning/git

OpenBSD

pkg_add git

阿尔卑斯
$ apk add git
Red Hat Enterprise Linux、Oracle Linux、CentOS、Scientific Linux 等。
RHEL 及其衍生版本通常会提供旧版本的 git。你可以下载一个压缩包并从源代码开始构建,或者使用第三方软件源(如 IUS Community Project)来获取较新版本的 git。

斯利塔兹
要在 VS Code 中设置 CUDA 代码的调试,请按照以下步骤操作:

安装 CUDA 工具包和 VS Code:
确保您的 Ubuntu 22.04 系统上安装了 CUDA Toolkit 和 Visual Studio Code。

打开您的项目文件夹:
在 VS Code 中打开 CUDA 项目的根目录。

安装所需的扩展:
如果尚未安装,请在 VS Code 中安装 CUDA 调试所需的扩展:

微软的“C/C++”
NVIDIA 的“CUDA”
创建launch.json:
要生成用于调试 CUDA 代码的 launch.json 文件,请执行以下步骤:

单击窗口一侧活动栏中的“运行和调试”按钮(或按 F5)。
选择“创建 launch.json 文件”选项。
选择“CUDA C++ (CUDA-GDB)”作为环境。
配置launch.json:
选择环境后,会在项目的.vscode目录下生成launch.json文件。 您可以根据需要修改 launch.json 文件以匹配您的设置。 这是一个配置示例:

{"version": "0.2.0","configurations": [{"name": "CUDA Debug","type": "cppdbg","request": "launch","program": "${workspaceFolder}/path/to/your/executable", // Path to your compiled CUDA executable"args": [], // Command line arguments if any"stopAtEntry": false,"cwd": "${workspaceFolder}","environment": [],"externalConsole": false,"MIMode": "gdb","setupCommands": [{"description": "Enable pretty-printing for CUDA","text": "-enable-pretty-printing","ignoreFailures": true}],"miDebuggerPath": "/usr/local/cuda/bin/cuda-gdb" // Path to cuda-gdb executable}]
}

设置断点:
打开需要调试的CUDA源文件,根据需要设置断点。

开始调试:

再次单击“运行和调试”按钮(或按 F5)。
选择“CUDA 调试”配置。
调试器将启动,执行将在断点处停止。

launch.json文件的内容

{"version": "0.2.0","configurations": [{"name": "CUDA C++ Launch","type": "cppdbg","request": "launch","program": "${workspaceFolder}/p2p", // 修正为 ${workspaceFolder}"args": [],"stopAtEntry": false,"cwd": "${workspaceFolder}" // 修正为 ${workspaceFolder}}]
}

https://blog.csdn.net/wohu1104/article/details/111464778
https://blog.csdn.net/weixin_42145502/article/details/107455999

在这里插入图片描述

用cuda c++(cuda dgb) 打断点

我的是打完断点不停,直接输出了,按着下面的步骤操作可以进行正常的打断点

在这里插入图片描述

# user@user-SYS-420GP-TNR:~/lcr/try$ nvcc -g -o example example.cu
# user@user-SYS-420GP-TNR:~/lcr/try$ cuda-gdb ./example
# 输出
NVIDIA (R) CUDA Debugger
11.5 release
Portions Copyright (C) 2007-2021 NVIDIA Corporation
GNU gdb (GDB) 10.1
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:<http://www.gnu.org/software/gdb/documentation/>.For help, type "help".
--Type <RET> for more, q to quit, c to continue without paging--

在这里插入图片描述

# user@user-SYS-420GP-TNR:~/lcr/try$ nvcc -g -o example example.cu
# user@user-SYS-420GP-TNR:~/lcr/try$ cuda-gdb ./example
# 输出
NVIDIA (R) CUDA Debugger
11.5 release
Portions Copyright (C) 2007-2021 NVIDIA Corporation
GNU gdb (GDB) 10.1
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:<http://www.gnu.org/software/gdb/documentation/>.For help, type "help".
--Type <RET> for more, q to quit, c to continue without paging--

在这里插入图片描述

# user@user-SYS-420GP-TNR:~/lcr/try$ cuda-gdb ./example# 输出
NVIDIA (R) CUDA Debugger
11.5 release
Portions Copyright (C) 2007-2021 NVIDIA Corporation
GNU gdb (GDB) 10.1
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:<http://www.gnu.org/software/gdb/documentation/>.For help, type "help".
--Type <RET> for more, q to quit, c to continue without paging--break example.cu:1034
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./example...
(cuda-gdb) 
(cuda-gdb) run
Starting program: /home/user/lcr/try/example 
hello world
1,1
[Inferior 1 (process 1786635) exited normally]
(cuda-gdb

在您的 CUDA GDB 会话中,看起来您已经成功地设置了断点并启动了程序。根据您提供的输出,程序似乎已经在断点处停下,并成功执行了打印语句。

在输出中,“hello world” 是您的程序输出的信息。然后,您可以看到调试器显示的行号是 1,1,这可能是因为 CUDA GDB 在 GPU 核心执行 CUDA 代码时可能不会显示准确的行号信息。
在这里插入图片描述

相关文章:

cuda gdb调试

如果cudaDeviceEnablePeerAccess函数不支持或不起作用&#xff0c;您仍然可以尝试其他方法来实现GPU之间的数据交换和通信。以下是一些替代方法&#xff1a; 通过主机内存进行数据传输&#xff1a; 如果GPU之间的数据交换不是非常频繁&#xff0c;您可以将数据从一个GPU复制到…...

【vim 学习系列文章 5 - cscope 过滤掉某些目录】

文章目录 cscope 过滤目录介绍 cscope 过滤目录介绍 第一步创建自己的cscope脚本~/.local/bin/cscope.sh&#xff0c;如下&#xff1a; function my_cscope() {CODE_PATHpwdecho "$CODE_PATH"echo "start cscope...."if [ ! -f "$CODE_PATH/cscope.…...

实验三 HBase1.2.6安装及配置

系列文章目录 文章目录 系列文章目录前言一、HBase1.2.6的安装二、HBase1.2.6的配置2.1 单机模式配置2.2 伪分布式模式配置 总结参考 前言 在安装HBase1.2.6之前&#xff0c;需要安装好hadoop2.7.6。 本篇文章参考&#xff1a;HBase2.2.2安装和编程实践指南 一、HBase1.2.6的安…...

LightDB sequence支持MAXVALUE最大值与Oracle相同

功能介绍 Oracle数据库在创建sequence的时候可以支持设置maxvalue 为9999999999999999999999999999&#xff0c;这样的SQL在LightDB23.3版本之前都是执行失败的。为了方便Oracle用户迁移到LightDB上&#xff0c;在LightDB23.3版本上&#xff0c;增加了sequence支持maxvalue设置…...

二、Kafka快速入门

目录 2.1 安装部署1、【单机部署】2、【集群部署】 2.2 Kafka命令行操作1、查看topic相关命令参数2、查看当前kafka服务器中的所有Topic3、创建 first topic4、查看 first 主题的详情5、修改分区数&#xff08;注意&#xff1a;分区数只能增加&#xff0c;不能减少&#xff09;…...

消息中间件-kafka实战-第五章-kafka重复消费、顺序消费及死信队列

目录 一、参考二、路由规则&#xff08;分片规则&#xff09;三、触发重复消费的场景场景一&#xff1a;触发rebalance问题描述可能原因实际影响参数在kafka0.10.1 之前:在kafka0.10.1之后&#xff1a;解决方案 场景二&#xff1a;服务宕机可能原因解决方案 消息幂等性 四、kaf…...

python爬虫9:实战2

python爬虫9&#xff1a;实战2 前言 ​ python实现网络爬虫非常简单&#xff0c;只需要掌握一定的基础知识和一定的库使用技巧即可。本系列目标旨在梳理相关知识点&#xff0c;方便以后复习。 申明 ​ 本系列所涉及的代码仅用于个人研究与讨论&#xff0c;并不会对网站产生不好…...

从业务层的代码出发,去排查通用框架代码崩溃的问题

目录 1、问题说明 1.1、Release下崩溃&#xff0c;Debug下很难复现 1.2、用Windbg打开dump文件&#xff0c;发现崩溃在通用的框架代码中 2、进一步分析 2.1、使用IDA查看汇编代码尝试寻找崩溃的线索 2.2、在Windbg中查看相关变量的值 2.3、查看最近代码的修改记录&#…...

LLM预训练大型语言模型Pre-training large language models

在上一个视频中&#xff0c;您被介绍到了生成性AI项目的生命周期。 如您所见&#xff0c;在您开始启动您的生成性AI应用的有趣部分之前&#xff0c;有几个步骤需要完成。一旦您确定了您的用例范围&#xff0c;并确定了您需要LLM在您的应用程序中的工作方式&#xff0c;您的下…...

[Machine Learning] 损失函数和优化过程

文章目录 机器学习算法的目的是找到一个假设来拟合数据。这通过一个优化过程来实现&#xff0c;该过程从预定义的 hypothesis class&#xff08;假设类&#xff09;中选择一个假设来最小化目标函数。具体地说&#xff0c;我们想找到 arg min ⁡ h ∈ H 1 n ∑ i 1 n ℓ ( X i…...

serialVersionUID 有何用途?如果没定义会有什么问题?

序列化是将对象的状态信息转换为可存储或传输的形式的过程。我们都知道&#xff0c;Java 对象是保持在 JVM 的堆内存中的&#xff0c;也就是说&#xff0c;如果 JVM 堆不存在了&#xff0c;那么对象也就跟着消失了。 而序列化提供了一种方案&#xff0c;可以让你在即使 JVM 停机…...

C# OpenCvSharp DNN 二维码增强 超分辨率

效果 项目 代码 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using OpenCvSharp; using OpenCvSharp.Dnn; using OpenCvSh…...

this.$refs使用方法

深入理解和使用this.$refs——Vue.js的利器 Vue.js是一个流行的JavaScript框架&#xff0c;用于构建交互性强大的用户界面。在Vue.js中&#xff0c;this.$refs是一个强大的特性&#xff0c;允许你直接访问组件中的DOM元素或子组件实例。本教程将带你深入了解this.$refs的使用方…...

Ohio主题 - 创意组合和代理机构WordPress主题

Ohio主题是一个精心制作的多用途、简约、华丽、多功能的组合和创意展示主题&#xff0c;具有敏锐的用户体验&#xff0c;您需要构建一个现代且实用的网站&#xff0c;并开始销售您的产品和服务。它配备了最流行的WordPress页面构建器 WPBakery Page Builder&#xff08;以前称为…...

mysql 、sql server trigger 触发器

sql server mySQL create trigger 触发器名称 { before | after } [ insert | update | delete ] on 表名 for each row 触发器执行的语句块## 表名&#xff1a; 表示触发器监控的对象 ## before | after : 表示触发的时间&#xff0c;before : 表示在事件之前触发&am…...

自然语言处理从入门到应用——LangChain:索引(Indexes)-[检索器(Retrievers)]

分类目录&#xff1a;《自然语言处理从入门到应用》总目录 检索器&#xff08;Retrievers&#xff09;是一个通用的接口&#xff0c;方便地将文档与语言模型结合在一起。该接口公开了一个get_relevant_documents方法&#xff0c;接受一个查询&#xff08;字符串&#xff09;并返…...

春秋云境:CVE-2022-0543(Redis 沙盒逃逸漏洞)

目录 一、i春秋题目 二、CVE-2022-0543&#xff1a;&#xff08;redis沙盒逃逸&#xff09; 漏洞介绍&#xff1a; 漏洞复现&#xff1a; 一、i春秋题目 靶标介绍&#xff1a; Redis 存在代码注入漏洞&#xff0c;攻击者可利用该漏洞远程执行代码。 进入题目&#xff1a;…...

关于uniapp组件的坑

关于uniapp组件的坑 我有一个组件写的没什么问题,但是报下面这个错误 is not found in path “components/xxx/xxxx” (using by “components/yyy/yyy”) 最后经过排除发现命名需要驼峰命名法 我原本组件命名: 文件夹名 test_tttt 文件名 test_tttt.vue 不行 最后改成文件…...

AIGC与软件测试的融合

一、ChatGPT与AIGC 生成式人工智能——AIGC&#xff08;Artificial Intelligence Generated Content&#xff09;&#xff0c;是指基于生成对抗网络、大型预训练模型等人工智能的技术方法&#xff0c;通过已有数据的学习和识别&#xff0c;以适当的泛化能力生成相关内容的技术。…...

滑动验证码-elementui实现

使用elementui框架实现 html代码 <div class"button-center"><el-popoverplacement"top":width"imgWidth"title"安全验证"trigger"manual"v-model"popoverVisible"hide"popoverHide"show&quo…...

ubuntu 20.04 安装 高版本cuda 11.7 和 cudnn最新版

一、安装显卡驱动 参考另一篇文章&#xff1a;Ubuntu20.04安装Nvidia显卡驱动教程_ytusdc的博客-CSDN博客 二、安装CUDA 英伟达官网&#xff08;最新版&#xff09;&#xff1a;CUDA Toolkit 12.2 Update 1 Downloads | NVIDIA Developer CUDA历史版本下载地址&#xff1a;C…...

svg图片如何渲染到页面,以及svg文件的上传

svg图片渲染到页面的几种方式 背景&#x1f7e1;require.context获取目录下的所有文件&#x1f7e1;方式1: 直接在html中渲染&#x1f7e1;方式: 发起ajax请求&#xff0c;获取SVG文件 背景 需要实现从本地目录下去获取所有的svg图标进行预览&#xff0c;将选中的图片显示在另…...

GPT-LLM-Trainer:如何使用自己的数据轻松快速地微调和训练LLM

一、前言 想要轻松快速地使用您自己的数据微调和培训大型语言模型&#xff08;LLM&#xff09;&#xff1f;我们知道训练大型语言模型具有挑战性并需要耗费大量计算资源&#xff0c;包括收集和优化数据集、确定合适的模型及编写训练代码等。今天我们将介绍一种实验性新方法&am…...

深入理解ForkJoin

任务类型 线程池执行的任务可以分为两种&#xff1a;CPU密集型任务和IO密集型任务。在实际的业务场景中&#xff0c;我们需要根据任务的类型来选择对应的策略&#xff0c;最终达到充分并合理地使用CPU和内存等资源&#xff0c;最大限度地提高程序性能的目的。 CPU密集型任务 …...

Spring5学习笔记—AOP编程

✅作者简介&#xff1a;大家好&#xff0c;我是Leo&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Leo的博客 &#x1f49e;当前专栏&#xff1a; Spring专栏 ✨特色专栏&#xff1a; M…...

适用于 Docker 用户的 kubectl

适用于 Docker 用户的 kubectl 你可以使用 Kubernetes 命令行工具 kubectl 与 API 服务器进行交互。如果你熟悉 Docker 命令行工具&#xff0c; 则使用 kubectl 非常简单。但是&#xff0c;Docker 命令和 kubectl 命令之间有一些区别。以下显示了 Docker 子命令&#xff0c; 并…...

网络安全设备篇——加密机

加密机是一种专门用于数据加密和解密的网络安全设备。它通过使用密码学算法对数据进行加密&#xff0c;从而保护数据的机密性和完整性。加密机通常被用于保护敏感数据&#xff0c;如金融信息、个人身份信息等。 加密机的主要功能包括&#xff1a; 数据加密&#xff1a;加密机使…...

Rust 基础入门 —— 2.3.所有权和借用

Rust 的最主要光芒&#xff1a; 内存安全 。 实现方式&#xff1a; 所有权系统。 写在前面的序言 因为我们这里实际讲述的内容是关于 内存安全的&#xff0c;所以我们最好先复习一下内存的知识。 然后我们&#xff0c;需要理解的就只有所有权概念&#xff0c;以及为了开发便…...

Node.js-Express框架基本使用

Express介绍 Express是基于 node.js 的web应用开发框架&#xff0c;是一个封装好的工具包&#xff0c;便于开发web应用&#xff08;HTTP服务&#xff09; Express基本使用 // 1.安装 npm i express // 2.导入 express 模块 const express require("express"); // 3…...

阿里云通用算力型u1云服务器CPU性能详细说明

​阿里云服务器u1是通用算力型云服务器&#xff0c;CPU采用2.5 GHz主频的Intel(R) Xeon(R) Platinum处理器&#xff0c;通用算力型u1云服务器不适用于游戏和高频交易等需要极致性能的应用场景及对业务性能一致性有强诉求的应用场景(比如业务HA场景主备机需要性能一致)&#xff…...

学做网站赚钱方法/关键词优化公司如何选择

程序在开始处有一条注释&#xff08;使用新的注释风格&#xff09;&#xff0c;给出了文件名和程序的目的。写这种程序说明很简单、不费时&#xff0c;而且在以后浏览或打印程序时很有帮助。...

网站建设b2b/免费的网站软件

firebug因此&#xff0c;您可能想知道为什么只有在浏览器中打开Firebug时才运行jQuery代码。 嗯&#xff0c;这可能是因为您在代码中使用了console.log命令&#xff0c;而jQuery代码失败是因为控制台不存在。 要解决此简单问题&#xff0c;请将console.log和firebug命令放在以…...

wordpress linux 静态/吴中seo页面优化推广

opporeno5pro可是一款刚刚上市没有多久的手机&#xff0c;小伙伴们都是想要知道这款手机是否是支持着5G&#xff0c;并且能否使用北斗导航&#xff0c;现在就有小编来为大家解答吧。一、opporeno5pro支持5G&#xff0c;支持北斗导航吗opporeno5pro是支持着双模5G&#xff0c;还…...

海南城乡建设庁网站/汕头seo排名收费

_新生儿出血症的病因是什么?隔挡式褶皱“我的电脑”窗口中文档的详细资料一般包括“名称”、大小、类型和修改时间这四项。在确定进口货物完税价格时&#xff0c;货物成交价格中含进口人向卖方支付的佣金&#xff0c;应该从完税价格中扣除。新生儿出血症的病因是什么?关于锐器…...

招牌设计 创意logo/短视频seo推广隐迅推专业

机器学习之分类回归树 (python 实现 CART)之前有文章介绍过决策树 (ID3) 简单回顾一下: ID3 每次选取最佳特征来分割数据, 这个最佳特征的判断原则是通过信息增益来实现的按照某种特征切分数据后, 该特征在以后切分数据集时就不再使用, 因此存在切分过于迅速的问题 ID3 算法还不…...

西宁网站建设报价/百度推广后台登陆首页

WebView 上传图片, 想必很多人都碰到过这样的场景. 而且 WebView 在4.4前后的区别非常大, 比如对URL跳转的格式, 对JS的注入声明等等, 4.4以后的WebView 已经是chromium内核, 有多强大就无需我赘述. 说这些, 其实也是为了说明也因为WebView的前后变化太大了, 所以在低版本和版本…...