DP の読み方: Kunpeng プロセッサ アーキテクチャとプログラミング (14) ACPI とソフトウェア アーキテクチャ固有のチューニング

オペレーティングシステムのカーネル

ACPI (Advanced Configuration and Power Interface) は、
Intel、Microsoft、HP、Sony などの企業が共同開発した電源管理規格です。これは、コンピュータ システムの電源状態、パフォーマンス、および構成の側面を管理するための共通の電源管理インターフェイスを提供します。

コンピュータ システムでは、 ACPI はシステムの起動、シャットダウン、休止状態、ウェイクアップなどの電源管理イベントの処理を担当します。また、ハードウェア デバイス、冷却デバイス、バッテリー、その他のデバイスの制御も提供します。

ACPI はコンピュータ システムにおいて重要な役割を果たし、システムのエネルギー効率とバッテリ寿命を向上させると同時に、より優れたシステム パフォーマンスと安定性を提供します。
ACPIのARM図
ARM64 プラットフォームのデバイス ツリーは、arch/arm64/boot/dts/Linux ソース コードのディレクトリで定義されます。デバイス ツリーは、システム ハードウェアを記述するために使用されるデータ構造であり、ブート プロセス中にハードウェアを初期化するために使用されます。

以下は、基本概念を理解するためだけに、仮想デバイス ツリーである単純な ARM64 プラットフォーム デバイス ツリーの例です。実際のデバイス ツリーには、より詳細なプロパティと構成が表示されます。
申し訳ありませんが、C コードを直接扱うことはできません。ただし、ARM64 プラットフォームのデバイス ツリー (デバイス ツリー) の基本構造を理解するのに役立ち、例を示すことはできます。


git clone https://github.com/torvalds/linux.git
cd linux
cd scripts/dtc/

make
sudo make install PREFIX=/usr/local


// SPDX-License-Identifier: GPL-2.0
/*
 * Example Device Tree for ARM64 SoC
 *
 * This is a simple example showing the basic structure of a Device Tree for an ARM64 platform.
 */

/dts-v1/;

/ {
    
    
    compatible = "example,arm64";
    model = "Example ARM64 SoC";

    memory@80000000 {
    
    
        device_type = "memory";
        reg = <0x0 0x80000000 0x0 0x80000000>; // 2 GiB of memory starting from 0x80000000
    };

    chosen {
    
    
        bootargs = "console=ttyAMA0,115200";
    };

    uart@9000000 {
    
    
        compatible = "example,uart";
        reg = <0x0 0x9000000 0x0 0x1000>;
        interrupt-parent = <&gic>;
        interrupts = <0 13 4>; // interrupt number 13, active high, level triggered
    };

    gic: interrupt-controller {
    
    
        compatible = "example,gic-v3";
        interrupt-controller;
        #interrupt-cells = <3>;
        interrupt-parent = <&gic_cpuif>;
    };

    gic_cpuif: interrupt-controller@5000 {
    
    
        compatible = "example,gic-v3-cpuif";
        reg = <0x0 0x5000 0x0 0x1000>;
        interrupts = <0 8 1>; // interrupt number 8, active high, edge triggered
        interrupt-parent = <&gic>;
    };
};

Kunpeng ソフトウェアの移植

高レベルのソフトウェア アーキテクチャ

Kunpeng ソフトウェアの移行プロセス

Kunpeng ソフトウェアの移行プロセスには次の手順が含まれます。

  1. JDKの準備:ARM版JDKをインストールします。
  2. 環境変数の構成: JDK パスなどの環境変数を構成します。
  3. コンパイル: Java ソース コードがバイトコードを生成します。
  4. テスト: Java プログラムを開始し、関数をデバッグします。

以上がKunpengソフトウェア移植の完全なプロセスです。

コンパイルツールの選択

