深入解析B站androidApp接口:從bilibili.api.ticket.v1.Ticket/GetTicket到SendMsg的技術分析

前言

最近一段時間,我對B站的App接口進行了深入分析,特別是關注了認證機制和私信功能的實現。通過逆向工程和網絡抓包,發現了B站移動端API的底層工作原理,包括設備標識生成機制、認證流程和消息傳輸協議。本文將分享這些研究成果,希望能對API安全設計和防護提供一些思考。

B站接口的基本架構

B站的移動端API采用了gRPC作為主要通信協議,這與普通的REST API有較大區別。gRPC使用Protocol Buffers(protobuf)進行數據序列化,具有更高的效率和更嚴格的類型檢查。

gRPC請求結構

B站的API請求通常包含以下幾個關鍵部分:

[壓縮標志(1字節)][消息長度(4字節)][Protobuf消息體]
  • 壓縮標志:通常是0(不壓縮)或1(gzip壓縮)
  • 消息長度:大端序的4字節整數,表示消息體的長度
  • 消息體:使用protobuf編碼的實際數據

例如,一個典型的請求可能是:

00 00 00 00 52 0A 2A 08 88 F3 EC 8A 01 10 01 18 E4 C7 A0 85 01 20 E9 8D FF E7 07 28 01 32 0F 7B 22 63 6F 6E 74 65 6E 74 22 3A 22 32 22 7D 80 01 01 2A 24 65 65 62 35 35 63 38 37 2D 66 32 36 34 2D 34 39 64 33 2D 61 61 39 62 2D 63 37 36 34 39 66 36 31 39 34 33 38

其中:

  • 00 - 不使用壓縮
  • 00 00 00 52 - 消息長度為82字節
  • 剩余部分 - protobuf編碼的消息體

設備標識機制深度解析

BUVID生成機制

BUVID (Bilibili Unique Video ID) 是B站用來唯一標識設備的關鍵值,其生成過程如下:

def generate_buvid(device_id, buvid_type):"""生成BUVID (B站設備唯一標識)參數:device_id: 設備ID (根據buvid_type的不同可以是AndroidID、MAC等)buvid_type: BUVID類型 (XX代表Android ID, XY代表MAC地址)"""# 預處理device_idif buvid_type == BUVIDType.MAC:device_id = device_id.replace(":", "")# 計算device_id的MD5值并轉為大寫id_md5 = hashlib.md5(device_id.encode('utf-8')).hexdigest().upper()# ..............(敏感信息脫敏處理)# 最終BUVID: 類型前綴 + ID_E + MD5buvid = buvid_type + id_e + id_md5return buvid

BUVID的格式為:XX/XY + 3位特征碼 + 32位MD5,共37位字符。

設備指紋(fp_local)生成與BUVID的關系

設備指紋(fp_local)與BUVID密切相關,通常用于二次驗證設備身份。fp_local的生成依賴于BUVID,同時也考慮了設備型號和無線電版本信息:

def generate_fp(buvid, device_model, device_radio):"""根據BUVID生成設備指紋"""# 1. 構建基礎字符串并計算MD5base_str = buvid + device_model + device_radiomd5_hex = hashlib.md5(base_str.encode('utf-8')).hexdigest()# 2. 添加時間戳time_str = datetime.now().strftime("%Y%m%d%H%M%S")# 3. 添加隨機字符串(16位十六進制)random_hex = ''.join(random.choice('0123456789abcdef') for _ in range(16))# 4. 合并所有部分fp_base = md5_hex + time_str + random_hex# 5. 計算校驗和,這里是關鍵部分。所以隨機生成并不能通過驗證calculate_checksum就不公布了checksum = calculate_checksum(fp_base)# 6. 返回完整指紋return fp_base + checksum

關鍵點:

  1. fp_local的首32位是由BUVID、設備型號和無線電版本共同決定的MD5值
  2. 接下來14位是生成時的時間戳
  3. 再加上16位隨機數據
  4. 最后2位是校驗和

BUVID與fp_local的關系驗證:

def verify_fp(buvid, fp, device_model, device_radio):"""驗證FP是否與BUVID匹配"""# 1. 提取FP中的MD5部分(前32個字符)fp_md5 = fp[:32]# 2. 計算預期的MD5base_str = buvid + device_model + device_radioexpected_md5 = hashlib.md5(base_str.encode('utf-8')).hexdigest()# 3. 驗證MD5部分是否匹配if fp_md5 != expected_md5:return False# 4. 驗證校驗和fp_base = fp[:-2]expected_checksum = calculate_checksum(fp_base)actual_checksum = fp[-2:]# 5. 返回校驗和是否匹配return expected_checksum == actual_checksum

