block格式差分包合并方法解析

system.transfer.list深度解析 system.transfer.list  system.new.dat很明显,通过名字我们就知道这两个文件的作用,system.new.dat为数据部分,system.transfer.list为转换的描述列表,我们可以通过这两个文件完成升级。我们打开一个升级包的升级脚本META-INF\com\google\android\updater-scriptblock_image_update("/... 阅读详情

采用合并差分包的方式,不过要做一些处理,以下是一些分析

1、做出两个差分包

对比两个升级包可以看出,我们只需要处理system  和vendor部分,其他驱动文件原生处理为了整包升级,所以01-03 和 02-03 中是一样的

2、修改01-03升级包,

修改updater-scrypt,以以下格式处理脚本文件

if getprop("ro.build.date.utc") == "1562576172" then

01-03升级脚本

......

else

02-03升级脚本

......

endif;

 

修改01-03升级包中system vendor文件的名称

system01.transfer.list system01.new.dat system01.patch.dat

vendor01.transfer.list vendor01.new.dat vendor01.patch.dat

同时修改updater-scrypt 中01-03脚本中的system vendor的名称

 

3、将02-03中升级包的updater-scrypt中的内容直接复制到else 后的部分,这里不用做任何的更改,全部脚本复制

 

4、将02-03中system 和 vendor的相关文件放入到 之前处理的的升级包中

处理后的截图如下

这样处理完后验证,发现刷01版本 可以正常升级到03 ,但是刷机到02 却无法升级到03,报错patch失败

recovery的log如下,看错误确实走进了else方法,因为02-03的cache判断是25841664 needed

 

[    6.998341] SELinux: Loaded file_contexts
[    6.998551] Source: LEAGOO/Z10/Z10:8.1.0/O11019/1553496128:user/release-keys
[    6.998579] Target: LEAGOO/Z10/Z10:8.1.0/O11019/1565838105:user/release-keys
[    6.998732] Verifying current system...
[    6.998805] 108990464 bytes free on /cache (25841664 needed)
[   19.534887] Verified system image...
[   20.454253] Verified vendor image...
[   20.454349] Patching system image after verification.
[   20.454449] performing update
[   20.462901] blockimg version is 4
[   20.462951] maximum stash entries 0
[   20.465919] creating stash /cache/recovery/3a0104144fd74fc8745d8bb2737492c5611934b0/
[   20.466837] 108986368 bytes free on /cache (25841664 needed)
[   20.466929]  erasing 68874 blocks
[   20.592881] stashing 284 overlapping blocks to a7201da77719855292aa705ec24e88804b4c1a68
[   20.592944] 108986368 bytes free on /cache (1163264 needed)
[   20.593019]  writing 284 blocks to /cache/recovery/3a0104144fd74fc8745d8bb2737492c5611934b0/a7201da77719855292aa705ec24e88804b4c1a68
[   20.667376] patching 284 blocks to 284
[   20.667434] Not a bsdiff patch.
[   20.667448] bspatch failed, result: 2
[   20.667460] Patch may be corrupted, offset: 0, SHA1: 03110be20c1d315bc6814caa3e1086b042f907ae
[   20.667475] Failed to apply bsdiff patch.
[   20.667488] failed to execute command [bsdiff 0 210 a7201da77719855292aa705ec24e88804b4c1a68 a819a07d4258d79f6fa909984c0933983f211e9b 2,189705,189989 284 2,189705,189989]
[   20.669709] script aborted: E1001: Failed to update system image.
[   20.669829] Patch application failed, retry update.

这里报错是patch文件不对,起初怀疑是不是用错了02的包,但是实际测试02-03原始升级包是可以升级成功的

目前针对这个错误判断是我们拷贝后的dat文件损坏了,但是对比跟02-03原包是一样,所以基本上是卡这儿了,只能填坑了

 

5、生成差分包dat文件处理

既然我们这样手动放入或者用zip命令不行,只能看最初的生成差分包时,是怎么把dat文件放入到升级包中

ota_from_target_file.py

def WriteBlockIncrementalOTAPackage(target_zip, source_zip, output_zip):
  ......
  ......
  system_diff.WriteScript(script, output_zip,
                          progress=0.8 if vendor_diff else 0.9)

  if vendor_diff:
    vendor_diff.WriteScript(script, output_zip, progress=0.1)

common.py

WriteScript方法

  def WriteScript(self, script, output_zip, progress=None):
    if not self.src:
      # write the output unconditionally
      script.Print("Patching %s image unconditionally..." % (self.partition,))
    else:
      script.Print("Patching %s image after verification." % (self.partition,))

    if progress:
      script.ShowProgress(progress, 0)
    self._WriteUpdate(script, output_zip)
    if OPTIONS.verify:
      self._WritePostInstallVerifyScript(script)

self._WriteUpdate(script, output_zip) 

看到我们想要的代码了 ,处理new.dat 和 patch.dat部分

  def _WriteUpdate(self, script, output_zip):
    ZipWrite(output_zip,
             '{}.transfer.list'.format(self.path),
             '{}.transfer.list'.format(self.partition))

    # For full OTA, compress the new.dat with brotli with quality 6 to reduce its size. Quailty 9
    # almost triples the compression time but doesn't further reduce the size too much.
    # For a typical 1.8G system.new.dat
    #                       zip  | brotli(quality 6)  | brotli(quality 9)
    #   compressed_size:    942M | 869M (~8% reduced) | 854M
    #   compression_time:   75s  | 265s               | 719s
    #   decompression_time: 15s  | 25s                | 25s

    if not self.src:
      bro_cmd = ['bro', '--quality', '6',
                 '--input', '{}.new.dat'.format(self.path),
                 '--output', '{}.new.dat.br'.format(self.path)]
      print("Compressing {}.new.dat with brotli".format(self.partition))
      p = Run(bro_cmd, stdout=subprocess.PIPE)
      p.communicate()
      assert p.returncode == 0,\
          'compression of {}.new.dat failed'.format(self.partition)

      new_data_name = '{}.new.dat.br'.format(self.partition)
      ZipWrite(output_zip,
               '{}.new.dat.br'.format(self.path),
               new_data_name,
               compress_type=zipfile.ZIP_STORED)
    else:
      new_data_name = '{}.new.dat'.format(self.partition)
      ZipWrite(output_zip, '{}.new.dat'.format(self.path), new_data_name)

    ZipWrite(output_zip,
             '{}.patch.dat'.format(self.path),
             '{}.patch.dat'.format(self.partition),
             compress_type=zipfile.ZIP_STORED)

ZipWrite方法

#
def ZipWrite(zip_file, filename, arcname=None, perms=0o644,
             compress_type=None):
  import datetime

  # http://b/18015246
  # Python 2.7's zipfile implementation wrongly thinks that zip64 is required
  # for files larger than 2GiB. We can work around this by adjusting their
  # limit. Note that `zipfile.writestr()` will not work for strings larger than
  # 2GiB. The Python interpreter sometimes rejects strings that large (though
  # it isn't clear to me exactly what circumstances cause this).
  # `zipfile.write()` must be used directly to work around this.
  #
  # This mess can be avoided if we port to python3.
  saved_zip64_limit = zipfile.ZIP64_LIMIT
  zipfile.ZIP64_LIMIT = (1 << 32) - 1

  =================
  <zipfile.ZipFile object at 0x7fd94260b0d0>
  /tmp/tmpBmzgWk/system.patch.dat
  system.patch.dat
  0
  =================
  print("=================")  
  print(zip_file)
  print(filename)
  print(arcname)
  print(compress_type)
  print("=================")
  
  if compress_type is None:
    compress_type = zip_file.compression
  if arcname is None:
    arcname = filename

  saved_stat = os.stat(filename)

  try:
    # `zipfile.write()` doesn't allow us to pass ZipInfo, so just modify the
    # file to be zipped and reset it when we're done.
    os.chmod(filename, perms)

    # Use a fixed timestamp so the output is repeatable.
    epoch = datetime.datetime.fromtimestamp(0)
    timestamp = (datetime.datetime(2009, 1, 1) - epoch).total_seconds()
    os.utime(filename, (timestamp, timestamp))

    zip_file.write(filename, arcname=arcname, compress_type=compress_type)
  finally:
    os.chmod(filename, saved_stat.st_mode)
    os.utime(filename, (saved_stat.st_atime, saved_stat.st_mtime))
    zipfile.ZIP64_LIMIT = saved_zip64_limit

通过打印我们知道了进入ZipWrite的参数,同时我看到了compress_type=zipfile.ZIP_STORED这样一个参数,对于patch.dat,查询后发现这是zipfile模块的一个参数

zipfile.ZIP_STORED

表示非压缩的常量。

那现在就比较明了了,对于dat文件,虽然是放进升级包,但是不做任何压缩的处理,而我们不管是怎么手动放,都对dat进行了压缩,所以我们现在要用zipfile模块写一个脚本去处理dat文件的拷贝

 

6、形成脚本处理升级包

import os
import os.path
import re
import subprocess
import sys
import shlex
import shutil
import tempfile
import threading
import time
import zipfile
import datetime


def ZipWrite(input_zip, filename, arcname=None, perms=0o644):

  # http://b/18015246
  # Python 2.7's zipfile implementation wrongly thinks that zip64 is required
  # for files larger than 2GiB. We can work around this by adjusting their
  # limit. Note that `zipfile.writestr()` will not work for strings larger than
  # 2GiB. The Python interpreter sometimes rejects strings that large (though
  # it isn't clear to me exactly what circumstances cause this).
  # `zipfile.write()` must be used directly to work around this.
  #
  # This mess can be avoided if we port to python3.
  saved_zip64_limit = zipfile.ZIP64_LIMIT
  zipfile.ZIP64_LIMIT = (1 << 32) - 1
  
  saved_stat = os.stat(filename)

  try:
    # `zipfile.write()` doesn't allow us to pass ZipInfo, so just modify the
    # file to be zipped and reset it when we're done.
    os.chmod(filename, perms)

    # Use a fixed timestamp so the output is repeatable.
    # 处理文件的时间戳
    epoch = datetime.datetime.fromtimestamp(0)
    timestamp = (datetime.datetime(2009, 1, 1) - epoch).total_seconds()
    os.utime(filename, (timestamp, timestamp))
    #将传入的文件生成为zipfile对象,传入参数a 代表可以追加文件
    zip_file = zipfile.ZipFile(input_zip, "a")
    #如果我们要追加的文件不在zip_file 文件列表中,执行追加
    if arcname not in zip_file.namelist():
      #使用write方法追加文件,并给到参数zipfile.ZIP_STORED
      zip_file.write(filename, arcname, zipfile.ZIP_STORED)
    else:
      print >> sys.stderr, "%s is already exist,do nothing..." % (arcname)
  finally:
    os.chmod(filename, saved_stat.st_mode)
    os.utime(filename, (saved_stat.st_atime, saved_stat.st_mtime))
    zipfile.ZIP64_LIMIT = saved_zip64_limit
    #处理好后关闭
    zip_file.close()

  return True

def main(argv):

  if len(argv) != 3:
    print(__doc__)
    sys.exit(1)

  input_zip = argv[0]
  filename = argv[1]
  arcname = argv[2]
  #传入的三个参数,1、升级包 2、需要放入的文件 3、放入后文件的名称
  if not ZipWrite(input_zip, filename, arcname):
    print >> sys.stderr, "error: failed to zip %s to %s" % (arcname,zip_file)
    exit(1)


if __name__ == '__main__':
  main(sys.argv[1:])

执行脚本:

./build/tools/releasetools/adups_zipfile_for_dat.py update.zip '/home/adups/FOTA/2019090901/02/target_files-package02/update002/vendor.transfer.list'  vendor.transfer.list

 

使用重新生成的差分包测试01-03 和 02-03 均验证OK,问题解决

NDK实战(五)—— 增量更新(下)—— 合并差分包 Android平台下合并patch差分包 一、添加文件 将 bzip2 的所有 .c 和 .h 文件以及bspatch.c 复制到Android Studio 的 cpp 目录下(记得修改main方法名,保证只有一个main入口) 二、在Cmake.txt中链接所有文件 使用 file(GLOB c_path src/main/cpp/*.c) 可以将所有文件添加为一个 c_path 路径变量 ... 阅读详情

相关推荐

微信小程序逆向分析实战:wxappUnpacker工具原理、使用与问题排查

在移动应用开发领域,逆向工程是一种通过分析已编译程序来理解其内部工作原理的技术。其核心原理在于对二进制文件格式、代码混淆和加密机制进行解析与还原,从而将机器码或中间代码转换回更易读的形式。这项技术的价值不仅在于安全研究和漏洞挖掘,更在于为开发者提供了学习优秀实现、排查线上疑难问题以及进行技术兼容性分析的有效途径。在微信小程序生态中,由于代码经过编译、压缩和加密,线上问题排查和竞品分析常面临“黑盒”挑战。wxappUnpacker正是针对此场景的Node.js工具链,它能对经过加密的.wxapkg包文件进行解

weixin_30588675的博客 453

aosp源码分析 5.0 BlockImageUpdateFn

block_image_update("/dev/block/bootdevice/by-name/system", package_extract_file("system.transfer.list"), "system.new.dat", "system.patch.dat"); // args: //    - block device (or file) to modify 

rockly89的博客 2278

深入解析Android OTA升级:从架构原理到实战调试

系统升级是移动设备维护与功能演进的核心机制,其本质是通过安全可靠的方式更新设备固件。在Android生态中,OTA(Over-The-Air)技术实现了这一过程的远程自动化,其底层原理涉及Bootloader引导、分区管理、安全校验与差分算法等多个技术模块的协同。从技术价值看,OTA不仅保障了系统安全性与功能迭代,还通过A/B分区、动态分区等机制极大提升了升级过程的可靠性与用户体验。在应用场景上,无论是手机厂商的系统推送、第三方ROM定制,还是物联网设备的固件更新,都深度依赖OTA技术栈。本文将聚焦Andr

weixin_30247781的博客 335

android rom打包解包工具,Android ROM包定制(解包,增删模块,打包)

解包 假设有一个名为update.zip的ROM包,我们要在Ubuntu下对它进行定制。首先把system.transfer.list和system.new.dat.br(有些旧版的系统的镜像可能是system.new.dat)从update.zip解压出来,转成system.img(原始镜像格式),修改完后又按步骤打包回原来的格式。本文只写了system分区的定制方法,但是对于其他分区也是类似的,都要转成原始镜像格式后才能对它修改。如果使用file system.img命令来查看system.img文件

带着梦想裸奔 6001

Unity项目包体优化:Build Report Tool深度解析与实战瘦身策略

在游戏开发中,包体大小是影响用户体验和项目成功的关键性能指标。其核心原理在于构建管线对项目资源的收集、处理和打包过程,任何未被优化的资源都会直接导致最终应用体积膨胀。从技术价值看,有效的包体管理不仅能降低用户下载门槛和存储成本,还能提升应用商店的曝光率与留存率。常见的应用场景包括移动端游戏、应用分发以及任何对安装包大小敏感的项目。针对这一需求,Unity社区的Build Report Tool插件提供了详尽的构建后分析能力,它能精确诊断出纹理、音频等资源的体积占比,帮助开发者定位冗余资产。通过结合纹理压缩、

weixin_33985507的博客 325

瑞萨RX FIT固件更新模块线性模式配置与内存映射实战解析

固件空中升级(FOTA)是嵌入式设备实现远程维护与功能迭代的核心技术,其基础在于引导加载程序(Bootloader)的稳定运行。Bootloader作为设备上电后最先执行的代码,负责初始化硬件、验证应用程序完整性并决定执行路径,其设计直接关系到系统的启动安全与可维护性。在资源受限的微控制器(MCU)上实现FOTA,关键在于高效、可靠的内存管理,这通常涉及对内部Flash存储器的精细划分与访问控制。瑞萨电子的RX系列MCU广泛用于工业与物联网领域,其提供的固件集成技术(FIT)模块封装了底层驱动,为开发者实现

java天气 382

解读 SEOmator 技术架构:从 CLI 到 5 种报告的完整数据流

SEOmator(仓库 seo-audit-skill)是一个开箱即用的 SEO 审计命令行工具:内置 373 条审计规则、覆盖 20 个类别,一条命令就能扫完一个网站,并可输出 console、JSON、HTML、Markdown、LLM 共 5 种格式的报告。这篇文章用 6 个步骤带你走读它的技术架构:一次 `seomator audit` 背后,数据是如何从 URL 一路流向报告的。 >

gitblog_00261的博客 112

安卓Recovery原理深度解析:从启动机制到刷机救砖实战

在移动操作系统领域,系统恢复与更新机制是保障设备稳定性的核心技术。其原理基于独立的引导环境,通过特定的启动链(如Bootloader决策、内核参数传递)实现与主系统的隔离。这项技术的核心价值在于为系统维护、故障修复和版本升级提供了一个安全、可靠的底层操作平台,广泛应用于OTA更新、数据清除、设备救砖等关键场景。理解其启动流程(如adb reboot recovery指令的传递路径)和分区操作机制(如对data分区的格式化),是进行安卓系统高级调试与深度定制的基础。本文聚焦于安卓Recovery,深入剖析其作

weixin_34248023的博客 354

小程序架构深度解析:从双线程模型到性能优化实战

小程序作为一种融合了前端、客户端与云端能力的混合技术体系,其核心在于一套受控的渲染容器与独特的双线程架构。从技术原理上看,它通过逻辑层与视图层的隔离设计,实现了安全性与一致性的平衡,所有交互均通过JSBridge进行异步通信。这种架构带来了数据驱动的编程范式,但也引入了setData通信的性能瓶颈,是优化关键。在工程实践中,理解其渲染原理、通信机制与组件化设计,对于构建高性能、可维护的应用至关重要。本文聚焦小程序的核心架构,深入探讨其双线程模型、setData优化策略及常见问题排查,帮助开发者掌握底层原理,

weixin_34126557的博客 341

【AVDTP】规范精讲[8-6]: 信令信息元素与服务能力全解析,从字段定义到协商流程

在蓝牙音视频传输体系中,AVDTP(音视频分发传输协议)是整个传输链路的控制核心,而信令消息则是所有设备交互的载体。两个蓝牙设备要建立稳定的音视频流,必须经过端点发现、能力查询、参数协商、流建立、启动传输等一系列握手流程。这整个过程的所有交互,都离不开两类核心基础:构成信令消息的信息元素,以及决定流配置的服务能力。

byte轻骑兵的技术小窝 8878

微信原生框架开发教育类小程序:POYI英语学习实战复盘

跨端框架如uni-app和Taro通过一套代码覆盖多端,但教育类小程序在音频播放、语音录制、长期存储等底层能力上,往往需要回归微信原生API处理焦点冲突与真机兼容问题。原生开发以对包体积、组件行为和调试链路的强可控性,换来更稳定的体验交付与更短的排错路径。在单词记忆、听力训练、口语评测等高频交互场景中,优雅设计数据模型与页面生命周期,可有效规避音频抢占、分包超限和渲染白屏等典型陷阱。当学习类产品需要精细管理登录态、本地缓存与云同步,并兼顾审核合规时,基于微信原生框架的工程化方案能提供清晰、直接的落地路径。本

weixin_34401479的博客 382

Unity WebGL游戏加载速度优化全链路实战:从压缩到进度条美化

在WebGL游戏开发中,资源加载速度是影响用户体验的关键因素。其核心原理在于,游戏资源需通过网络下载并在浏览器中解析初始化,任何环节的瓶颈都会导致加载延迟。优化加载速度不仅能提升用户留存率,更是工程实践中的重要环节。通过资源压缩技术(如Brotli、纹理ASTC格式)和构建配置优化,可有效减少网络传输数据量。结合按需加载策略与进度条美化,能显著改善玩家感知,适用于各类追求快速启动的WebGL应用场景。本文聚焦Unity WebGL,深入探讨如何通过全链路优化解决加载缓慢这一核心痛点。

weixin_30824599的博客 486

红米Note7|lineage18.1| 安卓11.0|红米Note7.zip

解锁后刷入 红米Note7|lineage18.1| 安卓11.0|顶级流畅|唯美清新|全新手势|强力推荐

UniApp 鸿蒙实战:应用性能优化全攻略

仓库详情页是 AtomGit APP 的核心页面之一,用户可以在这里查看仓库的完整信息、浏览文件结构、查看代码内容等。文件树浏览功能则是开发者工具类应用的标配,能够清晰地展示仓库的文件结构。本文详细介绍了 AtomGit APP 仓库详情页与文件树浏览功能的实现,包括仓库信息展示、文件树组件开发、代码文件查看、README 渲染等核心功能。

2502_92709686的博客 312

全志T113 Tina5.0开发:(一)添加自己的板级支持包

3.验证 先执行 source build/envsetup.sh ,然后lunch,下图可见9就是我们自己添加的板子。2. 1)修改 t113-evb1.mk重命名为t113-ws_devboard。我使用的spinand,只需要修改openwrt里面的文件即可。以下内容仅作为自己笔记,如果错误欢迎留言指出。修改t113-ws_devboard。

u014428915的博客 1164

calibre QRC提取寄生参数

typical将上面的文件QCI_flow里面的文件 在Cp 到当前 ,其实应该是某几个文件,但是我给忘记了 就全cp过来了 ,无影响,不过也希望大佬指正。

2202_75711937的博客 1519

大模型API选型实战:协议差异、Token计费与流式响应工程陷阱

大模型API调用远不止传参调用,本质是协议层、计费逻辑与流式链路的系统工程。理解RESTful设计差异(如鉴权头、错误结构、端点路径)决定SDK兼容性;掌握各模型tokenizer实现与padding机制,才能精准预估token消耗与真实成本;而流式响应的字段命名、UTF-8分块、TCP分包处理,直接关系前端实时性与用户体验。本文基于GPT-5.4 mini、Claude 4.6、DeepSeek V3和Qwen 3四款主流轻量级模型的72小时生产级压测,揭示API层面隐藏的稳定性瓶颈、静默截断、错误码歧义

weixin_34248023的博客 587

SD - WAN:企业出海的网络加速器

例如,一家中国的跨境电商企业,在欧美市场的促销活动期间,借助 SD - WAN 技术,即使面对海量订单数据的交互,也能确保欧美客户在浏览商品、下单支付时感受到近乎本地网络的流畅体验,大大提升了客户满意度,稳住了销售增速。企业无需在海外本地部署大量冗余服务器,只需依托云台,借助 SD - WAN 快速稳定的网络连接,即可轻松实现业务拓展,进一步精简运营架构,提升整体效能。在未来,随着技术的不断演进和企业出海需求的持续增长,SD - WAN 将持续赋能,助力更多企业在全球市场扬帆远航,书写辉煌篇章。

idcicp_com的博客 446

前端面试核心考点与高频题解析

前端开发作为现代Web应用的核心环节,其技术体系涵盖HTML/CSS基础、JavaScript语言特性以及主流框架原理。从技术实现原理来看,事件循环(Event Loop)机制决定了异步代码的执行顺序,而闭包则实现了函数作用域的延续,这两者都是JavaScript的核心概念。在工程实践层面,Flex/Grid布局解决了传统CSS布局难题,虚拟DOM技术提升了框架渲染性能。本文聚焦前端工程师面试中的高频考点,包括localStorage与sessionStorage的差异分析、React Fiber架构优化原

weixin_33924220的博客 338

Cadence AMS数模混合仿真:从零搭建高效验证环境的实战指南

本文是Cadence AMS数模混合仿真的实战指南,详细介绍了如何从零搭建高效的芯片验证环境。内容涵盖环境准备、Testbench创建、核心Config视图与ADE设置、仿真运行调试及性能加速技巧,旨在帮助工程师解决SoC设计中数字与模拟模块的集成验证难题,确保芯片设计一次成功。

weixin_29164091的博客 323

Fortigate 在AWS中配置HA

方案1: 1、将两台服务器配置在相同可用区中,使用飞塔原生HA功能,可以实现配置同步功能。 2、配置SSLVPN,在主服务器不可用时,可以实现自动切换到备用服务器继续提供VPN服务。 当前问题: 1、主挂掉后可以自动切换到备,但是原主服务器修复后不会自动切换到主状态。 2、如下图所示切换中丢包明显,需要客户端开启“保持连接”功能。 配置过程如下: 1、整体架构 2、创建VPC和子网,如下图所示...

子苏蓝莓的博客 892

基于微信小程序的原生开发流程实践——从0到可用

本文系统介绍了微信小程序原生开发的完整流程。首先概述了小程序的发展现状和技术特点,对比了原生开发与跨端框架的优劣势。随后详细讲解了开发环境搭建、项目结构解析、核心开发概念(双线程模型、生命周期、数据绑定等),并通过一个待办事项应用的实战案例演示了页面开发、逻辑实现和本地存储等关键技术。最后探讨了网络请求封装、用户登录、性能优化等进阶功能,以及测试发布流程。全文提供了丰富的代码示例和最佳实践,适合开发者快速掌握小程序原生开发的核心技能。

油墨香^-^的博客 196

C#项目实战——【实例】企业人事管理系统(二):4、数据库与数据表设计;5、创建项目;

(1)展开新建的db_PWMS数据库节点,选中“表”节点,单击鼠标右键,在弹出的快捷菜单中选择“新建表”命令,如下图:(2)在SQL Server 2008管理器的右边显示一个新表,这里输入要创建的表中所需要的字段,并设置主键,如下图:(3)单击“保存”按钮,弹出“选择名称”对话框,如下图,输入要新建的表名“tb_Login”,单击“确定”按钮,即可在数据库中添加一个表。

做有价值的事,积累有价值的笔记! 1621

小程序:300知识点/速查手册/微信原生小程序入门→中级→高级 + UniApp 跨端全栈

本文是一份小程序开发速查手册,涵盖从入门到高级的200个核心知识点。内容分为11大模块:基础架构、模板语法、样式规范、配置文件、生命周期、组件化开发、路由通信、原生API、分包工程化、性能优化及实战案例。重点解析小程序双线程架构、WXML/WXSS特性、组件化方案、setData机制、分包策略等核心技术,并提供性能优化技巧、安全规范和常见坑点解决方案。手册采用知识点编号形式,便于快速定位,适合开发者系统学习或日常查阅,帮助掌握小程序全栈开发能力。

snow的博客 527

基于ZYNQ的HP总线与DDR交互:实现PL与PS高效数据传输的完整指南

本文将深入探讨如何通过AXI HP总线实现PL与PS的DDR交互,结合代码示例、硬件配置与创新优化,助力开发者掌握这一关键技术。ZYNQ内部通过AXI HP接口直接连接PL与DDR控制器,PL通过AXI协议发送读写请求,绕过PS的CPU直接操作DDR。通过AXI HP总线实现PL与PS的DDR交互,开发者可充分发挥ZYNQ异构架构的优势。在Xilinx ZYNQ系列芯片中,PS(Processing System)与PL(Programmable Logic)的协同设计是其核心优势。

QQ_778132974的博客 1223

ICM20948 DMP代码详解(69)

ICM20948 DMP代码详解(69)

phmatthaus的专栏 617
上一篇: 一些常用实用的命令整理
下一篇: 二、A/B 升级update_engine分析-整体模块
李标标
博客等级 码龄11年 124粉丝 43原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值