你真的懂使用Runtime进行swizzle的最佳写法?

本文介绍iOS开发中Runtime方法交换的不同写法及其优劣对比。详细分析了一般写法与更优写法的区别,并解释了为什么某些情况下需要采取不同的处理方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

runtime 的黑魔法很多人都一定听过,或者已经在使用了。但是,怎么swizzle方法才是最好呢?

一般写法

Method originalMethod = class_getInstanceMethod(aClass, originalSel);
    Method swizzleMethod = class_getInstanceMethod(aClass, swizzleSel);
    method_exchangeImplementations(originalMethod, swizzleMethod);

或者是下面这种方式,swizzle第二种写法:

   Method originalMethod = class_getInstanceMethod(aClass, originalSel);
    Method swizzleMethod = class_getInstanceMethod(aClass, swizzleSel);
    BOOL didAddMethod = class_addMethod(aClass, originalSel, method_getImplementation(swizzleMethod), method_getTypeEncoding(swizzleMethod));
    if (didAddMethod) {
        class_replaceMethod(aClass, swizzleSel, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
    }else{
        method_exchangeImplementations(originalMethod, swizzleMethod);
    }

更好写法

其它,这样写,一般不会有问题,但是在一些情况下,比如这个hook的类没有实现你要swizzle的方法,这时是没有swizzle成功的,然后你自己写的 swizzle 里又自己调用自己,就无限循环。

    Method originalInsMethod = class_getInstanceMethod(class, originalSelector);
    // 处理为实例方法
    if (originalInsMethod)
    {
        method_exchangeImplementations(originalInsMethod, swizzledMethod);
    }else{
        // 处理为类方法
        Method originalClassMethod = class_getClassMethod(class, originalSelector);
        if (originalClassMethod)
        {
            method_exchangeImplementations(originalClassMethod, swizzledMethod);
        }else{
            // 如果hook的类没有实现这个方法,则先添加方法,然后设置方法的IMP为一个空block。否则直接class_replaceMethod,则方法实则没有交接
            class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
            method_setImplementation(swizzledMethod, imp_implementationWithBlock(^(id self, SEL _cmd){}));
        }
    }

总结

至于这个为什么会更好? 有时间在慢慢说啦~

参考


注:本文首发于 iHTCboy's blog,如若转载,请注明来源。

<think>好的,用户想验证PCIe链路的Swizzle配置是否正确,我需要先理解Swizzle在PCIe中的作用。根据引用[2],Swizzle函数用于调整中断引脚号,当设备通过PCI-PCI桥时,中断线需要重新映射。这可能涉及到PCI配置空间中的INTERRUPT_PIN和INTERRUPT_LINE寄存器。 首先,检查配置的正确性通常涉及读取相关寄存器的值。用户需要确认设备的中断引脚分配是否符合PCI规范,特别是在存在桥接设备的情况下。根据引用[2],使用pci_read_config_byte函数读取PCI_INTERRUPT_PIN(0x3D)的值,可以获取设备的中断引脚号,比如1代表INTA,2代表INTB等。 然后,考虑到Swizzle操作可能由桥接器处理,需要检查桥接器的配置是否正确。例如,每个桥接器可能会根据插槽位置调整中断引脚。用户可能需要遍历整个PCI拓扑结构,从根复合体到端点设备,验证每个桥接器的Swizzle逻辑是否正确应用。 另外,引用[3]提到Xilinx的Host驱动可能需要检查设备树中的配置,确保中断映射正确。设备树中的interrupt-map和interrupt-map-mask属性需要与硬件设计匹配,以确保Swizzle后的中断正确路由到CPU的中断控制器。 此外,实际测试方法也很重要。用户可以通过触发中断并观察系统响应,比如使用工具向设备发送命令,检查对应的中断是否被正确捕获。同时,使用lspci命令查看设备的中断分配情况,确认INTERRUPT_LINE是否正确配置。 最后,可能需要结合硬件信号测试,比如使用逻辑分析仪或示波器监测物理引脚的电平变化,确保Swizzle逻辑在硬件层面正确实现。这对于深层调试尤其重要,特别是在软件配置正确但硬件行为不符的情况下。 总结步骤:1. 读取配置寄存器的中断引脚信息;2. 检查桥接器的Swizzle逻辑;3. 验证设备树的中断映射;4. 使用工具测试中断行为;5. 必要时进行硬件信号测试。</think>### 验证PCIe链路Swizzle配置正确性的方法 #### 1. **检查PCI配置空间的中断引脚分配** - 通过读取设备配置空间中的`PCI_INTERRUPT_PIN`(偏移`0x3D`)和`PCI_INTERRUPT_LINE`(偏移`0x3C`)寄存器,确认设备的中断引脚(INTA/B/C/D)是否与PCI规范一致[^2]。 - 示例代码: ```c u8 pin, line; pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &line); ``` - 结果解释:`pin`值为`1-4`分别对应`INTA-INTD`,`line`值为操作系统分配的中断号。 #### 2. **验证PCI-PCI桥的Swizzle逻辑** - PCI-PCI桥会重新映射下游设备的中断引脚。需遍历总线拓扑,检查桥接设备是否按规则调整中断引脚号。例如: - 下游设备`INTA`可能被映射到上游桥的`INTB`[^2]。 - 工具支持:使用`lspci -vvv`查看设备的中断引脚和线路分配。 #### 3. **设备树中断映射验证(针对嵌入式场景)** - 在设备树中,确认`interrupt-map`和`interrupt-map-mask`属性是否正确描述Swizzle规则。例如: ```dts interrupt-map = <0x0000 0x0 0x0 0x1 &gic 0x30 0x0>; /* INTA映射到GIC中断号0x30 */ ``` - 确保驱动在`probe`阶段正确解析设备树中的中断配置[^3]。 #### 4. **触发中断测试** - 通过工具(如`devmem2`)或设备功能触发中断,观察`/proc/interrupts`中对应中断号的计数是否增加。 - 示例命令: ```bash watch -n 1 "cat /proc/interrupts | grep '设备名'" ``` #### 5. **硬件信号测试(深度调试)** - 使用逻辑分析仪监测PCIe设备的物理中断引脚(如PERST#、CLKREQ#),观察信号是否符合预期。 - 对比Swizzle规则调整前后的信号变化,确认硬件逻辑正确。 #### 总结流程图 ```mermaid graph TD A[读取PCI_INTERRUPT_PIN/LINE] --> B{是否符合Swizzle规则?} B -- 是 --> C[检查下游桥接设备] B -- 否 --> D[修正配置或驱动逻辑] C --> E[验证设备树中断映射] E --> F[触发中断测试] F --> G{中断响应正确?} G -- 是 --> H[配置正确] G -- 否 --> I[硬件信号调试] ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值