コンパイル ツールの選択は主に、使用するプログラミング言語と開発環境によって異なります。一般的なコンパイル ツールをいくつか示します。

  1. Microsoft Visual Studio: これは、Microsoft がサポートするすべてのプラットフォーム向けの C/C++/C# などのプログラミング言語用の開発ツールの完全なセットです。これには、UML ツール、コード制御ツール、統合開発環境 (IDE) などが含まれています。非常に実用的で強力なコード作成および開発ソフトウェアです。
  2. GCC: GNU Compiler Collection (GCC) は、C、C++、Objective-C、Fortran、Ada などの言語をサポートするプログラミング言語コンパイル用のソフトウェアです。
  3. Clang: Clang は、LLVM に基づく C/C++/Objective-C コンパイラーであり、主にコンパイル効率とコード品質を最適化するために使用されます。
  4. Java Development Kit (JDK): Java アプリケーションを開発している場合は、Java コンパイラ (Javac) およびその他のツールが含まれる JDK が必要です。
  5. Python インタプリタとコンパイラ: Python はインタプリタ型言語であるため、コンパイラは必要ありません。ただし、Python には、CPython、Jython、IronPython など、さまざまなインタプリタやコンパイラがあります。
    これはほんの一部であり、実際には他にも多くのコンパイル ツールから選択できます。自分の特定のニーズや習慣に応じて、自分に合ったコンパイル ツールを選択する必要があります。

コンパイルパラメータ移行の場合

コンパイル プロセス中に、いくつかの特定のコンパイル パラメーターがコンパイル結果と適応性に影響を与える可能性があります。以下に、移行プロセスで重要な役割を果たす可能性のあるコンパイル パラメーターの例をいくつか示します。

1. -march 和 -mtune:这两个参数用于指定目标处理器架构。例如,-march=native 将使编译器优化为运行在本地硬件上,而 -march=x86_64 将优化为运行在64位x86处理器上。
2. -fPIC (Position-Independent Code):该参数用于生成位置无关的代码,这在实现共享库时非常重要。
3. -I:该参数用于指定头文件的搜索路径。在移植过程中,可能需要修改此参数以适应新的环境。
4. -L:该参数用于指定库文件的搜索路径。同样,在移植过程中,可能需要修改此参数。
5. -l:该参数用于指定要链接的库。这可能涉及到链接到不同的库文件,以适应新的环境。
6. -D:该参数用于定义宏。在移植过程中,可能需要定义新的宏以适应新的环境。

上記は一般的なコンパイル パラメータのほんの一部の例であり、実際には、移行プロセスで使用できる他にも多くのコンパイル パラメータがあることに注意してください。特定のパラメーターの選択は、ニーズとターゲット プラットフォームの詳細によって異なります。

ソースコード改変事例

ソース コード変更のケースは、主に、特定のニーズや問題に合わせてプログラムのソース コードを変更および最適化することです。以下は、単純なソース コード変更のケースです。

C 言語プログラムがあるとします。このプログラムには という関数がありcalculate_average、整数配列とその配列の長さを入力として受け取り、配列の平均値を計算して結果を返します。

double calculate_average(int* arr, int length) {
    
    
    double sum = 0.0;
    for (int i = 0; i < length; i++) {
    
    
        sum += arr[i];
    }
    return sum / length;
}

ここで、この関数を変更して、配列内の負の数値を無視し、単純に計算をスキップするようにします。この機能を実現するために、簡単な判断ステートメントを追加できます。

double calculate_average(int* arr, int length) {
    
    
    double sum = 0.0;
    for (int i = 0; i < length; i++) {
    
    
        if (arr[i] >= 0) {
    
    
            sum += arr[i];
        }
    }
    return sum / length;
}

この変更により、関数は配列内の負でない数値のみをカウントし、その平均を返すようになりました。これを負の数値を含む配列に適用すると、負の数値を無視して、より正確な結果が得られます。

これは単なる例であり、実際のソース コードの変更はより複雑で、より詳細な情報が含まれる可能性があることに注意してください。ソース コードを変更する前に、変更によってエラーが発生したり、元の機能が破壊されたりしないことを確認するために、十分なテストとバックアップ (仮想マシン上で問題なく実行) を実行することをお勧めします。

Kunpeng 分析スキャン ツール 依存関係アドバイザー

dependency Advisor は、顧客のアプリケーションを Kunpeng サーバーに移行するプロセスを簡素化できるツールです。これは主に X86 サーバーにインストールされ、移植性と移植作業の分析に使用されます。このツールは、ユーザー ソフトウェア リソース パッケージ (RPM、JAR、TAR、zip、gzip ファイル) に含まれる SO 依存ライブラリのチェックと、SO 依存ライブラリの移植性の評価、指定されたユーザー ソフトウェア インストール パスにある SO 依存ライブラリのチェックをサポートします。そして、SO依存ライブラリの移植性を評価する; ユーザソフトウェアC/C++ソフトウェア構築プロジェクトファイルを確認し、ファイルの移植性を評価する; ユーザソフトウェアC/C++のソースコードを確認し、ソフトウェアソースの移植性を評価するファイル。

