国产精品久久久aaaa,日日干夜夜操天天插,亚洲乱熟女香蕉一区二区三区少妇,99精品国产高清一区二区三区,国产成人精品一区二区色戒,久久久国产精品成人免费,亚洲精品毛片久久久久,99久久婷婷国产综合精品电影,国产一区二区三区任你鲁

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

openharmony源碼靜態(tài)分析

姚小熊27 ? 來(lái)源:整合自博客園 ? 作者:整合自博客園 ? 2021-06-23 15:24 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

放原子開源基金會(huì)(簡(jiǎn)稱“基金會(huì)”)于 2020 年 9 月接受華為捐贈(zèng)的智能終端操作系統(tǒng)基礎(chǔ)能力相關(guān)代碼,隨后進(jìn)行開源,并根據(jù)命名規(guī)則為該開源項(xiàng)目命名為 OpenAtom OpenHarmony(簡(jiǎn)稱“OpenHarmony”)。

OpenHarmony是自主研發(fā)、不兼容安卓的全領(lǐng)域下一代開源操作系統(tǒng)。OpenHarmony內(nèi)核主要包括進(jìn)程和線程調(diào)度、內(nèi)存管理、IPC機(jī)制、timer管理等內(nèi)核基本功能。

#ifndef __scc

#define __scc(X) ((long) (X)) // 轉(zhuǎn)為long類型

typedef long syscall_arg_t;

#endif

#define __syscall1(n,a) __syscall1(n,__scc(a))

#define __syscall2(n,a,b) __syscall2(n,__scc(a),__scc(b))

#define __syscall3(n,a,b,c) __syscall3(n,__scc(a),__scc(b),__scc(c)) //

繼續(xù)搜索發(fā)現(xiàn)有多出匹配,我們關(guān)注arch/arm目錄下的文件,因?yàn)锳RM Cortext A7是Armv7-A指令集的32位CPU(如果是Armv8-A指令集的64位CPU則對(duì)應(yīng)arch/aarch64下的文件):

static inline long __syscall3(long n, long a, long b, long c)

{

register long r7 __ASM____R7__ = n;

register long r0 __asm__(“r0”) = a;

register long r1 __asm__(“r1”) = b;

register long r2 __asm__(“r2”) = c;

__asm_syscall(R7_OPERAND, “0”(r0), “r”(r1), “r”(r2));

}

這段代碼中還有三個(gè)宏,__ASM____R7__、__asm_syscall和R7_OPERAND:

#ifdef __thumb__

#define __ASM____R7__

#define __asm_syscall(。。.) do { \

__asm__ __volatile__ ( “mov %1,r7 ; mov r7,%2 ; svc 0 ; mov r7,%1” \

: “=r”(r0), “=&r”((int){0}) : __VA_ARGS__ : “memory”); \

return r0; \

} while (0)

#else // __thumb__

#define __ASM____R7__ __asm__(“r7”)

#define __asm_syscall(。。.) do { \

__asm__ __volatile__ ( “svc 0” \

: “=r”(r0) : __VA_ARGS__ : “memory”); \

return r0; \

} while (0)

#endif // __thumb__

#ifdef __thumb2__

#define R7_OPERAND “rI”(r7)

#else

#define R7_OPERAND “r”(r7)

#endif

它們有兩個(gè)實(shí)現(xiàn)版,分別對(duì)應(yīng)于編譯器THUMB選項(xiàng)的開啟和關(guān)閉。這兩種選項(xiàng)條件下的代碼流程基本一致,以下僅以未開啟THUMB選項(xiàng)為例進(jìn)行分析。這兩個(gè)宏展開后的__syscall3函數(shù)內(nèi)容為:

static inline long __syscall3(long n, long a, long b, long c)

{

register long r7 __asm__(“r7”) = n; // 系統(tǒng)調(diào)用號(hào)

register long r0 __asm__(“r0”) = a; // 參數(shù)0

register long r1 __asm__(“r1”) = b; // 參數(shù)1

register long r2 __asm__(“r2”) = c; // 參數(shù)2

do { \

__asm__ __volatile__ ( “svc 0” \

: “=r”(r0) : “r”(r7), “0”(r0), “r”(r1), “r”(r2) : “memory”); \

return r0; \

} while (0);

}

