99精品伊人亚洲|最近国产中文炮友|九草在线视频支援|AV网站大全最新|美女黄片免费观看|国产精品资源视频|精彩无码视频一区|91大神在线后入|伊人终合在线播放|久草综合久久中文

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

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

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

逐個(gè)分析鴻蒙內(nèi)核七段追蹤代碼

鴻蒙系統(tǒng)HarmonyOS ? 來(lái)源:my.oschina ? 作者:鴻蒙內(nèi)核源碼分析 ? 2021-04-28 16:51 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

本篇通過一張圖和七段代碼詳細(xì)說明系統(tǒng)調(diào)用的整個(gè)過程,代碼一捅到底,直到匯編層再也捅不下去. 先看圖,這里的模式可以理解為空間,因?yàn)槟J讲煌\(yùn)行的??臻g就不一樣.

pIYBAGCJIQ-ANIgUAACYJqdJ9_0363.png

過程解讀

在應(yīng)用層main中使用系統(tǒng)調(diào)用mq_open(posix標(biāo)準(zhǔn)接口)

mq_open被封裝在庫(kù)中,這里直接看庫(kù)里的代碼.

mq_open中調(diào)用syscall,將參數(shù)傳給寄出器R7,R0~R6

SVC 0完成用戶模式到內(nèi)核模式(SVC)的切換

_osExceptSwiHdl運(yùn)行在svc模式下.

PC寄存器直接指向_osExceptSwiHdl處取指令.

_osExceptSwiHdl是匯編代碼,先保存用戶模式現(xiàn)場(chǎng)(R0~R12寄存器),并調(diào)用OsArmA32SyscallHandle完成系統(tǒng)調(diào)用

OsArmA32SyscallHandle中通過系統(tǒng)調(diào)用號(hào)(保存在R7寄存器)查詢對(duì)應(yīng)的注冊(cè)函數(shù)SYS_mq_open

SYS_mq_open是本次系統(tǒng)調(diào)用的實(shí)現(xiàn)函數(shù),完成后return回到OsArmA32SyscallHandle

OsArmA32SyscallHandle再return回到_osExceptSwiHdl

_osExceptSwiHdl恢復(fù)用戶模式現(xiàn)場(chǎng)(R0~R12寄存器)

從內(nèi)核模式(SVC)切回到用戶模式,PC寄存器也切回用戶現(xiàn)場(chǎng).

由此完成整個(gè)系統(tǒng)調(diào)用全過程

七段追蹤代碼,逐個(gè)分析

1.應(yīng)用程序 main

int main(void)
{
	char mqname[NAMESIZE], msgrv1[BUFFER], msgrv2[BUFFER];
	const char *msgptr1 = "test message1";
	const char *msgptr2 = "test message2 with differnet length";
	mqd_t mqdes;
	int prio1 = 1, prio2 = 2;
	struct timespec ts;
	struct mq_attr attr;
	int unresolved = 0, failure = 0;
	sprintf(mqname, "/" FUNCTION "_" TEST "_%d", getpid());
	attr.mq_msgsize = BUFFER;
	attr.mq_maxmsg = BUFFER;
	mqdes = mq_open(mqname, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR, &attr);
	if (mqdes == (mqd_t)-1) {
		perror(ERROR_PREFIX "mq_open");
		unresolved = 1;
	}
	if (mq_send(mqdes, msgptr1, strlen(msgptr1), prio1) != 0) {
		perror(ERROR_PREFIX "mq_send");
		unresolved = 1;
	}
	printf("Test PASSED\n");
	return PTS_PASS;
}

2. mq_open 發(fā)起系統(tǒng)調(diào)用

mqd_t mq_open(const char *name, int flags, ...)
{
	mode_t mode = 0;
	struct mq_attr *attr = 0;
	if (*name == '/') name++;
	if (flags & O_CREAT) {
		va_list ap;
		va_start(ap, flags);
		mode = va_arg(ap, mode_t);
		attr = va_arg(ap, struct mq_attr *);
		va_end(ap);
	}
	return syscall(SYS_mq_open, name, flags, mode, attr);
}

解讀