さらに、Dependency Advisor は自動的に分析してガイダンス レポートを出力し、ソフトウェア移行レポートと移行作業の評価を提供します。また、コマンド ラインと Web の 2 つの作業モードもサポートしています。

Kunpeng コード移行ツール移植アドバイザー

Porting Advisor は、開発者がアプリケーションを x86 プラットフォームから Kunpeng プラットフォームに移行するのに役立つコード移行ツールです。具体的な機能には次のようなものがあります。

  1. 移植性の分析: Porting Advisor は、ユーザーのソース コードと関連する依存関係を分析して、Kunpeng プラットフォームに移行できるかどうかを判断できます。
  2. 自動分析: Porting Advisor は、変更が必要なコードの内容を自動的に分析し、変更の提案を提供します。
  3. ガイダンスの提供: Porting Advisor は、開発者が移行プロセスで発生した問題を解決し、対応するソリューションを提供するのを支援します。

コードの移行に Porting Advisor を使用すると、手動調査の作業負荷が軽減され、全体的な移行効率が向上します。

分析可迁移性
自动分析
提供指导

Kunpeng ソフトウェアのパフォーマンス調整

Kunpeng ソフトウェアのパフォーマンス調整プロセス

Kunpeng ソフトウェアのパフォーマンス チューニング プロセスには次の手順が含まれます。

  1. ベースラインの確立: 最適化または監視を開始する前に、まずベースライン データと最適化目標を確立する必要があります。これには、ハードウェア構成、ネットワーク、テスト モデル、システム動作データ (CPU/メモリ/IO/ネットワーク スループット/応答遅延など) が含まれます。システムパフォーマンスのボトルネックや最適化策の導入後のシステムパフォーマンスの変化をより適切に分析するには、システムの包括的な評価と監視を行う必要があります。最適化目標は、現在のハードウェアおよびソフトウェア アーキテクチャに基づいてシステムが達成すると予想されるパフォーマンス目標です。
  2. ストレス テストとボトルネックの監視: ピーク時のワークロードまたは専門的なストレス テスト ツールを使用して、システムのストレス テストを行います。いくつかのパフォーマンス監視ツールを使用して、システムのステータスを監視します。ストレステストでは、システムやプログラムの稼働状況を詳細に記録することが推奨されており、正確な履歴記録はボトルネックの分析や最適化対策の有効性の確認に役立ちます。
  3. パフォーマンス分析: ストレス テストの結果に基づいて、パフォーマンス分析を実行して、パフォーマンスのボトルネックを見つけます。これには、CPU、メモリ、I/O、ネットワークなどのボトルネックの発見が含まれます。
  4. 最適化: パフォーマンス分析の結果に応じて、対応する最適化措置を講じます。最適化の正確な方法は、システムやアプリケーションによって異なる場合があります。
  5. 再テスト:最適化施策を実施した後、再度ストレステストや性能モニタリングを実施し、最適化の効果を確認する必要があります。
  6. 反復: パフォーマンス チューニングは、システム パフォーマンスを最適化するために継続する必要がある反復プロセスです。

上記は Kunpeng ソフトウェアのパフォーマンス チューニングの一般的なプロセスであり、特定の実装は特定の状況に応じて調整する必要がある場合があります。

循环
建立基准
压力测试与监视瓶颈
性能分析
优化
再测试
迭代

CPUとメモリサブシステムのパフォーマンスチューニング

