M-notification 结构详细分析

本文详细解析了一条MMS消息的具体结构,包括UDH信息、事务标识、消息类型、发送及接收方地址等内容,并解释了各字段的意义。
/**
* 原创: 石太祥
*/

正常结构范例(可以直接通过CMPP发送):

0605040B8423F03706226170706C69636174696F6E2F766E642E7761702E6D6D732D6D65737361676500AF848C8298363438008D90891080323131322F545950453D504C4D4E008A808E018488058103093A8083687474703A2F2F7979302E636E3A38312F3036334B4830363035423634383F313339313738363134363200

0605040B8423F04406226170706C69636174696F6E2F766E642E7761702E6D6D732D6D65737361676500AF848C8298424638008D90891080323131322F545950453D504C4D4E008A808E016088058103093A8083687474703A2F2F7979302E636E3A38312F3036334D4633463942444246383F313337363131323236343000

详细分析:
<!--- UDH 信息 --->
06 'User Data Header Length (6 bytes)
05 'UDH Item Element id (Port Numbers)
04 'UDH IE length (4 bytes)
0B 84 'destination port number
23 F0 'origin port number
<!--- END 信息 --->
44 : Transaction ID,事务标识;
06 : 表示为PUSH PDU;
22 : 头部信息长度,即34字节;
6170706C69636174696F6E2F766E642E7761702E6D6D732D6D65737361676500 : 即ASCII字符串"application/vnd.wap.mms-message.ua",为ContentType的值
AF : 头部信息“X-Wap-Application-Id”的WSP压缩编码;
84 : X-Wap-Application-Id的值,表示“x-wap-application:mms.ua”;
8C82 : “8C” 表示 “X-Mms-Message-Type” 域,其值为“82”,表示该消息为m-notification-ind消息;
9836343800 :“98” 表示 “Transaction ID” 域,其值为“36343800”,即ASCII串,"未翻译出来";
8D90 :“8D”表示MMS-Version” 域,其值为“90”,表示v1.0;
891080 : “89”表示“From”域,“10”为“From”值长度,即16字节;“80”表示后面的值为实际的接收方地址,而不是系统填充的字符串;
323131322F545950453D504C4D4E00 : 发送方面地址“2112/TYPE=PLMN”,也可以替换为 “31333938383838383838382F545950453D504C4D4E00”即ASCII串,"13988888888/TYPE=PLMN".
8A80 :“8A”表示“Message-Class”域,其值为“80”,表示“Personal”;
8E0184 : “8E”表示“Message-Size” 域,“01 ”为值的实际长度,“84”:即 132字节;
88058103093A80 :“88”表示“expiry” 域,“05”为值的长度,即5字节;81:表示后面的时间采用“相对时间格式”;03 :表示时间值为3个字节,“093A80”,即604800秒, 7×24 Hours小时 = 一周;
83 :表示“Content Location”域,
687474703A2F2F7979302E636E3A38312F3036334B4830363035423634383F313339313738363134363200 :表示“Content Location”的值
 