SYS_mq_open是真正的系統(tǒng)調(diào)用函數(shù),對(duì)應(yīng)一個(gè)系統(tǒng)調(diào)用號(hào)__NR_mq_open,通過宏SYSCALL_HAND_DEF將SysMqOpen注冊(cè)到g_syscallHandle中.

static UINTPTR g_syscallHandle[SYS_CALL_NUM] = {0};	//系統(tǒng)調(diào)用入口函數(shù)注冊(cè)
static UINT8 g_syscallNArgs[(SYS_CALL_NUM + 1) / NARG_PER_BYTE] = {0};//保存系統(tǒng)調(diào)用對(duì)應(yīng)的參數(shù)數(shù)量
#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(__NR_mq_open, SysMqOpen, mqd_t, ARG_NUM_4)  

g_syscallNArgs為注冊(cè)函數(shù)的參數(shù)個(gè)數(shù),也會(huì)一塊記錄下來(lái).

四個(gè)參數(shù)為 SYS_mq_open的四個(gè)參數(shù),后續(xù)將保存在R0~R3寄存器中

3. syscall

long syscall(long n, ...)
{
	va_list ap;
	syscall_arg_t a,b,c,d,e,f;
	va_start(ap, n);
	a=va_arg(ap, syscall_arg_t);
	b=va_arg(ap, syscall_arg_t);
	c=va_arg(ap, syscall_arg_t);
	d=va_arg(ap, syscall_arg_t);
	e=va_arg(ap, syscall_arg_t);
	f=va_arg(ap, syscall_arg_t);//最多6個(gè)參數(shù)
	va_end(ap);
	return __syscall_ret(__syscall(n,a,b,c,d,e,f));
}
//4個(gè)參數(shù)的系統(tǒng)調(diào)用時(shí)底層處理
static inline long __syscall4(long n, long a, long b, long c, long d)
{
	register long a7 __asm__("a7") = n; //將系統(tǒng)調(diào)用號(hào)保存在R7寄存器
	register long a0 __asm__("a0") = a; //R0
	register long a1 __asm__("a1") = b; //R1
	register long a2 __asm__("a2") = c; //R2
	register long a3 __asm__("a3") = d; //R3
	__asm_syscall("r"(a7), "0"(a0), "r"(a1), "r"(a2), "r"(a3))
}

解讀

可變參數(shù)實(shí)現(xiàn)所有系統(tǒng)調(diào)用的參數(shù)的管理,可以看出,在鴻蒙內(nèi)核中系統(tǒng)調(diào)用的參數(shù)最多不能大于6個(gè)

R7寄存器保存了系統(tǒng)調(diào)用號(hào),R0~R5保存具體每個(gè)參數(shù)

可變參數(shù)的具體實(shí)現(xiàn)后續(xù)有其余篇幅詳細(xì)介紹,敬請(qǐng)關(guān)注.

4. svc 0

//切到SVC模式
#define __asm_syscall(...) do { \
	__asm__ __volatile__ ( "svc 0" \
	: "=r"(x0) : __VA_ARGS__ : "memory", "cc"); \
	return x0; \
	} while (0)

看不太懂的沒關(guān)系,這里我們只需要記?。合到y(tǒng)調(diào)用號(hào)存放在r7寄存器,參數(shù)存放在r0,r1,r2寄存器中,返回值最終會(huì)存放在寄存器r0中

    b   reset_vector            @開機(jī)代碼
    b   _osExceptUndefInstrHdl 	@異常處理之CPU碰到不認(rèn)識(shí)的指令
    b   _osExceptSwiHdl			@異常處理之:軟中斷
    b   _osExceptPrefetchAbortHdl	@異常處理之:取指異常
    b   _osExceptDataAbortHdl		@異常處理之:數(shù)據(jù)異常
    b   _osExceptAddrAbortHdl		@異常處理之:地址異常
    b   OsIrqHandler				@異常處理之:硬中斷
    b   _osExceptFiqHdl				@異常處理之:快中斷

解讀

svc全稱是 SuperVisor Call,完成工作模式的切換.不管之前是7個(gè)模式中的哪個(gè)模式,統(tǒng)一都切到SVC管理模式.但你也許會(huì)好奇,ARM軟中斷不是用SWI嗎,這里怎么變成了SVC了,請(qǐng)看下面一段話,是從ARM官網(wǎng)翻譯的:

SVC 超級(jí)用戶調(diào)用。 語(yǔ)法 SVC{cond} #immed 其中: cond 是一個(gè)可選的條件代碼(請(qǐng)參閱條件執(zhí)行)。 immed 是一個(gè)表達(dá)式,其取值為以下范圍內(nèi)的一個(gè)整數(shù): 在 ARM 指令中為 0 到 224–1(24 位值) 在 16 位 Thumb 指令中為 0-255(8 位值)。 用法 SVC 指令會(huì)引發(fā)一個(gè)異常。 這意味著處理器模式會(huì)更改為超級(jí)用戶模式,CPSR 會(huì)保存到超級(jí)用戶模式 SPSR,并且執(zhí)行會(huì)跳轉(zhuǎn)到 SVC 向量(請(qǐng)參閱《開發(fā)指南》中的第 6 章 處理處理器異常)。 處理器會(huì)忽略 immed。 但異常處理程序會(huì)獲取它,借以確定所請(qǐng)求的服務(wù)。 Note 作為 ARM 匯編語(yǔ)言開發(fā)成果的一部分,SWI 指令已重命名為 SVC。 在此版本的 RVCT 中,SWI 指令反匯編為 SVC,并提供注釋以指明這是以前的 SWI。 條件標(biāo)記 此指令不更改標(biāo)記。 體系結(jié)構(gòu) 此 ARM 指令可用于所有版本的 ARM 體系結(jié)構(gòu)。

而軟中斷對(duì)應(yīng)的處理函數(shù)為_osExceptSwiHdl,即PC寄存器將跳到_osExceptSwiHdl執(zhí)行

5. _osExceptSwiHdl

@ Description: Software interrupt exception handler
_osExceptSwiHdl: @軟中斷異常處理
    @保存任務(wù)上下文(TaskContext) 開始... 一定要對(duì)照TaskContext來(lái)理解
    SUB     SP, SP, #(4 * 16)	@先申請(qǐng)16個(gè)棧空間用于處理本次軟中斷
    STMIA   SP, {R0-R12}		@TaskContext.R[GEN_REGS_NUM] STMIA從左到右執(zhí)行,先放R0 .. R12
    MRS     R3, SPSR			@讀取本模式下的SPSR值
    MOV     R4, LR				@保存回跳寄存器LR

    AND     R1, R3, #CPSR_MASK_MODE                          @ Interrupted mode 獲取中斷模式
    CMP     R1, #CPSR_USER_MODE                              @ User mode	是否為用戶模式
    BNE     OsKernelSVCHandler                               @ Branch if not user mode 非用戶模式下跳轉(zhuǎn)
	@ 當(dāng)為用戶模式時(shí),獲取SP和LR寄出去值
    @ 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											 @獲取SP值,R0將作為OsArmA32SyscallHandle的參數(shù)
    STMFD   SP!, {R3}                                        @ Save the CPSR 入棧保存CPSR值 => TaskContext.regPSR
    ADD     R3, SP, #(4 * 17)                                @ Offset to pc/cpsr storage 跳到PC/CPSR存儲(chǔ)位置
    STMFD   R3!, {R4}                                        @ Save the CPSR and r15(pc) 保存LR寄存器 => TaskContext.PC
    STMFD   R3, {R13, R14}^                                  @ Save user mode r13(sp) and r14(lr) 從右向左 保存 => TaskContext.LR和SP
    SUB     SP, SP, #4										 @ => TaskContext.resved
    PUSH_FPU_REGS R1	@保存中斷模式(用戶模式模式)											
	@保存任務(wù)上下文(TaskContext) 結(jié)束
    MOV     FP, #0                                           @ Init frame pointer
    CPSIE   I	@開中斷,表明在系統(tǒng)調(diào)用期間可響應(yīng)中斷
    BLX     OsArmA32SyscallHandle	/*交給C語(yǔ)言處理系統(tǒng)調(diào)用,參數(shù)為R0,指向TaskContext的開始位置*/
    CPSID   I	@執(zhí)行后續(xù)指令前必須先關(guān)中斷
	@恢復(fù)任務(wù)上下文(TaskContext) 開始
    POP_FPU_REGS R1											 @彈出FP值給R1
    ADD     SP, SP,#4										 @ 定位到保存舊SPSR值的位置
    LDMFD   SP!, {R3}                                        @ Fetch the return SPSR 彈出舊SPSR值
    MSR     SPSR_cxsf, R3                                    @ Set the return mode SPSR 恢復(fù)該模式下的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}									 @恢復(fù)R0-R12寄存器
    LDMFD   SP, {R13, R14}^                                  @ Restore user mode R13/R14 恢復(fù)用戶模式的R13/R14寄存器
    ADD     SP, SP, #(2 * 4)								 @定位到保存舊PC值的位置
    LDMFD   SP!, {PC}^                                       @ Return to user 切回用戶模式運(yùn)行
	@恢復(fù)任務(wù)上下文(TaskContext) 結(jié)束