CPU およびメモリ サブシステムのパフォーマンスをチューニングするには、次の措置を講じることができます。

  1. CPU の側面:

    • マルチスレッドの最適化: マルチスレッドを合理的に使用し、コンピューティングタスクを複数のスレッドに分割して並列実行し、マルチコア CPU のパフォーマンスを最大限に活用します。
    • コンテキストの切り替えを減らす: スレッド間の頻繁な切り替えを減らし、コンテキストの切り替えによって発生するオーバーヘッドを回避します。
    • キャッシュの最適化: CPU キャッシュを最大限に活用して、キャッシュ ミスによるパフォーマンスの低下を回避します。たとえば、局所性の原則を使用してデータ アクセス パターンを最適化し、キャッシュ ミスを削減します。
  2. 記憶の面では:

    • メモリ割り当ての最適化: 頻繁なメモリの割り当てと解放を避けるために、メモリ割り当て戦略を合理的に設定します。オブジェクト プールやメモリ プールなどのテクノロジを使用して、メモリ管理を最適化できます。
    • メモリ アクセス モードの最適化: 局所性の原理を最大限に利用してメモリ アクセス モードを最適化します。たとえば、連続アクセス、整列アクセスなどを通じてメモリ アクセスのランダム性を軽減します。
    • メモリ圧縮とシャーディング: メモリ使用量が多いデータ構造またはオブジェクトの場合、メモリ使用量を削減し、アクセス効率を向上させるために、メモリ圧縮またはシャーディングを検討できます。
CPU方面优化
多线程优化
减少上下文切换
缓存优化
内存方面优化
内存分配优化
内存访问模式优化
内存压缩与分片

さらに、パフォーマンス監視およびパフォーマンス分析ツールを通じて CPU およびメモリ サブシステムを監視および分析し、パフォーマンスのボトルネックを見つけて、対応する最適化戦略を採用することができます。アプリケーションのシナリオや要件が異なれば、異なる最適化方法が必要になる場合があるため、特定の状況に応じて最適化し、パフォーマンス テストと評価を実行して最適化の効果を検証することをお勧めします。

ネットワークサブシステムのパフォーマンスチューニング

ネットワーク サブシステムのパフォーマンスを調整するには、次の措置を講じることができます。

  1. ネットワーク遅延を短縮します。

    • 高性能のネットワーク機器を使用する: データ パケットの送信遅延を減らすために、高性能のネットワーク スイッチ、ルーター、その他のネットワーク機器を選択します。
    • より高速なネットワーク プロトコルを使用する: たとえば、ハンドシェイク遅延と接続確立時間を短縮するために、より高速なトランスポート プロトコル (TCP Fast Open、QUIC など) を採用します。
    • ネットワーク トポロジの最適化: ネットワーク トポロジを合理的に計画し、データ パケットの伝送距離を短縮し、ネットワーク遅延を削減します。
  2. ネットワーク帯域幅を増やす:

    • ネットワーク負荷分散: 負荷分散機器またはソフトウェアを構成することにより、ネットワーク トラフィックが複数のサーバーに均等に分散され、ネットワーク全体の帯域幅が向上します。
    • データ圧縮と高速化: データ圧縮と高速化テクノロジを使用してデータ送信量を削減し、それによって利用可能な帯域幅を増やします。
    • 帯域幅容量の増加: ネットワーク機器をアップグレードして帯域幅容量を増やし、同時多発ネットワーク要求に対応します。
  3. ネットワークプロトコルとポリシーを最適化します。

    • TCP/IP パラメータの調整: 特定のアプリケーション シナリオに従って、ウィンドウ サイズ、輻輳制御アルゴリズムなどの TCP/IP プロトコルのパラメータを調整し、ネットワーク伝送効率を向上させます。
    • データパケットの優先管理:ネットワーク機器のQoS(Quality of Service)機能を設定することで、さまざまな種類のデータパケットに優先順位を付け、重要なデータをタイムリーに送信します。
  4. キャッシュとバッファの管理:

    • CDN アクセラレーション: コンテンツ配信ネットワーク (CDN) を使用して静的リソースをキャッシュし、データ送信を高速化します。
    • キャッシュ テクノロジの適用: 実際のニーズに応じて、キャッシュ テクノロジを合理的に使用して、一般的なデータとクエリ結果をメモリにキャッシュし、データ アクセスを高速化します。
    • バッファ サイズの最適化: ネットワーク デバイスのバッファ サイズを最適化し、バッファが大きすぎたり小さすぎたりすることによるパフォーマンスの問題を回避します。

此外,还可以通过监控和分析网络流量、延迟等指标,找出网络性能瓶颈,并进行相应的调优策略。综合考虑应用程序的特点、网络环境以及业务需求,选择合适的调优方案,并进行性能测试和评估,以验证优化效果。

CPU方面优化
内存方面优化
CPU多线程优化
减少上下文切换
缓存优化
内存分配优化
内存访问模式优化
内存压缩与分片

