android keystore源码分析
架构
Android Keystore API 和底层 Keymaster HAL 提供了一套基本的但足以满足需求的加密基元,以便使用访问受控且由硬件支持的密钥实现相关协议。
Keymaster HAL 是由原始设备制造商 (OEM) 提供的动态加载库,密钥库服务使用它来提供由硬件支持的加密服务。为了确保安全性,HAL 实现不会在用户空间乃至内核空间中执行任何敏感操作。敏感操作会被分配给通过某个内核接口连接的安全处理器。 最终的架构如下所示:

源码分析
源码分析基于Android 9.0
####AndroidKeyStore服务提供者
应用层调用时provider必须指明为"AndroidKeyStore",否则默使用的是BC库。
Android KeyStore 是Java 安全框架的一个提供者的实现,类名为AndroidKeyStoreProvider.java。
此类中定义了一些引擎类的实现:
- AndroidKeyStoreSpi 存储服务
- AndroidKeyStoreKeyPairGeneratorSpi$EC ECC密钥对生成
- AndroidKeyStoreKeyPairGeneratorSpi$RSA RSA密钥对生成
等等,这部分的代码在
/frameworks/base/keystore/java/android/security/keystore/
这些引擎类的实现内部有一个android.security.KeyStore对象。此对象是一个binder代理。通过binder通信转到系统服务的KeyStoreSerivce。
KeyStoreService服务
服务代码在/system/security/keystore/key_store_service.cpp
KeyStoreService 内部持有一个KeyStore对象,
代码在/system/security/keystore/KeyStore.cpp
KeyStore对象内部持有一个device,此device是KeymasterDevices,此对象是三个Keymaster的数组,分别对应软实现、TEE实现和SE实现。如果是TEE实现的话,keymaster hal 应该就是CA程序。
当系统启动时会加载keymaster hal的实现,并把他注册到硬件的servicemanager 中。
keymaster hal
keymaster hal的注册,这里是安卓模拟器goldfish中的服务注册示例。
Cross Reference: /device/generic/goldfish/keymaster/strongbox/service.cpp
int main() {::android::hardware::configureRpcThreadpool(1, true /* willJoinThreadpool */);using android::hardware::keymaster::V4_0::SecurityLevel;using ::keymaster::V4_0::ng::CreateKeymasterDevice;/** Create two software keymaster devices claiming different security levels for testing* purposes. They do not have the certificates of real TEE or Strongbox keymaster devices.*/auto keymaster = CreateKeymasterDevice(SecurityLevel::TRUSTED_ENVIRONMENT);auto status = keymaster->registerAsService("default");if (status != android::OK) {LOG(FATAL) << "Could not register default service for Keymaster 4.0 (" << status << ")";}auto strongbox = CreateKeymasterDevice(SecurityLevel::STRONGBOX);status = strongbox->registerAsService("strongbox");if (status != android::OK) {LOG(FATAL) << "Could not register strongbox service for Keymaster 4.0 (" << status << ")";}android::hardware::joinRpcThreadpool();return -1; // Should never get here.
}
keymaster枚举
Cross Reference: /system/security/keystore/keystore_main.cpp
KeymasterDevices enumerateKeymasterDevices(IServiceManager* serviceManager) {KeymasterDevices result;serviceManager->listByInterface(Wrapper::WrappedIKeymasterDevice::descriptor, [&](const hidl_vec<hidl_string>& names) {})
}
通过枚举获取keymaster的实现。构造keystore对象。
keymaster hal实现最终通过调用安全环境实现密钥生成、加密解密、签名验签。
keymaster 实现的接口定义如下。厂商只要按照规范要求实现此接口即可。
Cross Reference: /hardware/interfaces/keymaster/3.0/IKeymasterDevice.hal
Cross Reference: /hardware/interfaces/keymaster/4.0/IKeymasterDevice.hal
Android Keystore 机制总结
Android Keystore 提供安全的密钥管理和加密操作,其核心机制涉及多进程协作和跨空间调用。以下是关键组件及其交互流程:
重要类与组件
类/组件 | 所在进程 | 运行空间 | 描述 |
---|---|---|---|
android.security.KeyStore | 应用进程(如App进程) | 用户空间 | 应用层API,提供密钥生成、存储等接口。开发者通过此类访问Keystore功能。 |
KeyStoreService | keystore进程 | 用户空间 | 系统服务,处理应用请求,管理密钥生命周期,通过Binder与客户端通信。 |
KeymasterHAL (HIDL接口) | 厂商HAL进程(如vendor.some.process ) | 用户空间 | 硬件抽象层接口,由厂商实现,执行加密操作(如密钥生成、签名)。 |
内核驱动(如/dev/keymaster ) | 内核 | 内核空间 | 与硬件安全模块(HSM/TEE/StrongBox)通信,处理安全环境内的敏感操作。 |
调用流程与通信机制
- 应用层调用
- 进程: 应用进程 →
keystore
- 机制: Binder IPC
- 应用通过
android.security.KeyStore
发起请求(如生成密钥)。 - 调用通过 Binder 传递至
KeyStoreService
(运行在keystore
)。
- 应用通过
- 进程: 应用进程 →
- 系统服务处理
- 进程:
keystore
→ 厂商HAL进程 - 机制: HIDL/AIDL IPC
KeyStoreService
将请求转换为 Keymaster 操作(如调用generateKey
)。- 通过 HIDL 接口(如
IKeymasterDevice
)与厂商的KeymasterHAL
实现通信。
- 进程:
- 硬件抽象层执行
- 进程: 厂商HAL进程 → 内核
- 机制: 系统调用(ioctl)
KeymasterHAL
通过ioctl
调用内核驱动(如/dev/keymaster
)。- 驱动将操作转发至安全环境(如 TEE 或 StrongBox)。
- 安全环境操作
- 空间: 内核 → TEE/HSM
- 机制: SMC指令或安全监控调用
- 内核驱动通过安全机制(如 ARM TrustZone 的 SMC)触发安全环境内的操作。
- 密钥在安全环境内生成/使用,不会暴露到非安全内存。
关键点总结
- 用户空间与内核空间协作:敏感操作(如密钥生成)最终由安全环境(TEE/HSM)处理,确保密钥不泄露至普通内存。
- 跨进程通信:
- Binder:用于应用与系统服务的高效通信。
- HIDL/AIDL:解耦系统服务与厂商实现,支持向前兼容。
- 安全边界:内核驱动作为用户空间与安全环境的桥梁,通过严格权限控制保障隔离性。
[应用进程] --Binder--> [keystore进程] --HIDL--> [KeymasterHAL进程] --ioctl--> [内核驱动] --> [TEE/HSM]↑ | || (android.security.KeyStore) | (KeyStoreService) | (厂商实现)用户空间 用户空间 用户空间 内核空间
应用代码示例
try {final String KEY_ALIAS = "myKeyAliasx";KeyStore keyStore;keyStore = KeyStore.getInstance("AndroidKeyStore");keyStore.load(null);// 检查密钥是否已存在,如果不存在则生成新的密钥对if (!keyStore.containsAlias(KEY_ALIAS)) {//生成密钥KeyGenParameterSpec spec = new KeyGenParameterSpec.Builder(KEY_ALIAS,KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY).setDigests(KeyProperties.DIGEST_SHA256).setSignaturePaddings(KeyProperties.SIGNATURE_PADDING_RSA_PSS).setKeySize(2048).build();KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_RSA, "AndroidKeyStore");keyPairGenerator.initialize(spec);KeyPair keyPair = keyPairGenerator.generateKeyPair();}KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(KEY_ALIAS, null);PrivateKey privateKey = privateKeyEntry.getPrivateKey();KeyFactory factory = KeyFactory.getInstance(privateKey.getAlgorithm(), "AndroidKeyStore");KeyInfo keyInfo;//获取密钥信息keyInfo = factory.getKeySpec(privateKey, KeyInfo.class);if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {int securityLevel = keyInfo.getSecurityLevel();if (securityLevel == KeyProperties.SECURITY_LEVEL_TRUSTED_ENVIRONMENT) {System.out.println("key is in trusted environment");} else if (securityLevel == KeyProperties.SECURITY_LEVEL_STRONGBOX) {System.out.println("key is in strongbox");} else {System.out.println("key is in software");}} else {boolean insideSecureHardware = keyInfo.isInsideSecureHardware();System.out.println("insideSecureHardware=" + insideSecureHardware);}// 签名Signature signature = Signature.getInstance("SHA256withRSA/PSS");signature.initSign(privateKey);signature.update("adgfdfd".getBytes("UTF-8"));byte[] sign = signature.sign();} catch (Exception e) {e.printStackTrace();}
相关文章:
android keystore源码分析
架构 Android Keystore API 和底层 Keymaster HAL 提供了一套基本的但足以满足需求的加密基元,以便使用访问受控且由硬件支持的密钥实现相关协议。 Keymaster HAL 是由原始设备制造商 (OEM) 提供的动态加载库,密钥库服务使用它来提供由硬件支持的加密服…...
状态模式
状态(State)模式属于行为型模式的一种。 状态模式允许对象在其内部状态改变时改变其行为,使其看上去就像改变了自身所属的类一样。 状态模式是为了把一大串if...else...的逻辑给分拆到不同的状态类中,使得将来增加状态比较容易。…...
C++ | 面向对象 | 类
👻类 👾语法格式 class className{Access specifiers: // 访问权限DataType variable; // 变量returnType functions() { } // 方法 };👾访问权限 class className {public:// 公有成员protected:// 受保护成员private:// 私有成员 }…...
鸿蒙-AVPlayer
compileVersion 5.0.2(14) 音频播放 import media from ohos.multimedia.media; import common from ohos.app.ability.common; import { BusinessError } from ohos.base;Entry Component struct AudioPlayer {private avPlayer: media.AVPlayer | nu…...
Android移动应用开发实践-1-下载安装和简单使用Android Studio 3.5.2版本(频频出错)
一、下载安装 1.Android Studio3.5.2下载地址:Android Studio3.5.2下载地址 其他版本下载地址:其他版本下载地址 2.安装教程(可以多找几个看看) 安装 | 手把手教你Android studio 3.5.2安装(安装教程)_a…...
从.m3u8到.mp4:使用批处理脚本完成视频处理的完整指南
这里介绍一个Windows批处理脚本(Windows Batch Script),主要用于处理 .m3u8 ts 视频文件的下载和合并功能。 以下是程序的主要功能和逻辑流程: 功能概述 参数检查与路径处理: 检查是否传递了文件或文件夹路径作为参数…...
qt5的中文乱码问题,QString、QStringLiteral 为 UTF-16 编码
qt5的中文乱码问题一直没有很明确的处理方案。 今天处理进程间通信时,也遇到了qt5乱码问题,一边是设置的GBK,一边设置的是UTF8,单向通信约定采用UTF8。 发送端保证发的是UTF8字符串,因为UTF8在网络数据包中没有字节序…...
Gurobi 并行计算的一些问题
最近尝试用 gurobi 进行并行计算,即同时用多个 cpu 核计算 gurobi 的 model,但是发现了不少问题。总体来看,gurobi 对并行计算的支持并不是那么好。 gurobi 官方对于并行计算的使用在这个网址,并有下面的大致代码: i…...
Vue3 中如何实现响应式系统中的依赖收集和更新队列的解耦?
一、问题解析:为什么需要解耦? 在响应式系统中,依赖收集(追踪数据与视图的关联关系)和更新队列(批量处理数据变化带来的副作用)是两个核心但职责不同的模块。 Vue3 通过以下设计实现解耦&…...
vue项目中动态添加类名样式不生效问题
一、问题描述 在vue项目中使用:class{tableContent: summary}给元素动态添加了类名tableContent,运行代码后查看类名已经添加成功但样式并未生效。 二、问题产生原因并解决 刚开始把样式写在了<style lang"scss" scoped></style>中&#x…...
供应链管理系统--升鲜宝门店收银系统功能解析,登录、主界面、会员 UI 设计图(一)
供应链管理系统--升鲜宝门店收银系统功能解析,登录、主界面 会员 UI 设计图(一)...
用AI写游戏3——deepseek实现kotlin android studio greedy snake game 贪吃蛇游戏
项目下载 https://download.csdn.net/download/AnalogElectronic/90421306 项目结构 就是通过android studio 建空项目,改下MainActivity.kt的内容就完事了 ctrlshiftalts 看项目结构如下 核心代码 MainActivity.kt package com.example.snakegame1// MainA…...
设计模式的引入
面向对象设计原则 1. 软件设计固有的复杂性2. 面向对象设计原则2.1 引入2.2 依赖倒置原则2.3 开放封闭原则2.4 单一职责原则2.5 Liskov 替换原则( LSP)2.6 接口隔离原则( ISP)2.7 优先使用对象组合,而不是类继承2.8 封…...
P8697 [蓝桥杯 2019 国 C] 最长子序列
P8697 [蓝桥杯 2019 国 C] 最长子序列 题目 分析代码 题目 分析 先分析一波xdm 题意呢就是在s中找有多少个能和t匹配的字符,注意:连续匹配,输出连续的次数 欧克,开始分析,首先,哎~字母!还强调…...
基于阿里云PAI平台快速部署DeepSeek大模型实战指南
一、DeepSeek大模型:企业级AI应用的新标杆 1.1 为什么选择DeepSeek? 近期,DeepSeek系列模型凭借其接近GPT-4的性能和开源策略,成为全球开发者关注的焦点。在多项国际评测中,DeepSeek-R1模型在推理能力、多语言支持和…...
【java进阶】java多态深入探讨
前言 在Java的编程宇宙中,多态是极为关键的概念,它宛如一条灵动的纽带,串联起面向对象编程的诸多特性,赋予程序宛如生命般的动态活力与高度灵活性。透彻理解多态,不仅是提升代码质量的关键,更是开启高效编程大门的钥匙。 一、多态的定义与本质 多态,从概念层面来讲,…...
蓝桥杯备赛-拔河
问题描述 小明是学校里的一名老师,他带的班级共有 nn 名同学,第 ii 名同学力量值为 aiai。在闲暇之余,小明决定在班级里组织一场拔河比赛。 为了保证比赛的双方实力尽可能相近,需要在这 nn 名同学中挑选出两个队伍,…...
Zookeeper(67) Zookeeper在HBase中的应用是什么?
Zookeeper 在 HBase 中起到了至关重要的作用,主要用于协调和管理 HBase 集群中的多个组件。具体来说,Zookeeper 在 HBase 中的应用包括以下几个方面: Master 选举:HBase 集群中可以有多个 Master 节点,但只有一个处于…...
java后端开发day20--面向对象进阶(一)--static继承
(以下内容全部来自上述课程) 1.static–静态–共享 static表示静态,是java中的一个修饰符,可以修饰成员方法,成员变量。 1.静态变量 被static修饰的成员变量,叫做静态变量。 特点: 被该类…...
IDEA使用Maven方式构建SpringBoot项目
1、环境准备 确保你已经安装了以下工具: Java JDK(推荐 JDK 8 或更高版本) IntelliJ IDEA(推荐使用最新版本) 2、创建 Spring Boot 项目 (1) 打开 IntelliJ IDEA。 (2)…...
Spring Boot2.0之十 使用自定义注解、Json序列化器实现自动转换字典类型字段
前言 项目中经常需要后端将字典类型字段值的中文名称返回给前端。通过sql中关联字典表或者自定义函数不仅影响性能还不能使用mybatisplus自带的查询方法,所以推荐使用自定义注解、Json序列化器,Spring的缓存功能实现自动转换字典类型字段。以下实现Spri…...
C#问题解决方案 --- 生成软件hash,生成文件hash
生成软件hash值: private string GetEXEHashString() {//获得软件哈希值Process currProcess Process.GetCurrentProcess();string filePath currProcess.MainModule.FileName;string hashEXE string.Empty;using (FileStream fs new FileStream(filePath, Fil…...
云计算如何解决延迟问题?
在云计算中,延迟(latency)指的是从请求发出到收到响应之间的时间间隔。延迟过高可能会严重影响用户体验,特别是在需要实时响应的应用中,如在线游戏、视频流、金融交易等。云计算服务如何解决延迟问题,通常依…...
多模态人物视频驱动技术回顾与业务应用
一种新的商品表现形态,内容几乎存在于手淘用户动线全流程,例如信息流种草内容、搜索消费决策内容、详情页种草内容等。通过低成本、高时效的AIGC内容生成能力,能够从供给端缓解内容生产成本高的问题,通过源源不断的低成本供给倒推…...
鸿蒙中连接手机可能遇到的问题
连接权限问题:手机开启了严格的权限管理机制,若未授予鸿蒙设备连接所需的权限,如蓝牙连接时未开启蓝牙权限,或者 USB 连接时未允许设备进行调试、文件传输等操作,就会导致连接失败。例如,当使用鸿蒙平板通过…...
15.代码随想录算法训练营第十五天|(递归)110. 平衡二叉树,257. 二叉树的所有路径*,404. 左叶子之和,222.完全二叉树的节点个数[打卡自用]
15.代码随想录算法训练营第十五天|(递归)110. 平衡二叉树,257. 二叉树的所有路径*,404. 左叶子之和,222.完全二叉树的节点个数 给定一个二叉树,判断它是否是 平衡二叉树 示例 1: 输入…...
H5 火柴人科目三和GitHub获取仓库点星星的用户列表发生了艺术的碰撞
先看效果,代码写的比较乱,有待优化 效果 https://linyisonger.github.io/H5.Examples/?name./089.%E7%9C%8B%E6%98%9F%E6%98%9F%E7%9A%84%E8%88%9E%E8%80%85.html 思路 看起来很简单,实则也不是很难,就是需要思路要打开。 一…...
使用消息队列怎样防止消息重复?
大家好,我是君哥。 使用消息队列时,我们经常会遇到一个可能对业务产生影响的问题,消息重复。在订单、扣款、对账等对幂等有要求的场景,消息重复的问题必须解决。 那怎样应对重复消息呢?今天来聊一聊这个话题。 1.三…...
06.【C++】模板初阶(template<typename T>,充分复用函数,函数模板和类模板的使用)
目录 一. 泛型编程 二. 函数模板(template的使用) 2.1 函数模板概念 2.2 函数模板格式 2.3 函数模板的原理 2.4 函数模板的实例化 2.5 模板参数的匹配原则 三. 类模板 3.1 类模板的定义格式 3.2 类模板的实例化 一. 泛型编程 如何实现一个通用…...
深入理解 并查集LRUCaChe
并查集&LRUCaChe 个人主页:顾漂亮 文章专栏:Java数据结构 1.并查集的原理 在一些应用问题中,需要将n个不同的元素划分成一些不相交的集合。开始时,每个元素自成一个单元素集合,然后根据一定规律将归于同一组元素的…...
在 macOS 系统上安装 kubectl
在 macOS 系统上安装 kubectl 官网:https://kubernetes.io/zh-cn/docs/tasks/tools/install-kubectl-macos/ 用 Homebrew 在 macOS 系统上安装 如果你是 macOS 系统,且用的是 Homebrew 包管理工具, 则可以用 Homebrew 安装 kubectl。 运行…...
如何设置HTTPOnly和Secure Cookie标志?
设置HttpOnly和Secure标志于Cookie中是增强Web应用安全性的重要措施。这两个标志帮助防止跨站脚本攻击(XSS)和中间人攻击(MitM)。下面是关于如何设置这些标志的具体步骤: 设置方法 在服务器端设置 根据你的服务器端…...
seacmsv9注入管理员账号密码+orderby+limi
1:mysql默认存储引擎innoDB携带的表 1,mysql.innodb_table_stats 2,mysql.innodb_index_stats SELECT table_name FROM mysql.innodb_table_stats WHERE database_name DATABASE(); 2: 关键字做处理 HEX编码:0x696E666F726D6174696F6E5F7…...
Orange 开源项目 - 集成百度智能云-千帆大模型
1 集成百度智能云-千帆大模型 百度智能云-千帆ModelBuilder百度智能云千帆大模型服务与开发平台ModelBuilder(以下简称千帆ModelBuilder)是面向企业开发者的一站式大模型开发及服务运行平台。千帆ModelBuilder不仅提供了包括文心一言底层模型和第三方开源…...
mac 安装Eclipse,汉化及安装ERMaster
1、下载Eclipse 进入官网直接下载 https://www.eclipse.org/downloads/ 2、Eclipse 汉化 以下是 Eclipse 2024-12 汉化的具体方法: 1、打开安装新软件界面:打开 Eclipse,点击菜单栏中的 “Help”,选择 “Install New Software……...
C++程序员内功修炼——Linux C/C++编程技术汇总
在软件开发的宏大版图中,C 语言宛如一座巍峨的高山,吸引着无数开发者攀登探索。而 Linux 操作系统,以其开源、稳定、高效的特性,成为了众多开发者钟爱的开发平台。将 C 与 Linux 相结合,就如同为开发者配备了一把无坚不…...
Unity3D 战斗系统架构与设计详解
引言 战斗系统是许多游戏的核心玩法之一,尤其是在动作游戏、角色扮演游戏(RPG)和策略游戏中。Unity3D 作为一款强大的游戏引擎,提供了丰富的工具和 API 来帮助开发者实现复杂的战斗系统。本文将详细探讨 Unity3D 中战斗系统的架构…...
Apache Commons Chain 与 Spring Boot 整合:构建用户注册处理链
文章目录 概述1. 环境准备2. 创建自定义上下文3. 创建命令验证用户输入保存用户数据发送欢迎邮件 4. 构建并执行处理链5. 使用处理链6. 运行结果7. 总结 概述 本文档旨在展示如何在 Spring Boot 应用中使用 Apache Commons Chain 来实现一个用户注册的处理链。我们将通过 Chai…...
数据结构:二叉树的数组结构以及堆的实现详解
目录 一.树与二叉树 1.树的概念与相关术语: 2.二叉树: (1)定义: (2)特殊的二叉树: (3)完全二叉树 (4)二叉树的存储结构&#x…...
机器学习01
机器学习的基本过程如下: 1.数据获取 2.数据划分 3.特征提取 4.模型选择与训练 5.模型评估 6.模型调优 一、特征工程(重点) 0. 特征工程步骤为: 特征提取(如果不是像dataframe那样的数据,要进行特征提取&#…...
常见锁类型介绍
下面结合代码详细介绍 Mutex、RW Lock、Futex、自旋锁、信号量、条件变量 和 synchronized,并分析它们的适用场景、特点以及为什么这些锁适用于特定场景。我们将从锁的实现机制和性能特点出发,解释其适用性。 1. Mutex(互斥锁) 代…...
[uboot][stm32]配置LTDC屏幕
文章目录 前提dts设备树修改Kconfig日志打印后记 https://github.com/wdfk-prog/u-boot 前提 手上刚好有块屏幕,尝试在uboot中点亮一下使用前请使用其他手段点亮该屏幕确保屏幕的完好再进行操作.确保配置的参数及引脚是可用的. dts设备树修改 ltdc状态修改为重定向前绑定,另…...
nodejs用ws模块反向代理socks5数据,即用ws写服务端和客户端及加密
首先思路是客户端发送socks5请求数据——>服务端解密并解析socks5数据是否为真,解析出Host和port,并用net.socket访问目标网站,目标网站返回数据,服务端再用ws发送返回数据给客户端 //解析socks5数据和返回socks5格式响应 //在读下面代码…...
【MySQL篇】数据库基础
目录 1,什么是数据库? 2,主流数据库 3,MySQL介绍 1,MySQL架构 2,SQL分类 3,MySQL存储引擎 1,什么是数据库? 数据库(Database,简称DB…...
linux后台运行程序怎么停止
启动 nohup ./jmeter -nt test.jmx 查看 ps -ef | grep nohup或者 ps -ef | grep test 停止 kill 掉上面查询出的进程 疑惑 停止掉java进程或者jmeter进程,但是没有实际停止任务,所以用nohup查出来进程再停止比较靠谱!!...
华为认证考试证书下载步骤(纸质+电子版)
华为考试证书可以通过官方渠道下载相应的电子证书,部分高级认证如HCIE还支持申请纸质证书。 一、华为电子版证书申请步骤如下: ①访问华为培训与认证网站 打开浏览器,登录华为培训与认证官方网站 ②登录个人账号 在网站首页,点…...
scala基础
Scala基础 scala基础Scala介绍第一个scala代码object和class的区别关键区别伴生类和伴生对象: 字节码解析在java中创建三个类 反编译代码编译User.class源码后的结果编译Emp.class源码后的结果 注释Scala类型推断&至简原则变量var和val之间的区别可变变量不可变…...
Linux中的查看命令
路径分为相对路径(行相对当前工作目录开始的路径)和绝对路径(不管是)#:命令提示符,从这个位置可以开始输入命令,另一个提示符为$,如果是root,则提示为#;如果是…...
深入了解 NAT 模式:网络地址转换的奥秘
深入了解 NAT 模式:网络地址转换的奥秘 在计算机网络的世界里,NAT 模式(Network Address Translation,网络地址转换)扮演着至关重要的角色。它就像是网络中的翻译官,在不同网络地址之间进行转换࿰…...
HTML第二节
一.列表 1.列表的简介 2.无序列表 注:1.ul里面只能放li,不能放标题和段落标签 2.li里面可以放标题和段落等内容 3.有序列表 4.定义列表 注:要实现上图的效果需要CSS 二.表格 1.表格介绍 注:1.th有额外的效果,可以…...