OsKernelSVCHandler:@主要目的是保存ExcContext中除(R0~R12)的其他寄存器
    ADD     R0, SP, #(4 * 16)	@跳轉(zhuǎn)到保存PC,LR,SP的位置,此時(shí)R0位置剛好是SP的位置
    MOV     R5, R0				@由R5記錄SP位置,因?yàn)镽0要暫時(shí)充當(dāng)SP寄存器來(lái)使用
    STMFD   R0!, {R4}                                        @ Store PC => ExcContext.PC
    STMFD   R0!, {R4}										 @ 相當(dāng)于保存了=>  ExcContext.LR
    STMFD   R0!, {R5}										 @ 相當(dāng)于保存了=>  ExcContext.SP

    STMFD   SP!, {R3}                                        @ Push task`s CPSR (i.e. exception SPSR). =>ExcContext.regPSR
    SUB     SP, SP, #(4 * 2)                                 @ user sp and lr => =>ExcContext.USP,ULR

    MOV     R0, #OS_EXCEPT_SWI                               @ Set exception ID to OS_EXCEPT_SWI.
															 @ 設(shè)置異常ID為軟中斷
    B       _osExceptionSwi                                  @ Branch to global exception handler.
															 @ 跳到全局異常處理
    解讀

運(yùn)行到此處,已經(jīng)切到SVC的棧運(yùn)行,所以先保存上一個(gè)模式的現(xiàn)場(chǎng)

獲取中斷模式,軟中斷的來(lái)源可不一定是用戶模式,完全有可能是SVC本身,比如系統(tǒng)調(diào)用中又發(fā)生系統(tǒng)調(diào)用.就變成了從SVC模式切到SVC的模式

MOV R0, SP;sp將作為參數(shù)傳遞給OsArmA32SyscallHandle

調(diào)用OsArmA32SyscallHandle這是所有系統(tǒng)調(diào)用的統(tǒng)一入口

注意看OsArmA32SyscallHandle的參數(shù)UINT32 *regs

6. OsArmA32SyscallHandle

/* The SYSCALL ID is in R7 on entry.  Parameters follow in R0..R6 */
/******************************************************************
由匯編調(diào)用,見于 los_hw_exc.s    / BLX    OsArmA32SyscallHandle
SYSCALL是產(chǎn)生系統(tǒng)調(diào)用時(shí)觸發(fā)的信號(hào),R7寄存器存放具體的系統(tǒng)調(diào)用ID,也叫系統(tǒng)調(diào)用號(hào)
regs:參數(shù)就是所有寄存器
注意:本函數(shù)在用戶態(tài)和內(nèi)核態(tài)下都可能被調(diào)用到
//MOV     R0, SP @獲取SP值,R0將作為OsArmA32SyscallHandle的參數(shù)
******************************************************************/
LITE_OS_SEC_TEXT UINT32 *OsArmA32SyscallHandle(UINT32 *regs)
{
    UINT32 ret;
    UINT8 nArgs;
    UINTPTR handle;
    UINT32 cmd = regs[REG_R7];//C7寄存器記錄了觸發(fā)了具體哪個(gè)系統(tǒng)調(diào)用
	
    if (cmd >= SYS_CALL_NUM) {//系統(tǒng)調(diào)用的總數(shù)
        PRINT_ERR("Syscall ID: error %d !!!\n", cmd);
        return regs;
    }

    if (cmd == __NR_sigreturn) {//收到 __NR_sigreturn 信號(hào)
        OsRestorSignalContext(regs);//恢復(fù)信號(hào)上下文
        return regs;
    }

    handle = g_syscallHandle[cmd];//拿到系統(tǒng)調(diào)用的注冊(cè)函數(shù),類似 SysRead 
    nArgs = g_syscallNArgs[cmd / NARG_PER_BYTE]; /* 4bit per nargs */
    nArgs = (cmd & 1) ? (nArgs >> NARG_BITS) : (nArgs & NARG_MASK);//獲取參數(shù)個(gè)數(shù)
    if ((handle == 0) || (nArgs > ARG_NUM_7)) {//系統(tǒng)調(diào)用必須有參數(shù)且參數(shù)不能大于8個(gè)
        PRINT_ERR("Unsupport syscall ID: %d nArgs: %d\n", cmd, nArgs);
        regs[REG_R0] = -ENOSYS;
        return regs;
    }
	//regs[0-6] 記錄系統(tǒng)調(diào)用的參數(shù),這也是由R7寄存器保存系統(tǒng)調(diào)用號(hào)的原因
    switch (nArgs) {//參數(shù)的個(gè)數(shù) 
        case ARG_NUM_0:
        case ARG_NUM_1:
            ret = (*(SyscallFun1)handle)(regs[REG_R0]);//執(zhí)行系統(tǒng)調(diào)用,類似 SysUnlink(pathname);
            break;
        case ARG_NUM_2://如何是兩個(gè)參數(shù)的系統(tǒng)調(diào)用,這里傳三個(gè)參數(shù)也沒有問題,因被調(diào)用函數(shù)不會(huì)去取用R2值
        case ARG_NUM_3:
            ret = (*(SyscallFun3)handle)(regs[REG_R0], regs[REG_R1], regs[REG_R2]);//類似 SysExecve(fileName, argv, envp);
            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:	//7個(gè)參數(shù)的情況
            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保存系統(tǒng)調(diào)用返回值
    OsSaveSignalContext(regs);//保存信號(hào)上下文現(xiàn)場(chǎng)

    /* 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;//返回寄存器的值
}

解讀

參數(shù)是regs對(duì)應(yīng)的就是R0~Rn

R7保存的是系統(tǒng)調(diào)用號(hào),R0~R3保存的是SysMqOpen的四個(gè)參數(shù)

g_syscallHandle[cmd]就能查詢到SYSCALL_HAND_DEF(__NR_mq_open, SysMqOpen, mqd_t, ARG_NUM_4)注冊(cè)時(shí)對(duì)應(yīng)的SysMqOpen函數(shù)

*(SyscallFun5)handle此時(shí)就是SysMqOpen

注意看 SysMqOpen 的參數(shù)是最開始的main函數(shù)中的mqdes = mq_open(mqname, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR, &attr);由此完成了真正系統(tǒng)調(diào)用的過程

7. SysMqOpen

mqd_t SysMqOpen(const char *mqName, int openFlag, mode_t mode, struct mq_attr *attr)
{
    mqd_t ret;
    int retValue;
    char kMqName[PATH_MAX + 1] = { 0 };

    retValue = LOS_StrncpyFromUser(kMqName, mqName, PATH_MAX);
    if (retValue < 0) {
        return retValue;
    }
    ret = mq_open(kMqName, openFlag, mode, attr);//一個(gè)消息隊(duì)列可以有多個(gè)進(jìn)程向它讀寫消息
    if (ret == -1) {
        return (mqd_t)-get_errno();
    }
    return ret;
}

解讀

此處的mq_open和main函數(shù)的mq_open其實(shí)是兩個(gè)函數(shù)體實(shí)現(xiàn).一個(gè)是給應(yīng)用層的調(diào)用,一個(gè)是內(nèi)核層使用,只是名字一樣而已.

SysMqOpen是返回到OsArmA32SyscallHandleregs[REG_R0] = ret;

OsArmA32SyscallHandle再返回到_osExceptSwiHdl

_osExceptSwiHdl后面的代碼是用于恢復(fù)用戶模式現(xiàn)場(chǎng)和SPSR,PC等寄存器.

以上為鴻蒙系統(tǒng)調(diào)用的整個(gè)過程.

編輯:hfy

聲明:本文內(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)注

    31

    文章

    5433

    瀏覽量

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

    關(guān)注

    183

    文章

    2642

    瀏覽量

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

掃碼添加小助手

加入工程師交流群

    評(píng)論

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

    鴻蒙5開發(fā)寶藏案例分享---Grid性能優(yōu)化案例

    注意到。今天我就帶大家拆解這個(gè)案例,加上詳細(xì)講解和代碼分析,幫你輕松提升應(yīng)用流暢度! ?問題場(chǎng)景:為什么Grid會(huì)卡? 當(dāng)Grid布局需要實(shí)現(xiàn) 不規(guī)則網(wǎng)格 (比如合并單元格)時(shí),我們常用<
    發(fā)表于 06-12 17:47

    鴻蒙5開發(fā)寶藏案例分享---分析幀率問題

    鴻蒙性能優(yōu)化寶藏:幀率問題實(shí)戰(zhàn)案例解析 嘿,各位鴻蒙開發(fā)者! 今天分享一個(gè)開發(fā)中的大發(fā)現(xiàn)——鴻蒙官方文檔里藏著一堆超實(shí)用的性能優(yōu)化案例!這些案例不僅解決了常見的丟幀卡頓問題,還附帶了詳細(xì)的分析
    發(fā)表于 06-12 17:07

    鴻蒙5開發(fā)寶藏案例分享---點(diǎn)擊完成時(shí)延分析

    ... profiler.stopTrace(\'page_switch\'); 幀率分析:揪出超時(shí)渲染幀(紅色警告幀) 調(diào)用棧追蹤:ArkTS/Native雙視角分析 支持冷啟動(dòng)/卡頓/內(nèi)存等場(chǎng)景深度優(yōu)化
    發(fā)表于 06-12 17:03

    DevEco Studio構(gòu)建分析工具Build Analyzer 為原生鴻蒙應(yīng)用開發(fā)提速

    不同構(gòu)建階段的性能差異,進(jìn)一步優(yōu)化構(gòu)建流程。 Build Analyzer作為一款強(qiáng)大的構(gòu)建分析工具,為原生鴻蒙應(yīng)用開發(fā)者提供了從任務(wù)追蹤到性能優(yōu)化的全方位支持。通過其細(xì)粒度的分析和直
    發(fā)表于 02-17 18:06

    鴻蒙Flutter實(shí)戰(zhàn):14-現(xiàn)有Flutter 項(xiàng)目支持鴻蒙 II

    引言 在之前的文章鴻蒙Flutter實(shí)戰(zhàn):09-現(xiàn)有Flutter項(xiàng)目支持鴻蒙中,介紹了如何改造項(xiàng)目,適配鴻蒙平臺(tái)。 文中講述了整體的理念和思路,本文更進(jìn)一步,結(jié)合可實(shí)操的項(xiàng)目代碼,詳
    發(fā)表于 12-26 14:59

    要求為為供電電壓的范圍在2.7V-5V之間,用于驅(qū)動(dòng)五位七段共陰極數(shù)碼管,求推薦一款數(shù)碼管驅(qū)動(dòng)芯片?

    推薦一款TI的數(shù)碼管驅(qū)動(dòng)芯片,要求為為供電電壓的范圍在2.7V-5V之間,用于驅(qū)動(dòng)五位七段共陰極數(shù)碼管,最好能給出建議原理圖。謝謝!
    發(fā)表于 12-16 08:35

    其利天下技術(shù)·電機(jī)控制SVPWM七段式算法·無(wú)刷電機(jī)驅(qū)動(dòng)方案

    一般控制三相電機(jī)的控制技術(shù)采用SVPWM(SpaceVectorPulseWidthModulation)算法。它對(duì)于電機(jī)控制可以提供更高的效率和更低的噪聲。SVPWM控制算法可以分為七段式和五
    的頭像 發(fā)表于 12-11 10:28 ?3134次閱讀
    其利天下技術(shù)·電機(jī)控制SVPWM<b class='flag-5'>七段</b>式算法·無(wú)刷電機(jī)驅(qū)動(dòng)方案

    矩陣4x4個(gè)按鍵,如何把識(shí)別結(jié)果按編號(hào)01-16(十進(jìn)制)顯示在兩個(gè)七段數(shù)碼管上?

    矩陣4x4個(gè)按鍵,并把識(shí)別結(jié)果按編號(hào)01-16(十進(jìn)制)顯示在兩個(gè)七段數(shù)碼管上,按鍵按下時(shí)顯示,不按時(shí)消失編號(hào)消失。 2.為了更加實(shí)用,要求加上去抖動(dòng)電路模塊
    發(fā)表于 10-31 20:43

    鴻蒙系統(tǒng)生態(tài)設(shè)備突破10億臺(tái) 超過15000個(gè)鴻蒙原生應(yīng)用和元服務(wù)上架

    從操作系統(tǒng)內(nèi)核、文件系統(tǒng),到編程語(yǔ)言、人工智能框架和大模型等全部實(shí)現(xiàn)自研;放棄了傳統(tǒng)的Linux內(nèi)核以及安卓開源代碼項(xiàng)目AOSP,僅支持鴻蒙內(nèi)核
    的頭像 發(fā)表于 10-23 16:43 ?1970次閱讀

    鴻蒙Flutter實(shí)戰(zhàn):08-如何調(diào)試代碼

    。 方案二 適應(yīng)DecEco運(yùn)行鴻蒙項(xiàng)目,注意需要打開的是ohos鴻蒙目錄代碼,待IDE分析結(jié)束后,點(diǎn)擊運(yùn)行。 當(dāng)app在鴻蒙設(shè)備上啟動(dòng)成功
    發(fā)表于 10-23 16:29

    數(shù)碼管的使用方法和接線步驟

    數(shù)碼管的基本單元是發(fā)光二極管(LED),通過控制不同LED的亮滅來(lái)顯示數(shù)字和字符。根據(jù)段數(shù),數(shù)碼管可分為七段和八,其中八數(shù)碼管比七段多一個(gè)小數(shù)點(diǎn)顯示。按發(fā)光二極管單元的連接方式,數(shù)
    的頭像 發(fā)表于 08-29 18:22 ?7084次閱讀

    數(shù)碼管顯示屏在仿真軟件中叫什么

    數(shù)碼管顯示屏,又稱為七段顯示器或七段LED顯示器,是一種常見的數(shù)字顯示設(shè)備,廣泛應(yīng)用于電子設(shè)備中,如計(jì)算器、電子鐘、數(shù)字儀表等。在仿真軟件中,數(shù)碼管顯示屏通常被稱為“7-segment
    的頭像 發(fā)表于 08-28 17:08 ?2972次閱讀

    數(shù)碼管在仿真軟件里面怎么找

    數(shù)碼管,又稱為七段顯示器或七段顯示器,是一種常用的數(shù)字顯示設(shè)備,廣泛應(yīng)用于電子設(shè)備中,如電子鐘、計(jì)算器、數(shù)字儀表等。在仿真軟件中,數(shù)碼管的查找和使用是一個(gè)重要的技能。 一、數(shù)碼管的基本概念 數(shù)碼管
    的頭像 發(fā)表于 08-28 17:06 ?3610次閱讀

    總結(jié)七段數(shù)碼管的分類和工作原理

    七段數(shù)碼管是一種常見的電子顯示設(shè)備,廣泛應(yīng)用于各種電子設(shè)備中,如計(jì)算器、電子鐘、數(shù)字儀表等。 一、七段數(shù)碼管的分類 按顯示方式分類 七段數(shù)碼管按照顯示方式可以分為靜態(tài)顯示和動(dòng)態(tài)顯示兩種類型。 (1
    的頭像 發(fā)表于 08-28 16:27 ?3950次閱讀

    七段數(shù)碼管怎么判斷共陰共陽(yáng)

    七段數(shù)碼管是一種常見的顯示設(shè)備,用于顯示數(shù)字和字母。它由個(gè)發(fā)光二極管(LED)組成,每個(gè)LED可以獨(dú)立控制,以形成不同的數(shù)字和字母。七段數(shù)碼管有兩種類型:共陰和共陽(yáng)。這兩種類型的數(shù)碼管在電路連接
    的頭像 發(fā)表于 08-28 16:17 ?3673次閱讀