磁盘I/O子系统性能调优

对于磁盘I/O子系统的性能调优,可以采取以下措施:

优化磁盘I/O性能的常见措施包括:

  1. 使用RAID技术:RAID技术可以提供更高的磁盘读写性能和冗余容错能力。

  2. 块大小优化:根据应用程序的访问模式和数据块大小,调整磁盘块的大小以提高磁盘I/O性能。

  3. 操作系统参数调优:操作系统参数调整相关参数来改善磁盘I/O性能。

  4. 文件系统选择与优化:选择适合特定应用场景的文件系统,并进行相应的优化。

  5. I/O缓存与缓冲区管理:I/O缓存和缓冲区管理技术来减少磁盘I/O操作次数。

  6. 应用程序优化:应用程序优化,减少不必要的磁盘I/O操作。

  7. 磁盘性能监控与故障诊断:磁盘性能监控磁盘的性能指标,及时发现潜在问题,并采取相应的故障诊断和修复措施。

这些措施综合起来可以提升磁盘I/O子系统的性能和可靠性。但需要根据具体情况进行调优,并进行性能测试和评估,以验证优化效果。

应用程序性能调优

对于应用程序的性能调优,可以采取以下措施:

  1. 代码优化:优化算法和数据结构和提高代码执行效率。
  2. 数据库优化:数据库索引优化和提高数据检索操作。
  3. 缓存技术应用:使用缓存技术和提高读取速度。
  4. 网络通信优化:减少网络请求次数和提高速度。
  5. 性能监控与调试:使用性能监控工具和评估系统的性能表现。
  1. 代码优化:

    • 优化算法和数据结构:选择高效的算法和数据结构,减少不必要的计算和内存消耗,提高代码执行效率。
    • 减少资源占用:及时释放不再使用的资源,避免资源泄露。合理使用内存、文件句柄、数据库连接等资源,避免资源瓶颈。
    • 并发编程优化:合理使用多线程、多进程或异步编程模型,利用多核处理器和异步操作提高并发性能。
  2. 数据库优化:

    • 数据库索引优化:分析数据库查询的频率和模式,创建适当的索引来加速数据检索操作。
    • 数据库连接管理:合理维护和管理数据库连接,减少连接的建立和关闭开销。
    • 批量操作和事务管理:将多个数据库操作批量提交或使用事务进行管理,减少单次数据库交互的次数,提高效率和数据一致性。
  3. 缓存技术应用:

    • 使用缓存技术:将频繁读取的数据缓存在内存中,减少对底层存储系统(如数据库)的访问,提高读取速度。
    • 合理设置缓存策略:根据数据的更新频率和重要性,设置合适的缓存策略,如缓存过期策略、LRU(最近最少使用)策略等。
  4. 网络通信优化:

    • 减少网络请求次数:合并多个网络请求、采用批量操作,减少网络开销和延迟。
    • 压缩和加速数据传输:使用数据压缩和加速技术,减少网络传输数据量,提高速度。
  5. 性能监控与调试:

    • 使用性能监控工具:通过监控工具来获取应用程序的性能指标,如CPU使用率、内存占用、数据库查询时间等,找出性能瓶颈和潜在问题。
    • 进行性能测试:模拟实际使用场景,进行负载测试和性能测试,评估系统的性能表现,及时发现和解决性能问题。

除了以上措施,还可以根据具体应用场景和需求进行针对性的优化。关注应用程序的瓶颈和低效点,不断进行测试和改进,以提高应用程序的性能和响应速度。同时,注意平衡性能调优和可维护性之间的关系,避免过度优化导致代码难以理解和维护。

增加硬件资源
+增加CPU、内存和磁盘等硬件资源()
+使用更快的存储设备或网络传输设备()
调整软件参数
+调整操作系统或数据库的参数()
+调整Web服务器参数()
优化软件架构和设计
+应用合适的软件设计模式和开发框架()
+优化软件架构()
资源的合理利用
+减少访问磁盘次数()
+使用缓存技术对数据进行缓存()
进行性能测试和优化
+负载测试和性能测试()
+评估不同参数组合或优化技术()
系统监控和调试
+实时监控系统性能和资源利用率()
+收集日志信息()

基础软件性能调优