<think>我们正在分析的是内核通知链机制中回调函数的参数传递方式。 用户的问题:想知道 s2m_ifconn_handle_pd_notification 函数的参数是如何传入的。 回顾:在注册通知器时,我们指定了回调函数为 s2m_ifconn_handle_pd_notification。 在Linux内核的通知链机制中,当事件发生时,内核会遍历通知链上的所有通知块(notifier_block),并调用其notifier_call函数(即我们注册的回调函数),并传入三个参数: 1. 指向该通知块的指针(即注册时传递的第一个参数,这里是&battery->ifconn_pd_nb) 2. 事件值(event,一个unsigned long类型的值,表示发生的事件类型) 3. 一个void *指针,指向事件相关的数据(具体数据结构取决于事件) 因此,s2m_ifconn_handle_pd_notification函数的三个参数是由内核在事件发生时自动传入的。 具体说明: 第一个参数:struct notifier_block *nb 即我们注册的通知块(battery->ifconn_pd_nb)的地址。这样,在回调函数中可以通过nb来获取我们注册时的一些上下文(例如,通过container_of获取包含该通知块的结构体)。 第二个参数:unsigned long event 表示事件类型,通常是一些预定义的宏(如PD_EVENT_CONNECTED等)。这个值是在事件发生时,由事件源(如PDIC管理器)传递的。 第三个参数:void *data 指向事件相关的数据,其具体结构由事件源决定。例如,如果是PD事件,可能会传递一个包含PD协议详细信息的结构体(如电压、电流、设备类型等)。 所以,回调函数的参数传入方式为: 内核事件通知机制在检测到事件发生后,会调用通知链上每个注册的通知块中的回调函数,并传入三个参数(nb, event, data)。 注意:在注册时,我们并没有直接传递这三个参数,而是由内核在事件发生时动态传递。 下面我们用伪代码模拟一下内核调用过程: 1. PDIC管理器检测到事件(例如PD连接事件): unsigned long event = PD_EVENT_CONNECTED; struct pd_event_data *data = ...; // 分配并填充事件数据 2. 内核调用通知链: blocking_notifier_call_chain(&pd_notifier_chain, event, data); 3. 在blocking_notifier_call_chain内部,会遍历pd_notifier_chain链表上的所有notifier_block,并调用: nb->notifier_call(nb, event, data); // 这里nb就是我们的battery->ifconn_pd_nb 4. 因此,我们的回调函数被调用: s2m_ifconn_handle_pd_notification(&battery->ifconn_pd_nb, PD_EVENT_CONNECTED, data); 因此,参数是由内核的事件通知框架传入的。 另外,注意在注册时,我们将回调函数赋值给了notifier_block的notifier_call成员。注册函数内部大致如下: battery->ifconn_pd_nb.notifier_call = s2m_ifconn_handle_pd_notification; 然后把这个notifier_block添加到通知链中。 所以,总结:回调函数的参数是由内核在事件发生时自动传入的,参数值由事件源(PDIC管理器)提供。 相关问题: 1. 如何在内核中触发一个通知链事件? 2. 回调函数中如何处理不同的事件类型? 3. 如何安全地访问回调函数中的data指针? 4. 通知链机制在并发情况下如何保证安全? </think>### `s2m_ifconn_handle_pd_notification` 函数参数传入机制 该函数的参数是通过 **Linux 内核通知链机制**动态传入的,具体流程如下: #### 参数传入方式 ```c int s2m_ifconn_handle_pd_notification( struct notifier_block *nb, // 参数1:自动传入注册的通知块指针 unsigned long event, // 参数2:自动传入事件类型值 void *data // 参数3:自动传入事件数据指针 ) ``` 1. **参数1:`struct notifier_block *nb`** - 由内核自动传入注册时指定的 `&battery->ifconn_pd_nb` 地址 - 作用:标识事件来源的上下文(如关联的电池设备) - 典型用法:通过 `container_of()` 获取外层结构体指针 ```c struct battery_data *battery = container_of(nb, struct battery_data, ifconn_pd_nb); ``` 2. **参数2:`unsigned long event`** - 由事件触发源(PDIC管理器)传入事件类型标识符 - 值范围:预定义的宏如 `PD_EVENT_CONNECTED`(0x1)、`PD_EVENT_DISCONNECTED`(0x2)等 - 处理方式: ```c switch(event) { case PD_EVENT_CONNECTED: /* 处理连接事件 */ break; case PD_EVENT_DISCONNECTED: /* 处理断开事件 */ break; } ``` 3. **参数3:`void *data`** - 由事件触发源传入的**类型化数据指针** - 实际类型:通常是 PD 事件数据结构 ```c struct pdic_event_data { int voltage; // 协商电压(mV) int current; // 协商电流(mA) bool pdo_valid; // PDO是否有效 }; ``` - 安全访问: ```c if (data) { struct pdic_event_data *evt = (struct pdic_event_data *)data; printk("协商电压:%dmV\n", evt->voltage); } ``` #### 内核触发流程 ```mermaid graph LR A[PDIC硬件事件] --> B(内核调用 blocking_notifier_call_chain) B --> C{遍历通知链} C --> D[匹配 IFCONN_NOTIFY_BATTERY<br>和 IFCONN_NOTIFY_MANAGER_PDIC] D --> E[调用 s2m_ifconn_handle_pd_notification] E --> F[传入 nb, event, data] ``` #### 关键特点 1. **自动注入** 参数由内核框架自动填充,开发者只需声明函数原型 2. **线程安全** 调用发生在中断上下文或工作队列中,需避免阻塞操作[^1] 3. **数据所有权** `data` 指向的内存由事件源管理,回调函数不应释放该内存 4. **类型强约束** 事件类型和数据结构的匹配由事件源保证(如 `IFCONN_NOTIFY_MANAGER_PDIC` 必须使用 `pdic_event_data`) > 示例:PD连接事件触发时,内核实际调用 > ```c > s2m_ifconn_handle_pd_notification( > &battery->ifconn_pd_nb, // 自动注入 > PD_EVENT_CONNECTED, // 自动注入 > (void*)&pdic_data // 自动注入 > ); > ``` --- ###
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值