這種設計確保了:

  • 設備更換后無法保持相同的指紋
  • 服務器可以驗證設備指紋的真實性
  • 可以檢測設備信息的篡改

Ticket認證機制分析

JWT格式的Ticket結構

Ticket采用JWT(JSON Web Token)格式,由三部分組成:Header、Payload和Signature。

典型的B站Ticket如下:

eyJhbGciOiJIUzI1NiIsImtpZCI6InMwMyIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3NDQ2NTYxNjcsImlhdCI6MTc0NDYyNzA2NywiYnV2aWQiOiJYVUY4MjRFRkQ3NjUyNTE5NzhCOEIyNzlEMDYyODNFQkQ1OTZFIn0.flJFBus6TltpIlD_byS2bM0kzXyQe0o-5ndOnrtuTOc

解析后:

  • Header: {"alg":"HS256","kid":"s03","typ":"JWT"}
  • Payload: {"exp":1744656167,"iat":1744627067,"buvid":"XUF824EFD765251978B8B279D06283EBD596E"}
  • Signature: HMAC-SHA256簽名

Ticket獲取請求的構造

獲取Ticket的請求較為復雜,涉及多層嵌套的protobuf消息和簽名計算:

def create_ticket_request(self, device_bin):"""創建Ticket請求數據"""# 創建請求數據request_data = bytearray()# 創建x-fingerprint的值fingerprint_value = self.create_fingerprint_value()# 添加字段1: context (x-fingerprint)# 添加字段1: context (x-exbadbasket)# 將兩個context條目添加到請求中# 添加字段2: key_id = "ec01"# 添加字段3: sign# 壓縮數據compressed_data = gzip.compress(bytes(request_data))# 構造gRPC消息# ----------- 此處省略return bytes(grpc_message)

簽名計算的安全性

簽名計算是認證系統的核心安全機制:

def calculate_app_sign(self, device_bin, fingerprint_value, exbadbasket_value=b''):"""計算應用簽名"""# 簽名密鑰key = b'E2lc5tgtl'  # 注:此處為示例密鑰,非真實值# 將base64編碼的device_bin解碼device_bin_data = base64.b64decode(device_bin)# 創建HMAC對象h = hmac.new(key, digestmod=hashlib.sha256)# 按特定順序更新數據# 此處脫敏處理,省略# 獲取十六進制摘要return h.hexdigest()

Protobuf消息的構造與解析

protobuf字段類型

protobuf編碼中,每個字段都由標簽和值組成:

  • 標簽:(field_number << 3) | wire_type
  • 值:根據wire_type決定編碼方式

常見的wire_type:

  • 0: Varint (int32, int64, bool等)
  • 1: 64-bit (fixed64, double等)
  • 2: Length-delimited (string, bytes, embedded messages等)
  • 5: 32-bit (fixed32, float等)

手動構造protobuf消息

沒有.proto定義文件時,我們需要手動構造protobuf消息,當然你也可以用現成的庫去處理:

def append_tag(self, buf, field_number, wire_type):"""添加字段標簽"""tag = (field_number << 3) | wire_typeself.append_varint(buf, tag)def append_varint(self, buf, value):"""添加varint類型的值"""while value >= 0x80:buf.append((value & 0x7f) | 0x80)value >>= 7buf.append(value & 0x7f)def append_string(self, buf, value):"""添加字符串類型字段"""encoded = value.encode('utf-8')self.append_varint(buf, len(encoded))  # 長度前綴buf.extend(encoded)  # 字符串內容

解析protobuf消息

從二進制數據解析protobuf消息也很關鍵:

def parse_protobuf(data):"""解析protobuf格式數據"""result = {}try:offset = 0while offset < len(data):# 獲取字段編號和類型field_and_type = data[offset]field_num = field_and_type >> 3wire_type = field_and_type & 0x07offset += 1# 基于wire_type處理不同類型的數據if wire_type == 0:  # Varintvalue = 0shift = 0while True:b = data[offset]offset += 1value |= ((b & 0x7f) << shift)if not (b & 0x80):breakshift += 7result[str(field_num)] = valueelif wire_type == 2:  # Length-delimitedlength = 0shift = 0while True:b = data[offset]offset += 1length |= ((b & 0x7f) << shift)if not (b & 0x80):breakshift += 7# 嘗試解析為字符串、JSON或嵌套消息try:string_value = data[offset:offset+length].decode('utf-8')if string_value.startswith('{') and string_value.endswith('}'):try:json_value = json.loads(string_value)result[str(field_num)] = string_valueexcept:result[str(field_num)] = string_valueelse:result[str(field_num)] = string_valueexcept:# 嵌套消息或二進制數據nested_result = parse_protobuf(data[offset:offset+length])if nested_result:result[str(field_num)] = nested_resultelse:result[str(field_num)] = data[offset:offset+length].hex()offset += length# 處理其他wire_type...except Exception as e:print(f"Protobuf解析錯誤: {e}")return result

私信發送功能詳解

私信消息的protobuf結構

私信消息的protobuf結構如下:

消息 {field1: {  // 內部消息field1: 接收者UID (VarInt)field2: 消息類型 (VarInt)field3: 序列號 (VarInt)field4: 設備標識 (VarInt)field5: 標志位 (VarInt)field6: 消息內容JSON (String)field16: 標志位 (VarInt)}field5: 消息ID (String)
}

構造和發送私信

def create_and_send_message(self, content, receiver_uid, message_id=None):"""構造并發送B站私信消息"""# 生成消息IDif message_id is None:message_id = str(uuid.uuid4())# 創建消息數據message_data = bytearray()# 添加內部消息inner_msg = bytearray()# 添加接收者UID# 添加消息類型# 添加序列號# 添加設備標識# 添加標志位# 添加消息內容(JSON格式)# 添加標志位self.append_tag(inner_msg, 16, 0)self.append_varint(inner_msg, 1)# 將內部消息添加到外層消息self.append_tag(message_data, 1, 2)self.append_varint(message_data, len(inner_msg))message_data.extend(inner_msg)# 添加消息IDself.append_tag(message_data, 5, 2)self.append_string(message_data, message_id)# 創建gRPC消息# 準備請求頭headers = {"APP-KEY": "android64","Content-Type": "application/grpc","User-Agent": "...","buvid": self.buvid,"x-bili-device-bin": self.device_bin(),"x-bili-fawkes-req-bin": self.fawkes_req_bin(),"x-bili-locale-bin": "...","x-bili-metadata-bin": self.generate_bili_metadata(),"authorization": f"identify_v1 {self.access_key}","x-bili-ticket": self.ticket# 其他必要的頭信息...}# 發送請求url = "https://app.bilibili.com/bilibili.im.interface.v1.ImInterface/SendMsg"response = requests.post(url, headers=headers, data=bytes(grpc_message))return response

解析Base64編碼的錯誤消息

B站的錯誤響應常常是Base64編碼的protobuf消息:

def parse_base64_protobuf(base64_str):"""解析Base64編碼的protobuf數據"""try:# 補全paddingpadding = len(base64_str) % 4if padding:base64_str += '=' * (4 - padding)# 解碼Base64decoded_data = base64.b64decode(base64_str)# 解析protobufreturn resultexcept Exception as e:print(f"解析Base64 protobuf數據失敗: {e}")return None

例如,錯誤消息CAISBTIxMDI2GlAKJ3R5cGUuZ29vZ2xlYXBpcy5jb20vYmlsaWJpbGkucnBjLlN0YXR1cxIlCKKkARIf5LiN6IO957uZ6Ieq5bex5Y+R6YCB5raI5oGv5ZOmfg解析后可能包含"不允許給自己發送消息"的提示。

技術要點分析

1. 多層認證機制

B站采用了多層認證策略:

  • BUVID:設備唯一標識
  • fp_local:基于BUVID的設備指紋
  • Ticket:JWT格式的臨時憑證
  • access_key:長期授權令牌

這種多層機制增加了偽造身份的難度。

2. 簽名驗證

請求過程中,多處使用了HMAC簽名來確保數據完整性和來源可靠性。例如:

  • Ticket請求中對device_bin和fingerprint_value進行簽名
  • JWT格式的Ticket本身也包含簽名

3. 設備指紋算法

設備指紋(fp_local)的生成算法具有以下特點:

  • 基于設備特征(BUVID、型號、無線電版本)
  • 包含時間戳,允許追蹤指紋生成時間
  • 添加校驗和,驗證數據完整性
  • 部分隨機化,防止完全預測

4. protobuf格式的優勢利用

B站充分利用了protobuf的優勢:

  • 高效的序列化/反序列化
  • 嚴格的類型檢查
  • 二進制格式難以直接分析和修改
  • 版本兼容性好

5. 協議頭中各個值的算法

Ascii 類

user-agent 客戶端 UA, 必需.
device_model 設備 Model
device_build 設備 Build
app_ver APP 版本號
mobi_app APP 包類型
app_build APP 版本號
app_build_inner APP 版本號(內部)
x-bili-gaia-vtoken 暫時留空.
x-bili-aurora-eid 未登錄留空. 必需.
x-bili-mid 用戶 UID, 未登錄默認為 0. 必需.
x-bili-aurora-zone 留空. 必需.
x-bili-trace-id 如 16e903399574695df75be114ff63ac64:f75be114ff63ac64:0:0. 需要算法處理. 必需.
authorization 鑒權, 登錄時設定為 identify_v1 {access_key}, 未登錄時無需此項.
buvid 設備唯一標識, 有自己的一套算法.
bili-http-engine cronet
te trailers

Binary 類

x-bili-fawkes-req-bin 設備 Fawkes 信息,加密信息,必須
x-bili-metadata-bin 使用 Metadata 生成. 加密信息,必須
x-bili-device-bin 設備信息, 加密信息,必須
x-bili-network-bin 設備網絡信息, 加密信息,必須
x-bili-restriction-bin 限制信息, 加密信息,必須
x-bili-locale-bin 設備區域信息,加密信息,必須
x-bili-exps-bin 加密信息,必須

安全漏洞與防范建議

通過分析,我發現了幾個潛在的安全問題及其防范措施:

1. 設備模擬防范

問題:通過分析可以偽造設備信息,包括BUVID和指紋。

防范措施

  • 增加設備特征采集,如硬件序列號、系統指紋等
  • 引入設備行為特征分析,識別異常行為模式
  • 實施設備綁定策略,限制賬號可用設備數量
  • 定期更新設備指紋算法,增加逆向難度

2. 簽名密鑰保護

問題:客戶端存儲的簽名密鑰可能被提取。

防范措施

  • 使用白盒加密技術保護客戶端密鑰
  • 實施密鑰分散存儲和動態派生
  • 定期輪換密鑰
  • 服務端增加額外驗證,不完全依賴客戶端簽名

3. Protobuf結構保護

問題:通過逆向工程可以分析出protobuf結構。

防范措施

  • 混淆字段名和字段編號
  • 定期更新協議結構
  • 添加冗余或誘餌字段
  • 對關鍵字段進行額外加密

4. JWT安全加固

問題:JWT可能面臨重放攻擊或篡改。

防范措施

  • 縮短Token有效期
  • 實施Token綁定(將Token與特定會話或設備綁定)
  • 使用更強的簽名算法(如ES256而非HS256)
  • 服務端維護已吊銷Token列表

5. 請求頻率限制

問題:可能出現API濫用。

防范措施

  • 實施基于賬號和設備的請求頻率限制
  • 為敏感操作增加驗證碼或其他人機驗證
  • 監控異常請求模式并實施自動封禁
  • 對同一設備的多賬號操作進行關聯分析

實踐經驗與優化方向

代碼優化

在研究過程中,我發現以下編碼實踐更有效:

# 更清晰的protobuf構造
def create_message(receiver_id, content):msg = bytearray()# 使用輔助函數增加可讀性add_varint_field(msg, 1, receiver_id)add_string_field(msg, 6, json.dumps({"content": content}))return msg

調試技巧

分析和調試protobuf消息:

def debug_protobuf(hex_data):"""將十六進制數據解析為人類可讀的形式"""data = binascii.unhexlify(hex_data.replace(" ", ""))result = parse_protobuf(data)# 美化輸出return json.dumps(result, indent=2, ensure_ascii=False)

結語

通過對B站App接口的深入分析,我們不僅理解了其身份驗證和消息發送機制,也掌握了protobuf消息的構造和解析技術。這些知識不僅適用于B站,也可以應用到其他使用類似技術棧的應用分析中。

對于API開發者,本文揭示了現代移動應用API安全設計的多層次防護策略,以及可能的改進方向。對于研究者,則提供了一個深入理解gRPC和protobuf在實際應用中如何使用的案例。

希望本文對你了解現代移動應用的API實現有所幫助。記住,技術研究應當遵守倫理和法律邊界,尊重平臺和用戶的權益。

在這里插入圖片描述


本文內容僅供學習和研究使用,請勿用于任何非法或違反相關服務條款的目的。使用本文中的技術進行未授權訪問或攻擊行為可能違反《網絡安全法》等相關法律法規,責任自負,如有需要聯系作者可通過 dGcgQGludm9rZXlvdQ== (base64decode后查看聯系方式) 聯系我。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/901399.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/901399.shtml
英文地址,請注明出處:http://en.pswp.cn/news/901399.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

從零開始學A2A一:A2A 協議概述與核心概念

A2A 協議概述與核心概念 學習目標 基礎理解 掌握A2A協議的基本概念和背景理解協議的設計原則和核心思想了解協議在AI領域的重要性 技術掌握 熟悉A2A協議的核心功能組件掌握能力發現和任務管理機制理解多模態交互和安全通信原則 實踐應用 能夠設計基于A2A的智能體系統掌握協議…

2025.04.10-拼多多春招筆試第三題

?? 點擊直達筆試專欄 ??《大廠筆試突圍》 ?? 春秋招筆試突圍在線OJ ?? 筆試突圍OJ 03. 數字重排最大化問題 問題描述 LYA是一位專業的數字設計師。她手中有兩個數字序列 s 1 s_1

蒼穹外賣day04

Spring Task實現定時處理訂單狀態 作用&#xff1a;不需要輸入提示信號&#xff0c;便可定時自動執行程序 使用步驟 1、啟動類上加上注解&#xff08;EnableScheduling&#xff09;開啟定時任務調度 2、專門創建一個包來管理執行定時任務的類&#xff0c;該類需要交給IOC容…

BFD:網絡鏈路檢測與聯動配置全攻略

目錄 BFD簡介 BFD會話建立方式和檢測機制 BFD會話建立過程 BFD工作流程 聯動功能 BFD與OSPF聯動配置需求 BFD與OSPF聯動配置實現 BFD與VRRP聯動配置需求 BFD與VRRP聯動配置實現 單臂回聲 BFD默認參數及調整方法 BFD簡介 一種全網統一、檢測迅速、監控網絡中鏈…

【LLM】A2A 與 MCP:剖析 AI Agent 互聯時代的兩種關鍵協議

隨著人工智能技術的飛速發展&#xff0c;AI Agent&#xff08;智能體&#xff09;正從理論走向實踐&#xff0c;有望成為提升生產力的關鍵。然而&#xff0c;正如歷史上任何新興技術領域一樣&#xff0c;標準的缺失導致了“筒倉效應”——不同來源、不同框架構建的 Agent 難以有…

免費下載 | 2025清華五道口:“十五五”金融規劃研究白皮書

《2025清華五道口&#xff1a;“十五五”金融規劃研究白皮書》的核心內容主要包括以下幾個方面&#xff1a; 一、五年金融規劃的重要功能與作用 凝聚共識&#xff1a;五年金融規劃是國家金融發展的前瞻性謀劃和戰略性安排&#xff0c;通過廣泛聽取社會各界意見&#xff0c;凝…

滾輪控制目標臂長度調整相機距離

通過鼠標滾輪來控制攝像機目標臂長度 , 調整相機距離 看圖就行,不多說,照著連就完事了

kernel32!GetQueuedCompletionStatus函數分析之返回值得有效性

第一部分&#xff1a;//#define STATUS_SUCCESS 0x0返回值為0 } else { // // Set the completion status, capture the completion // information, deallocate the associated IRP, and // attempt to write the…

UE5 Chaos :渲染網格體 (Render Mesh) 和模擬網格體 是如何關聯的?為什么模擬網格體 可以驅動渲染網格體?

官方文獻&#xff1a;https://dev.epicgames.com/community/learning/tutorials/pv7x/unreal-engine-panel-cloth-editor 這背后的核心是一種常見的計算機圖形學技術&#xff0c;通常稱為代理綁定 (Proxy Binding) 或 表面變形傳遞 (Surface Deformation Transfer)。 關聯機制…

老舊測試用例生成平臺異步任務與用戶通知優化

在現代 Web 開發中&#xff0c;異步任務處理和用戶通知是兩個重要的功能。由于老舊測試平臺【測試用例生成平臺&#xff0c;源碼分享】進行智能化升級后&#xff0c;未采用異步任務處理&#xff0c;大模型推理時間較長&#xff0c;導致任務阻塞&#xff0c;無法處理其他任務&am…

Java使用ANTLR4對Lua腳本語法校驗

文章目錄 什么是ANTLR&#xff1f;第一個例子ANTLR4 的工作流程Lua腳本語法校驗準備一個Lua Grammar文件maven配置新建實體類Lua語法遍歷器語法錯誤監聽器單元測試 參考 什么是ANTLR&#xff1f; https://www.antlr.org/ ANTLR (ANother Tool for Language Recognition) is a…

觀察者模式(行為模式)

觀察者模式 觀察者模式屬于行為模式&#xff0c;個人理解&#xff1a;和發布訂閱者魔模式是有區別的 細分有兩種&#xff1a;推模式和拉模式兩種&#xff0c;具體區別在于推模式會自帶推送參數&#xff0c;拉模式是在接收通知后要自己獲取更新參數 觀察者模式&#xff08;Obs…

內網滲透 --- 之殺軟工具探測

目錄 內網殺軟探測與應對實戰方案 一、總體思路 二、探測階段——殺軟工具與手法 2.1 進程與服務檢測 2.2 注冊表與文件系統檢測 2.3 Nmap 與 NSE 腳本掃描 三、處理階段——探測到殺軟后的應對措施 3.1 分析評估 3.2 應對策略 四、判斷與驗證——注入 webshell 后如…

(2025親測可用)Chatbox多端一鍵配置Claude/GPT/DeepSeek-網頁端配置

1. 資源準備 API Key&#xff1a;此項配置填寫在一步API官網創建API令牌&#xff0c;一鍵直達API令牌創建頁面創建API令牌步驟請參考API Key的獲取和使用API Host&#xff1a;此項配置填寫https://yibuapi.com/v1查看支持的模型請參考這篇教程模型在線查詢 2. ChatBox網頁版配…

【Pandas】pandas DataFrame keys

Pandas2.2 DataFrame Indexing, iteration 方法描述DataFrame.head([n])用于返回 DataFrame 的前幾行DataFrame.at快速訪問和修改 DataFrame 中單個值的方法DataFrame.iat快速訪問和修改 DataFrame 中單個值的方法DataFrame.loc用于基于標簽&#xff08;行標簽和列標簽&#…

Redis存儲“大數據對象”的常用策略及StackOverflowError錯誤解決方案

Hi&#xff0c;大家好&#xff0c;我是灰小猿&#xff01; 在一些功能的開發中&#xff0c;我們一般會有一些場景需要將得到的數據先暫時的存儲起來&#xff0c;以便后面的接口或業務使用&#xff0c;這種場景我們一般常用的場景就是將數據暫時存儲在緩存中&#xff0c;之后再…

【Python】讀取xyz坐標文件輸出csv文件

Python讀取xyz坐標文件輸出csv文件 import sys import numpy as np import pandas as pd from tqdm import tqdm import cv2 import argparsedef read_xyz(file_path):with open(file_path, "r") as f: # 打開文件data f.readlines() # 讀取文件datas []for …

leetcode 139. Word Break

這道題用動態規劃解決。 class Solution { public:bool wordBreak(string s, vector<string>& wordDict) {unordered_set<string> wordSet;for(string& word:wordDict){wordSet.insert(word);}int s_len s.size();//s的下標從1開始起算&#xff0c;dp[j]…

驅動開發硬核特訓 · Day 11(下篇):從 virtio_blk 看虛擬總線驅動模型的真實落地

&#x1f50d; B站相應的視屏教程&#xff1a; &#x1f4cc; 內核&#xff1a;博文視頻 - 總線驅動模型實戰全解析 敬請關注&#xff0c;記得標為原始粉絲。 &#x1f527; 在上篇中&#xff0c;我們已經從理論視角分析了“虛擬總線驅動模型”在 Linux 驅動體系中的獨特定位。…

音視頻轉換器 AV 接口靜電保護方案

方案簡介 音視頻轉換器是將音視頻&#xff08;AV&#xff09;信號轉換成其他格式或信號類型的設備或軟件。 它能夠實現大多數視頻、音頻以及圖像格式之間的轉換&#xff0c;包括但不限于 RMVB、AVI、 MP4、MOV 等常見格式&#xff0c;同時也支持將不同采樣率、位深度、聲道數…