這里最后的一個(gè)內(nèi)嵌匯編比較復(fù)雜,它符合如下格式(具體細(xì)節(jié)可以查閱gcc內(nèi)嵌匯編文檔的擴(kuò)展匯編說明):

asm asm-qualifiers ( AssemblerTemplate

: OutputOperands

[ : InputOperands

[ : Clobbers ] ])

匯編模板為:“svc 0”, 輸出參數(shù)部分為:“=r”(r0),輸出寄存器為r0輸入?yún)?shù)部分為:“r”(r7), “0”(r0), “r”(r1), “r”(r2),輸入寄存器為r7,r0,r1,r2,(“0”的含義是,這個(gè)輸入寄存器必須和輸出寄存器第0個(gè)位置一樣) Clobber部分為:“memory”

這里我們只需要記住:系統(tǒng)調(diào)用號(hào)存放在r7寄存器,參數(shù)存放在r0,r1,r2,返回值最終會(huì)存放在r0中;

SVC指令,ARM Cortex A7手冊(cè) 的解釋為:

The SVC instruction causes a Supervisor Call exception. This provides a mechanism for unprivileged software to make a call to the operating system, or other system component that is accessible only at PL1.

翻譯過來(lái)就是說

SVC指令會(huì)觸發(fā)一個(gè)“特權(quán)調(diào)用”異常。這為非特權(quán)軟件調(diào)用操作系統(tǒng)或其他只能在PL1級(jí)別訪問的系統(tǒng)組件提供了一種機(jī)制。

詳細(xì)的指令說明在

到這里,我們分析了鴻蒙系統(tǒng)上應(yīng)用程序如何進(jìn)入內(nèi)核態(tài),主要分析的是musl libc的實(shí)現(xiàn)。

liteos-a內(nèi)核的系統(tǒng)調(diào)用實(shí)現(xiàn)分析

既然SVC能夠觸發(fā)一個(gè)異常,那么我們就要看看liteos-a內(nèi)核是如何處理這個(gè)異常的。

ARM Cortex A7中斷向量表

在ARM架構(gòu)參考手冊(cè)中,可以找到中斷向量表的說明:

f4fa71d9e8dfffc1b1e7c3efcb4001e0.png

可以看到SVC中斷向量的便宜地址是0x08,我們可以在kernel/liteos_a/arch/arm/arm/src/startup目錄的reset_vector_mp.S文件和reset_vector_up.S文件中找到相關(guān)匯編代碼:

__exception_handlers:

/*

*Assumption: ROM code has these vectors at the hardware reset address.

*A simple jump removes any address-space dependencies [i.e. safer]

*/

b reset_vector

b _osExceptUndefInstrHdl

b _osExceptSwiHdl

b _osExceptPrefetchAbortHdl

b _osExceptDataAbortHdl

b _osExceptAddrAbortHdl

b OsIrqHandler

b _osExceptFiqHdl

PS:kernel/liteos_a/arch/arm/arm/src/startup目錄有兩個(gè)文件reset_vector_mp.S文件和reset_vector_up.S文件分別對(duì)應(yīng)多核和單核編譯選項(xiàng):

ifeq ($(LOSCFG_KERNEL_SMP), y)

LOCAL_SRCS += src/startup/reset_vector_mp.S

else

LOCAL_SRCS += src/startup/reset_vector_up.S

endif

SVC中斷處理函數(shù)

上面的匯編代碼中可以看到,_osExceptSwiHdl函數(shù)就是SVC異常處理函數(shù),具體實(shí)現(xiàn)在kernel/liteos_a/arch/arm/arm/src/los_hw_exc.S文件中:

@ Description: Software interrupt exception handler

_osExceptSwiHdl:

SUB SP, SP, #(4 * 16) @ 棧增長(zhǎng)

STMIA SP, {R0-R12} @ 保存R0-R12寄存器到棧上

MRS R3, SPSR @ 移動(dòng)SPSR寄存器的值到R3

MOV R4, LR