基础软件(如操作系统、数据库、Web服务器等)的性能调优,可以采取以下措施:

  1. 增加硬件资源:

    • 增加CPU、内存和磁盘等硬件资源,以提高基础软件的执行速度和并发处理能力。
    • 使用更快的存储设备或网络传输设备,以提高数据的访问速度和传输效率。
  2. 调整软件参数:

    • 根据应用的工作负载和硬件配置,调整操作系统或数据库的参数,以达到最优性能。
    • 对于Web服务器,可以调整连接池大小、缓存策略、请求过滤等参数,以提高并发处理和响应速度。
  3. 优化软件架构和设计:

    • 应用合适的软件设计模式和开发框架,以提高代码复用性和可维护性。
    • 良好的软件架构可以提高基础软件的并发处理能力和可扩展性。
  4. 资源的合理利用:

    • 对于数据库系统,可以通过使用数据库缓存、合理索引等手段,减少访问磁盘的次数,提高数据访问速度。
    • 对于Web服务器,可以使用缓存技术对经常访问的数据进行缓存,降低数据库访问的频率。
  5. 进行性能测试和优化:

    • 对基础软件进行负载测试和性能测试,找出瓶颈和性能瓶颈。
    • 评估不同参数组合或优化技术的性能效果,选择最优方案。
  6. 系统监控和调试:

    • 通过系统监控工具实时监控系统的性能、资源利用率等指标,在系统出现异常时及时进行调试和修复。
    • 收集日志信息,及时发现潜在问题,并对系统进行诊断。

除了以上措施,还可以根据不同的基础软件进行针对性的调优。例如,对于数据库系统,还可以使用分区、分片等技术,提高数据处理的并行性和可扩展性。对于Web服务器,还可以使用负载均衡技术,提高并发处理能力和可用性。总之,基础软件的性能调优需要多方面的考虑和综合处理。
アプリケーションの読み取りおよび書き込みの最適化メカニズム

鲲鹏性能优化工具 Tuning Kit

Tuning Kit 是一款针对鲲鹏计算平台的性能分析和优化工具,能收集处理器硬件、操作系统、进程/线程、函数等各层次的性能数据,分析出系统性能指标,定位到系统瓶颈点及热点函数。

Tuning Kit 支持以下功能特性:

  1. 系统配置全景分析:采集整个系统的软硬件配置信息,分析并针对不合理项提供优化建议。
  2. システムパフォーマンスのパノラマ分析: 業界のUSE (使用率、飽和、エラー) メソッドから学び、システムCPU、メモリ、ストレージIO、ネットワークIOおよびその他のリソースの動作条件を収集し、それらの使用率、飽和、エラーおよびその他の指標を取得します。 、システムのボトルネックを特定します。
  3. 一部のシステム インデックス項目については、既存のベンチマーク値と最適化経験に基づいて最適化の提案が提供されます。
  4. システム リソース スケジューリング分析: CPU スケジューリング イベントに基づいて、CPU コアの実行ステータス、各時点のプロセス/スレッド、プロセス/スレッドの切り替えを分析し、対応する最適化の提案を提供します。

チューニング キットは、ユーザーがシステム パフォーマンスをより深く理解し、システムのボトルネックを特定して解決し、システム全体の効率を向上させるのに役立ちます。

系统配置全景分析
系统资源调度分析
系统性能全景分析
针对部分系统指标项优化建议

Kunpeng ブーストキット
Kunpeng 開発者コミュニティ: https://www.hikunpeng.com/developer/boostkit
クンペンブーストキット 23.0
コード移行モジュール
Kunpeng 公式ドキュメントのアドレス
https://www.hikunpeng.com/document/detail/zh/kunpengdevps/porting/qs/qs-pa-kunpengdevps. htmlKunpeng
小芝
https://www.hikunpeng.com/zh/airobot

参考文献:
[1] GB/T 7714: Dai Zhitao、Liu Jianpei. Kunpeng プロセッサ アーキテクチャとプログラミング: Huawei Intelligent Computing Technology Series [M]. 北京: 清華大学出版局、2020. [2] https://www.hikunpeng
。 com/
[3] Qi Zhengwei、Guan Haibing. Simple System Virtualization: Principles and Practice [M] 北京: 清華大学出版局、2021 年。

おすすめ

転載: blog.csdn.net/m0_74037814/article/details/132564623