MacOS上 DMG文件

DMG文件基础概念

  1. 定义与特性
    DMG(Disk Image)是macOS专属的磁盘映像格式,采用HFS+/APFS文件系统封装,支持压缩(AES-128/256加密)、分卷和校验功能。其本质是将文件系统结构+数据打包为单一文件,通过虚拟设备节点(/dev/disk*)挂载访问。
  2. 核心用途
    • 软件分发:78%的macOS第三方应用通过DMG分发
    • 数据备份:可创建加密的磁盘映像
    • 系统恢复:部分恢复工具使用DMG存储

macOS选择DMG的技术动因

  1. 完整性保障
    校验和机制确保安装包传输无损,双击时自动验证
  2. 安装流程标准化
    允许开发者自定义安装界面(背景图/协议文档)
  3. 文件系统兼容性
    完美支持macOS特性如资源派生(Resource Fork)

APP安装流程与底层机制

  1. 用户可见操作
  2. 底层执行过程
    • 内核将DMG映射为虚拟设备(如/dev/disk5s1)
    • 挂载到/Volumes/临时目录,文件系统驱动解析元数据
    • 复制操作触发APFS写时复制(CoW)机制

关键问题解析

  1. 挂载点溯源
  2. 大小差异原因
    • DMG压缩存储 vs 挂载后解压状态
    • 文件系统元数据(如HFS+目录B-tree)占用额外空间
  3. 废纸篓仍可访问
    文件句柄保留机制:DMG挂载后系统保持对原始文件的引用,移动至~/.Trash不影响已打开句柄
  4. 不自动卸载的设计考量
    • 用户体验:避免中断用户可能的二次安装
    • 性能优化:减少重复挂载开销
  5. 影响
    • 我们为了节省空间,安装完APP后,就会把安装文件(*.dmg)删掉,由于该文件安装后没有自动卸载,即使删除了,磁盘空间也不会被释放,此时,需要参考下面的手动卸载操作,手动卸载后,磁盘空间理解释放(很爽)

实用操作指南

  1. 手动卸载
  2. 工具差异
    • hdiutil专管磁盘映像,可追溯DMG关联
    • diskutil侧重物理设备管理,无DMG元数据接口
  3. DMG制作示例

    支持参数:

    • -format UDZO:压缩映像
    • -size 100m:预分配空间
  4. 访达中操作
    • 访达中的“位置”里面也可以看到挂载的dmg文件,也可以点击“推出”进行卸载

vscode terminal设置

使用terminal时,快捷键很重要,如:

alt+b (backword): 光标左移一个单词

alt+f (forword): 光标右移一个单词

alt+. : 自动填充上个命令的最后一个单词

但是,默认情况下,可能这个不好使,需要设置 terminal.integrated.macOptionIsMeta ,选中复选框如下:

或者 ⌘ + shift + p 打开settings.json ,添加如下配置:

MacOS 升级

MacOS从14 升级到15。

xcode需要从15升级到16; xcode升级后,xcode已经不能支持iOS12的开发了。

上一次升级MacOS 13 -> 14的时候,xcode也是被迫升级的,xcode从14升级到15之后,我的appcode(2022)就已经抱怨xcode版本太高了,让我降回去使用,然后就一直没使用appcode

 

各版本xcode支持的最低iOS系统版本:

Xcode各版本支持的系统版本如下:‌12

系统支持的最低版本要求

  • iOS:Xcode 13支持iOS 9,而Xcode 14及以上版本最低支持iOS 11。从2024年4月29日起,上传到App Store的App必须使用Xcode 15构建,支持iOS 12及以上的系统版本。

这些信息可以帮助开发者选择合适的Xcode版本和系统版本进行开发和测试,确保应用兼容性和顺利提交到App Store。

目前(2024年)xcode 15还是主流,还能构建iOS12系统上的APP,这些系统上的APP还能继续升级。

当苹果官方要求最低xcode版本为16的时候,就不可能构建出来支持iOS12系统的APP了,换言之,因为iPhone 5s的系统版本最高支持到iOS12,所以,iPhone 5s上的APP就不可能继续升级了。

小学数学问题

问题:

对于一组数字,在不改变原有数字顺序的情况下,删除 m 个数字,使得剩下的 n – m 个数字组成的数最大。

思路:

  1. 维护一个栈:
    • 使用一个栈来存储当前选择的数字。
    • 当遇到一个新的数字时,比较它与栈顶元素。如果新数字更大,并且可以删除栈顶元素(即 m > 0),则弹出栈顶元素。
  2. 处理剩余数字:
    • 如果在遍历完所有数字后,还有剩余的删除次数 m,继续从栈中弹出元素直到 m 减少到 0。
  3. 构建结果:
    • 最终栈中的元素即为保留的最大数。

AI编码实现:(这个实现运行结果不对)

  1. 初始化栈:
    • 使用一个切片 stack 来模拟栈的行为。
  2. 遍历输入字符串:
    • 对于每个字符(数字),检查是否可以删除栈顶元素以使结果更大。
    • 如果可以删除栈顶元素,则弹出栈顶元素,并减少剩余的删除次数 k。
    • 将当前字符压入栈中。
  3. 处理剩余的删除次数:
    • 在遍历完所有字符后,如果还有剩余的删除次数 k,继续从栈中弹出元素直到 k 减少到 0。
  4. 构建结果字符串:
    • 使用 bytes.TrimLeft 去掉结果字符串中的前导零。
    • 如果结果为空,则返回 “0”。

对于输入 num = “27886483” 和 m = 3,程序的输出将是:

这个结果确保了在不改变原有数字顺序的情况下,删除 3 个数字得到的最大可能的数。

 

补充:

stack[len(stack)-1] < digit  的这个逻辑 AI生成的时候是错的,写的是 stack[len(stack)-1] > digit; 手动修改后算法可用

 

由上面逻辑来看,真心不是小学生能够完成的。

golang tcp keepalive

缘起: grpc-client 连接 grpc-server后,空闲连接的情况下,server端会每隔15s向client发送一个keepalive数据包; 从grpc-server的配置中没有找到这个15s的配置,有的只是一个2小时发送一次的应用层的ping包。为啥呢?

分析:

  1. 该数据包可能是系统自己发送的,查看一下sysctl -a|grep tcp |grep keepalive 如下:
    按照这个配置,应该是75s一次才对,和实际的15s不符;难道不是系统发出来的?
  2. kill -19 PID后,发现间隔15s的数据包依然发送,说明肯定是系统发出来的
  3. 由于MacOS上的netstat 无法查看连接的Timer信息,于是使用Linux进行测试,发现keepalive的timer果然是从15s递减至0后就会发送该数据包(这里还发现当时间小于10s时,ss显示的时间单位是错的,把s写成了ms)。
  4. 一定是golang设置了一个和系统默认值不一样的keepalive; 那么是在什么时候设置的呢?从server端的Accept看起吧,发现Listen的时候有一个无法自定义的ListenerConfig,这里面有

 

 

@ net/dialog.go

Listen的时候,KeepAlive是0值,但是在newTcpConn的时候,检测如果是0值,就参考下面的默认值。

@ net/tcpsock.go

 

其实,在grpc/server.go 的grpc.Server.Serve()方法中已经特别说明了这个事情(而且仅就此问题做了说明):