AND R1, R3, #CPSR_MASK_MODE @ Interrupted mode

CMP R1, #CPSR_USER_MODE @ User mode

BNE OsKernelSVCHandler @ Branch if not user mode

@ we enter from user mode, we need get the values of USER mode r13(sp) and r14(lr)。

@ stmia with ^ will return the user mode registers (provided that r15 is not in the register list)。

MOV R0, SP

STMFD SP!, {R3} @ Save the CPSR

ADD R3, SP, #(4 * 17) @ Offset to pc/cpsr storage

STMFD R3!, {R4} @ Save the CPSR and r15(pc)

STMFD R3, {R13, R14}^ @ Save user mode r13(sp) and r14(lr)

SUB SP, SP, #4

PUSH_FPU_REGS R1

MOV FP, #0 @ Init frame pointer

CPSIE I @ Interrupt Enable

BLX OsArmA32SyscallHandle

CPSID I @ Interrupt Disable

POP_FPU_REGS R1

ADD SP, SP,#4

LDMFD SP!, {R3} @ Fetch the return SPSR

MSR SPSR_cxsf, R3 @ Set the return mode SPSR

@ we are leaving to user mode, we need to restore the values of USER mode r13(sp) and r14(lr)。

@ ldmia with ^ will return the user mode registers (provided that r15 is not in the register list)

LDMFD SP!, {R0-R12}

LDMFD SP, {R13, R14}^ @ Restore user mode R13/R14

ADD SP, SP, #(2 * 4)

LDMFD SP!, {PC}^ @ Return to user

這段代碼的注釋較為清楚,可以看到,內(nèi)核模式會(huì)繼續(xù)調(diào)用OsKernelSVCHandler,用戶模式會(huì)繼續(xù)調(diào)用OsArmA32SyscallHandle函數(shù);

OsArmA32SyscallHandle函數(shù)

我們這里分析的流程是從用戶模式進(jìn)入的,所以調(diào)用的是OsArmA32SyscallHandle,它的實(shí)現(xiàn)位于kernel/liteos_a/syscall/los_syscall.c文件:

/* The SYSCALL ID is in R7 on entry. Parameters follow in R0..R6 */

LITE_OS_SEC_TEXT UINT32 *OsArmA32SyscallHandle(UINT32 *regs)

{

UINT32 ret;

UINT8 nArgs;

UINTPTR handle;

UINT32 cmd = regs[REG_R7];

if (cmd 》= SYS_CALL_NUM) {

PRINT_ERR(“Syscall ID: error %d !!!\n”, cmd);

return regs;

}

if (cmd == __NR_sigreturn) {

OsRestorSignalContext(regs);

return regs;

}

handle = g_syscallHandle[cmd]; // 得到實(shí)際系統(tǒng)調(diào)用處理函數(shù)

nArgs = g_syscallNArgs[cmd / NARG_PER_BYTE]; /* 4bit per nargs */

nArgs = (cmd & 1) ? (nArgs 》》 NARG_BITS) : (nArgs & NARG_MASK);

if ((handle == 0) || (nArgs 》 ARG_NUM_7)) {

PRINT_ERR(“Unsupport syscall ID: %d nArgs: %d\n”, cmd, nArgs);

regs[REG_R0] = -ENOSYS;

return regs;

}

switch (nArgs) { // 以下各個(gè)case是實(shí)際函數(shù)調(diào)用

case ARG_NUM_0:

case ARG_NUM_1:

ret = (*(SyscallFun1)handle)(regs[REG_R0]);

break;

case ARG_NUM_2:

case ARG_NUM_3:

ret = (*(SyscallFun3)handle)(regs[REG_R0], regs[REG_R1], regs[REG_R2]);

break;

case ARG_NUM_4:

case ARG_NUM_5:

ret = (*(SyscallFun5)handle)(regs[REG_R0], regs[REG_R1], regs[REG_R2], regs[REG_R3],

regs[REG_R4]);

break;

default:

ret = (*(SyscallFun7)handle)(regs[REG_R0], regs[REG_R1], regs[REG_R2], regs[REG_R3],

regs[REG_R4], regs[REG_R5], regs[REG_R6]);

}

regs[REG_R0] = ret; // 返回值填入R0

OsSaveSignalContext(regs);

/* Return the last value of curent_regs. This supports context switches on return from the exception.

* That capability is only used with theSYS_context_switch system call.

*/

return regs;

}

這個(gè)函數(shù)中用到了個(gè)全局?jǐn)?shù)組g_syscallHandle和g_syscallNArgs,它們的定義以及初始化函數(shù)也在同一個(gè)文件中:

static UINTPTR g_syscallHandle[SYS_CALL_NUM] = {0};

static UINT8 g_syscallNArgs[(SYS_CALL_NUM + 1) / NARG_PER_BYTE] = {0};

void SyscallHandleInit(void)

{

#define SYSCALL_HAND_DEF(id, fun, rType, nArg) \

if ((id) 《 SYS_CALL_NUM) { \

g_syscallHandle[(id)] = (UINTPTR)(fun); \

g_syscallNArgs[(id) / NARG_PER_BYTE] |= \

((id) & 1) ? (nArg) 《《 NARG_BITS : (nArg); \

}

#include “syscall_lookup.h”

#undef SYSCALL_HAND_DEF

}

其中SYSCALL_HAND_DEF宏的對(duì)齊格式我做了一點(diǎn)調(diào)整。

從g_syscallNArgs成員賦值以及定義的地方,能看出它的每個(gè)UINT8成員被用來(lái)存放兩個(gè)系統(tǒng)調(diào)用的參數(shù)個(gè)數(shù),從而實(shí)現(xiàn)更少的內(nèi)存占用;

syscall_lookup.h文件和los_syscall.c位于同一目錄,它記錄了系統(tǒng)調(diào)用函數(shù)對(duì)照表,我們僅節(jié)取一部分:

SYSCALL_HAND_DEF(__NR_read, SysRead, ssize_t, ARG_NUM_3)

SYSCALL_HAND_DEF(__NR_write, SysWrite, ssize_t, ARG_NUM_3) //

看到這里,write系統(tǒng)調(diào)用的內(nèi)核函數(shù)終于找到了——SysWrite。

到此,我們已經(jīng)知道了liteos-a的系統(tǒng)調(diào)用機(jī)制是如何實(shí)現(xiàn)的。

liteos-a內(nèi)核SysWrite的實(shí)現(xiàn)

SysWrite函數(shù)的實(shí)現(xiàn)位于kernel/liteos_a/syscall/fs_syscall.c文件:

ssize_t SysWrite(int fd, const void *buf, size_t nbytes)

{

int ret;

if (nbytes == 0) {

return 0;

}

if (!LOS_IsUserAddressRange((vaddr_t)(UINTPTR)buf, nbytes)) {

return -EFAULT;

}

/* Process fd convert to system global fd */

fd = GetAssociatedSystemFd(fd);

ret = write(fd, buf, nbytes); //

它又調(diào)用了write?但是這一次是內(nèi)核空間的write,不再是 musl libc,經(jīng)過一番搜索,我們可以找到另一個(gè)文件third_party/NuttX/fs/vfs/fs_write.c中的write:

ssize_t write(int fd, FAR const void *buf, size_t nbytes) {

#if CONFIG_NFILE_DESCRIPTORS 》 0

FAR struct file *filep;

if ((unsigned int)fd 》= CONFIG_NFILE_DESCRIPTORS)

#endif

{ /* Write to a socket descriptor is equivalent to send with flags == 0 */

#if defined(LOSCFG_NET_LWIP_SACK)

FAR const void *bufbak = buf;

ssize_t ret;

if (LOS_IsUserAddress((VADDR_T)(uintptr_t)buf)) {

if (buf != NULL && nbytes 》 0) {

buf = malloc(nbytes);

if (buf == NULL) { /* 省略 錯(cuò)誤處理 代碼 */ }

if (LOS_ArchCopyFromUser((void*)buf, bufbak, nbytes) != 0) {/* 省略 */}

}

}

ret = send(fd, buf, nbytes, 0); // 這個(gè)分支是處理socket fd的

if (buf != bufbak) {

free((void*)buf);

}

return ret;

#else

set_errno(EBADF);

return VFS_ERROR;

#endif

}

#if CONFIG_NFILE_DESCRIPTORS 》 0

/* The descriptor is in the right range to be a file descriptor.。。 write

* to the file.

*/

if (fd 《= STDERR_FILENO && fd 》= STDIN_FILENO) { /* fd : [0,2] */

fd = ConsoleUpdateFd();

if (fd 《 0) {

set_errno(EBADF);

return VFS_ERROR;

}

}

int ret = fs_getfilep(fd, &filep);

if (ret 《 0) {

/* The errno value has already been set */

return VFS_ERROR;

}

if (filep-》f_oflags & O_DIRECTORY) {

set_errno(EBADF);

return VFS_ERROR;

}

if (filep-》f_oflags & O_APPEND) {

if (file_seek64(filep, 0, SEEK_END) == -1) {

return VFS_ERROR;

}

}

/* Perform the write operation using the file descriptor as an index */

return file_write(filep, buf, nbytes);

#endif

}

找到這段代碼,我們知道了:

liteos-a的vfs是在NuttX基礎(chǔ)上實(shí)現(xiàn)的,NuttX是一個(gè)開源RTOS項(xiàng)目;

liteos-a的TCP/IP協(xié)議棧是基于lwip的,lwip也是一個(gè)開源項(xiàng)目;

這段代碼中的write分為兩個(gè)分支,socket fd調(diào)用lwip的send,另一個(gè)分支調(diào)用file_write;

至于,file_write如何調(diào)用到存儲(chǔ)設(shè)備驅(qū)動(dòng)程序,則是更底層的實(shí)現(xiàn)了,本文不在繼續(xù)分析。

補(bǔ)充說明

本文內(nèi)容均是基于鴻蒙系統(tǒng)開源項(xiàng)目OpenHarmony源碼靜態(tài)分析所整理,沒有進(jìn)行實(shí)際的運(yùn)行環(huán)境調(diào)試,實(shí)際執(zhí)行過程可能有所差異,希望發(fā)現(xiàn)錯(cuò)誤的讀者及時(shí)指正。文中所有路徑均為整個(gè)openharmony源碼樹上的相對(duì)路徑(而非liteos源碼相對(duì)路徑)。

責(zé)任編輯:YYX

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 開源
    +關(guān)注

    關(guān)注

    3

    文章

    4207

    瀏覽量

    46152
  • 鴻蒙系統(tǒng)
    +關(guān)注

    關(guān)注

    183

    文章

    2642

    瀏覽量

    69859
  • OpenHarmony
    +關(guān)注

    關(guān)注

    33

    文章

    3952

    瀏覽量

    21107
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    #OpenHarmony HDC調(diào)試

    OpenHarmony
    視美泰
    發(fā)布于 :2026年01月16日 09:46:28

    #OpenHarmony 開發(fā)環(huán)境準(zhǔn)備

    OpenHarmony
    視美泰
    發(fā)布于 :2026年01月16日 09:44:31

    #OpenHarmony 鏡像燒錄

    OpenHarmony
    視美泰
    發(fā)布于 :2026年01月16日 09:42:36

    #OpenHarmony 系統(tǒng)概述

    OpenHarmony
    視美泰
    發(fā)布于 :2026年01月16日 09:39:20

    #OpenHarmony Hello World應(yīng)用以及部署

    OpenHarmony
    視美泰
    發(fā)布于 :2026年01月16日 09:32:52

    OpenHarmony系統(tǒng)】本期視頻將為您介紹怎樣將鏡像燒錄到板卡中。

    OpenHarmony
    視美泰
    發(fā)布于 :2026年01月15日 14:29:55

    鎖存器中的時(shí)間借用概念與靜態(tài)時(shí)序分析

    對(duì)于基于鎖存器的設(shè)計(jì),靜態(tài)時(shí)序分析會(huì)應(yīng)用一個(gè)稱為時(shí)間借用的概念。本篇博文解釋了時(shí)間借用的概念,若您的設(shè)計(jì)中包含鎖存器且時(shí)序報(bào)告中存在時(shí)間借用,即可適用此概念。
    的頭像 發(fā)表于 12-31 15:25 ?5501次閱讀
    鎖存器中的時(shí)間借用概念與<b class='flag-5'>靜態(tài)</b>時(shí)序<b class='flag-5'>分析</b>

    什么是CVE?如何通過SAST/靜態(tài)分析工具Perforce QAC 和 Klocwork應(yīng)對(duì)CVE?

    本文將為您詳解什么是CVE、CVE標(biāo)識(shí)符的作用,厘清CVE與CWE、CVSS的區(qū)別,介紹CVE清單內(nèi)容,并說明如何借助合適的靜態(tài)分析工具(如Perforce QAC/Klocwork),在軟件開發(fā)早期發(fā)現(xiàn)并修復(fù)漏洞。
    的頭像 發(fā)表于 10-31 14:24 ?525次閱讀
    什么是CVE?如何通過SAST/<b class='flag-5'>靜態(tài)</b><b class='flag-5'>分析</b>工具Perforce QAC 和 Klocwork應(yīng)對(duì)CVE?

    智能小車設(shè)計(jì)源碼和圖紙資料

    智能小車設(shè)計(jì)源碼和圖紙
    發(fā)表于 08-25 15:38 ?1次下載

    汽車軟件團(tuán)隊(duì)必看:基于靜態(tài)代碼分析工具Perforce QAC的ISO 26262合規(guī)實(shí)踐

    ISO 26262合規(guī)指南,從ASIL分級(jí)到工具落地,手把手教你用靜態(tài)代碼分析(Perforce QAC)實(shí)現(xiàn)高效合規(guī)。
    的頭像 發(fā)表于 08-07 17:33 ?1145次閱讀
    汽車軟件團(tuán)隊(duì)必看:基于<b class='flag-5'>靜態(tài)</b>代碼<b class='flag-5'>分析</b>工具Perforce QAC的ISO 26262合規(guī)實(shí)踐

    貢獻(xiàn) OpenHarmony 庫(kù)關(guān)鍵配置

    # 貢獻(xiàn) OpenHarmony 庫(kù)關(guān)鍵配置 #自研框架#ArkUI-X#三方框架#OpenHarmony#HarmonyOS ## 創(chuàng)建第三方庫(kù) - 打開 DevEco Studio 創(chuàng)建一個(gè)
    發(fā)表于 05-28 13:46

    請(qǐng)問下,openharmony支持哪一款龍芯的開發(fā)板?有沒有開源的龍芯的openharmony源碼

    想買個(gè)2k0300的開發(fā)板學(xué)習(xí)龍芯和openharmony,愣是沒有看到提供openharmony源碼的,也沒與看到開源的代碼。gitee上,openharmony的龍芯sig倉(cāng)庫(kù)也是
    發(fā)表于 04-26 13:06

    OpenHarmony4.1系統(tǒng)WiFi藍(lán)牙打不開時(shí),教你如何排查解決問題

    ;Laval鴻蒙社區(qū)推薦并通過了開源鴻蒙XTS認(rèn)證,成功適配OpenHarmony3.2、4.0、4.1、5.0Release系統(tǒng),SDK源碼全開放!WiFi打不開缺
    的頭像 發(fā)表于 03-12 18:55 ?1030次閱讀
    <b class='flag-5'>OpenHarmony</b>4.1系統(tǒng)WiFi藍(lán)牙打不開時(shí),教你如何排查解決問題

    OpenHarmony5.0系統(tǒng)怎么去除鎖屏直接進(jìn)入界面?教你2步搞定

    ;Laval鴻蒙社區(qū)推薦并通過了開源鴻蒙XTS認(rèn)證,成功適配OpenHarmony3.2、4.0、4.1、5.0Release系統(tǒng),SDK源碼全開放!刪除Scre
    的頭像 發(fā)表于 03-12 18:51 ?1152次閱讀
    <b class='flag-5'>OpenHarmony</b>5.0系統(tǒng)怎么去除鎖屏直接進(jìn)入界面?教你2步搞定