UCOSII系统移植详解「建议收藏」

UCOSII系统移植详解「建议收藏」一,移植UCOSII操作系统的CPU前提条件1,处理器的C编译器能产生可重入型的代码,如果不行的话,那么就不能在任务之间随意的切换,因为当你切换到别的任务的时候,该任务在这个函数的数据就会被破坏。2,处理器CPU支持中断,并能产生定时中断3,用C语言就可以开关中断,进行任务切换4,处理器CPU能够支持一定数量的数据存储硬件堆栈,也就是栈5,处理器有将堆栈指针以及其他的CPU的寄存器的内容读出,并存储到堆栈或者内存中去的指令。任务切换的时候,需要将当前的CPU指针保存到刚刚执行的任务当中。

大家好,又见面了,我是你们的朋友全栈君。

一,移植UCOSII操作系统的CPU前提条件

1,处理器的C编译器能产生可重入型的代码,如果不行的话,那么就不能在任务之间随意的切换,因为当你切换到别的任务的时候,该任务在这个函数的数据就会被破坏。

2,处理器CPU支持中断,并能产生定时中断

3,用C语言就可以开关中断,进行任务切换

4,处理器CPU能够支持一定数量的数据存储硬件堆栈,也就是栈

5,处理器有将堆栈指针以及其他的CPU的寄存器的内容读出,并存储到堆栈或者内存中去的指令。任务切换的时候,需要将当前的CPU指针保存到刚刚执行的任务当中。然后切换到优先级更高的任务当中。

二,UCOSII实际移植的文件:

UCOSII的移植实例就是要求用户编写4个简单的汇编语言函数,如果编译器支持插入行汇编代码就可以将所有的与处理器相关的代码放置到OS_CPU_C.c里面种,就不需要适用汇编文件。
(1)OSStartHighRdy(); //使得最高优先级的任务运行的函数

OSStart()函数调用OSStartHighRdy()来使得就绪太任务中最高优先级的任务开始运行

void OSStartHighRdy()
{
    调用用户定义的OSTaskSwHook();
    OSRunning = TRUE;
    //得到将要恢复运行的任务的堆栈指针。
    stack pointer = OSTcbHighRdy->OSTCBStkPtr;
    //从新的堆栈中恢复处理器的所有的寄存器,就是把刚刚切换的堆栈保存到别的地方当中
    //执行中断返回,然后跳转PC指针到别的地方中去。
}

(2)OSCtxSw(); 任务级的切换是通过执行软中断指令,或者依据处理器的不同,执行TPAP陷阱指令执行的。中断服务子程序,陷阱或者异常处理的向量的地址必须指向OSCtxSw();

//任务的切换的函数:
void OSCtxSw()
{
    保存处理器寄存器;
    在当前的任务的任务控制块中保存当前任务的堆栈指针;
    OSTCBCur->OSTCBStkPtr = stack pointer;
    OSTaskSwHook();
    OSTCBCur = OSTCBHighRdy;
    OSPrioCur = OSPrioHighRdy;
 
    //得到将要重新开始运行的任务的堆栈指针:
    stack pointer = OSTCBHighRdy->OSTCBstkPtr;
    //从新的任务堆栈中恢复所有的寄存器的值;
    //执行中断返回的指令。
}

(3)OSIntCtxSw();

void OSTickISR(void)
{
    //保存处理器的寄存器
    //调用OSIntEnter或者直接给OSIntNesting加1
    if(OSIntNesting ==1)
    {
        OSTCBCur->OSTCBStkPtr = Stack Pointer;
    }
    //给产生中断的设备清中断
    //重新允许中断
    OSTimeTick();   //硬件的产生中断的原理
    OSIntExit();    //中断退出
    //恢复处理器寄存器
    //执行中断返回指令
}

(4)OSTickISR();

void OSintCtxSw(void)
{
    //调整堆栈指针
    OSintExit();
    OSINTCtxSw();
}

移植UCOSII,大部分的代码是基于底层进行编写的,不需要进行移植。移植UCOSII操作系统的时候需要移植的几个文件:INCLUDES.h是一个主头文件,出现在每个.c 文件的第一行。下面讲移植UCOSII操作系统的时候需要实际移植的三个关键文件:

1,OS_CPU.h

/*        数据类型       */
typedef unsigned char BOOLEAN;
typedef unsigned int OS_STK;   //堆栈入口的宽度为16位
typedef unsigned short OS_CPU_SR; //定义CPU状态寄存器的宽度为16位
/*         与处理器有关的代码    */
#define OS_ENTER_CRITICAL()     //进入临界区的代码
#define OS_EXIT_CRITICAL()      //跳出临界区的代码
 
#define OS_STK_GHOWTH   1  定义堆栈的方向:1=向下递减,0=向上递增
#define OS_TASK_SW()   //定义软件任务切换的函数。

2,OS_CPU_C.c (最关键的移植文件):要求用户编写10个简单的C函数:

OSTaskStkInit();OSTaskCreateHook();OSTaskDelHook();OSTaskSwHook();OSTaskIdleHook();
OSTaskStatHook();OSTimeTickHook();OSInitHookBegin();OSInitHookend();OSTCBInitHook();
(1)OSTaskStkInit()的示例代码

OS_STK * OSTaskStkInit(void (*task)(void * pd),
                        void * pada,
                        OS_STK  *ptos,
                        INT16U  opt);
{
    pada = pada;
    模拟ISR向量;
    //按照预先设计的寄存器值初始化堆栈结构;
    //不断的在堆栈中相应的位置填入你要传递的参数
    //返回栈顶指针给调用该函数的函数
    //在这里假定堆栈是从上往下递减的,下面讨论同样适用于以相反方向从下到上递增的堆栈结构。
}

(2)OSTaskCreateHook():
添加任务的时候OS_TCBInit()函数都会调用OSTaskCreateHook()函数,该函数允许扩展UCOSII的功能,当UCOSII设置完任务控制块OS_TCB初始化的绝大部分的工作后,但是在任务控制块被链接到相应的任务链中之前,以及在该任务就绪运行之前,UCOSII会调用OSTaskCreateHook(),该函数被调用的时候中断是打开的。

(3)OSTaskIdleHook()
很多微处理器都允许执行相应的指令,将CPU置于低功耗模式。而当接收到中断信号的时候,CPU就会退出低功耗模式,OSTaskIdle()函数可调用OSTaskIdleHook()函数,实现CPU的这种低功耗的模式:

void OS_TaskIdle(void *pdata)
{
    pdata = pdata;
    for(;;)
    {
        OS_ENTER_CRITICAL();
        OSIdleCtr++;
        OS_EXIT_CRITICAL();
        OSTaskIdleHook();
    }
}
void OSTaskIdleHook(void)
{
    asm("STOP");
    //收到中断并完成中断服务。
}

三,UCOSII三个关键文件:

1,OS_CPU.h

typedef unsigned char BOOLEAN;   //声明一个布尔变量
typedef unsigned char INT8U;     //无符号的8位整型变量
typedef signed   char INT8S;     //有符号的8位整型变量
 
//关键移植部分:
typedef INT32U    OS_STK;    //堆栈是32位宽度
 
typedef INT32U    OS_CPU_SR; //定义SR的寄存器为32位
 
//进入临界区函数,此处是通过汇编实现的
#define OS_ENTER_CRITICAL()  (cpu_sr = OSCPUSaveSR())
#define OS_EXIT_CRITICAL()   (OSCPURestoreSR(cpu_sr))
 
#define OS_STK_GROWTH   1  //堆栈的生长的方向是从高地址到低地址
 
//关键的任务切换的函数
#define  OS_TASK_SW()  OSCtxSw()

2,OS_CPU_C.C

#include "ucos_ii.h"
 
OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt)
{
    OS_STK  *stk;
    opt = opt;
    stk = ptos;      //定义一个局部变量
    *(stk) = (OS_STK)task;   //Entry Point
    *(--stk) = (INT32U)0;    //LR
    *(--stk) = (INT32U)0;    //R12
    *(--stk) = (INT32U)0;    //R11
    *(--stk) = (INT32U)0;    //R10
    *(--stk) = (INT32U)0;    //R9
    *(--stk) = (INT32U)0;    //R8
    *(--stk) = (INT32U)0;    //R7
    *(--stk) = (INT32U)0;    //R6
    *(--stk) = (INT32U)0;    //R5
    *(--stk) = (INT32U)0;    //R4
    *(--stk) = (INT32U)0;    //R3
    *(--stk) = (INT32U)0;    //R2
    *(--stk) = (INT32U)0;    //R1
    *(--stk) = (INT32U)p_arg;    //R0
    *(--stk) = (INT32U)0x000000131L;    //CPSR
    /* 这个就是配置CPU的堆栈的寄存器,SVC的用户模式,
        同时的打开普通中断和快速中断
    */
 
    return (stk);
}
 
因为其他的函数不是必须要移植的,所以这里就不进行移植了。
此段代码的意义是初始化堆栈,堆栈是用OS_STK定义的数组。
进行堆栈操作时注意S3C2440是满减栈,此代码后面会有所讲解。

3,OS_CPU_A.s:实现核心的任务切换需要的基本的函数

SRCPND       EQU  0x4a000000    ; 源中断的寄存器
INTPND       EQU  0x4a000010    ; 中断挂起寄存器:IRQ可以读取此寄存器决定服务32个中断源的哪个源
 
rEINTPEND   EQU  0x560000a8
INTOFFSET   EQU  0x4a000014
 
 
USERMODE    EQU     0x10    //用户模式
FIQMODE     EQU     0x11    //快速中断模式
IRQMODE     EQU     0x12    //中断模式
SVCMODE     EQU     0x13    //普通模式
ABORTMODE   EQU     0x17    //异常模式
UNDEFMODE   EQU     0x1b
MODEMASK    EQU     0x1f
NOINT       EQU     0xc0
 
;*********************************************************************************************************
;                                    EXPORT and EXTERNAL REFERENCES
;*********************************************************************************************************/
    IMPORT  OSRunning
    IMPORT  OSTCBCur
    IMPORT  OSTCBHighRdy
    IMPORT  OSPrioCur
    IMPORT  OSPrioHighRdy
    IMPORT  OSIntNesting
 
 
    IMPORT  OSIntEnter
    IMPORT  OSIntExit
    IMPORT  OSTaskSwHook
    IMPORT  OSTimeTick
 
    IMPORT  EINT0_Handle
 
 
    EXPORT  OSStartHighRdy
    EXPORT  OSCtxSw
    EXPORT  OSTickISR    
    EXPORT  OSIntCtxSw
 
    EXPORT  OSCPUSaveSR
    EXPORT  OSCPURestoreSR
 
    EXPORT  OS_CPU_IRQ_ISR
 
                PRESERVE8
    AREA UCOS_ARM, CODE, READONLY
 
;*********************************************************************************************************
;                                          START MULTITASKING
;                                       void OSStartHighRdy(void)
;
; The stack frame is assumed to look as follows:
;
;                                Entry Point(Task Name)                (High memory)
;                               LR(R14)
;                               R12
;                               R11
;                               R10
;                               R9
;                               R8
;                               R7
;                               R6
;                               R5
;                               R4
;                               R3
;                               R2
;                               R1
;                               R0 : argument
; OSTCBHighRdy->OSTCBStkPtr --> CPSR                                (Low memory)
;
; Note : OSStartHighRdy() MUST:
;           a) Call OSTaskSwHook() then,
;           b) Set OSRunning to TRUE,
;           c) Switch to the highest priority task.
;********************************************************************************************************** */
OSStartHighRdy  
    ;----------------------------------------------------------------------------------    
    ; OSRunning = TRUE;
    ;----------------------------------------------------------------------------------    
 
    MSR     CPSR_cxsf,#(SVCMODE :OR: NOINT)     ;Switch to SVC mode with IRQ&FIQ disable
 
    BL        OSTaskSwHook            ;Call user define Task switch hook
 
    LDR        R0, =OSRunning          ; OSRunning =TRUE
    MOV        R1, #1
    STRB     R1, [R0]
 
    ;----------------------------------------------------------------------------------        
    ;         SP = OSTCBHighRdy->OSTCBStkPtr;
    ;----------------------------------------------------------------------------------    
    LDR     R0, =OSTCBHighRdy
    LDR     R0, [R0]         
    LDR     SP, [R0]         
 
    ;----------------------------------------------------------------------------------        
    ; Prepare to return to proper mode
    ;----------------------------------------------------------------------------------    
    LDMFD     SP!, {R0}  
    MSR     SPSR_cxsf, R0
    LDMFD     SP!, {R0-R12, LR, PC}^
 
 
;**********************************************************************************************************
;                                PERFORM A CONTEXT SWITCH (From task level)
;                                           void OSCtxSw(void)
;
; Note(s):        1) Upon entry: 
;                    OSTCBCur      points to the OS_TCB of the task to suspend
;                    OSTCBHighRdy  points to the OS_TCB of the task to resume
;
;                 2) The stack frame of the task to suspend looks as follows:
;                                                   
;                                                   PC                    (High memory)
;                                                      LR(R14)                    
;                                                   R12
;                                                       R11
;                                                   R10
;                                                       R9
;                                                   R8
;                                                   R7
;                                                   R6
;                                                   R5
;                                                   R4
;                                                   R3
;                                                   R2
;                                                   R1
;                                                   R0
;                         OSTCBCur->OSTCBStkPtr ----> CPSR                    (Low memory)
;
;
;                 3) The stack frame of the task to resume looks as follows:
;
;                                                        PC                (High memory)
;                                                   LR(R14)    
;                                                       R12
;                                                   R11
;                                                   R10
;                                                       R9
;                                                   R8
;                                                   R7
;                                                       R6
;                                                   R5
;                                                   R4
;                                                   R3
;                                                   R2
;                                                   R1
;                                                       R0
;                     OSTCBHighRdy->OSTCBStkPtr ---->    CPSR                    (Low memory)
;*********************************************************************************************************/
OSCtxSw
 
    STMFD    SP!, {LR}           ;PC
    STMFD    SP!, {R0-R12, LR}   ;R0-R12 LR
    MRS        R0,  CPSR       ;Push CPSR
    STMFD    SP!, {R0}    
 
    ;----------------------------------------------------------------------------------
    ;         OSTCBCur->OSTCBStkPtr = SP
    ;----------------------------------------------------------------------------------        
    LDR        R0, =OSTCBCur
    LDR        R0, [R0]
    STR        SP, [R0]
 
    ;----------------------------------------------------------------------------------        
    ; OSTaskSwHook();
    ;---------------------------------------------------------------------------------    
    BL         OSTaskSwHook
 
    ;----------------------------------------------------------------------------------            
    ; OSTCBCur = OSTCBHighRdy;
    ;----------------------------------------------------------------------------------        
    LDR        R0, =OSTCBHighRdy
    LDR        R1, =OSTCBCur
    LDR        R0, [R0]
    STR        R0, [R1]
 
    ;----------------------------------------------------------------------------------        
    ; OSPrioCur = OSPrioHighRdy;
    ;----------------------------------------------------------------------------------        
    LDR        R0, =OSPrioHighRdy
    LDR        R1, =OSPrioCur
    LDRB    R0, [R0]
    STRB    R0, [R1]
 
    ;----------------------------------------------------------------------------------        
    ;  SP = OSTCBHighRdy->OSTCBStkPtr;
    ;----------------------------------------------------------------------------------        
    LDR        R0, =OSTCBHighRdy
    LDR        R0, [R0]
    LDR        SP, [R0]
 
    ;----------------------------------------------------------------------------------    
    ;Restore New task context
    ;----------------------------------------------------------------------------------    
    LDMFD     SP!, {R0}        ;POP CPSR
    MSR     SPSR_cxsf, R0
    LDMFD     SP!, {R0-R12, LR, PC}^    
 
 
;*********************************************************************************************************
;                                            TICK HANDLER
;
; Description:  
;     This handles all the Timer0(INT_TIMER0) interrupt which is used to generate the uC/OS-II tick.
;*********************************************************************************************************/
 
OSTickISR
    MOV     R5,LR    
    MOV     R1, #1
    MOV        R1, R1, LSL #10        ; Timer0 Source Pending Reg.
    LDR     R0, =SRCPND
    LDR     R2, [R0]
    ORR     R1, R1,R2
    STR     R1, [R0]
 
    LDR        R0, =INTPND
    LDR        R1, [R0]
    STR        R1, [R0]        
 
    ;----------------------------------------------------------------------------------        
    ; OSTimeTick();
    ;----------------------------------------------------------------------------------    
    BL        OSTimeTick
 
 
    MOV    PC, R5                ; Return     
 
;*********************************************************************************************************
;                                PERFORM A CONTEXT SWITCH (From an ISR)
;                                        void OSIntCtxSw(void)
;
; Description: 1) This code performs a context switch if a higher priority task has been made ready-to-run
;                   during an ISR.
;
;                 2) The stack frame of the task to suspend looks as follows:
;
;                                                      PC                    (High memory)
;                                                   LR(R14)
;                                                   R12
;                                                       R11
;                                                   R10
;                                                       R9
;                                                   R8
;                                                   R7
;                                                   R6
;                                                   R5
;                                                   R4
;                                                   R3
;                                                   R2
;                                                   R1
;                                                   R0
;                                                   
;                         OSTCBCur->OSTCBStkPtr ----> CPSR                    (Low memory)
;
;
;                 3) The stack frame of the task to resume looks as follows:
;
;                                                        PC                    (High memory)
;                                                   LR(R14)    
;                                                       R12
;                                                   R11
;                                                   R10
;                                                       R9
;                                                   R8
;                                                   R7
;                                                       R6
;                                                   R5
;                                                   R4
;                                                   R3
;                                                   R2
;                                                   R1
;                                                       R0
;                     OSTCBHighRdy->OSTCBStkPtr ---->    CPSR                    (Low memory)
;*********************************************************************************************************/
OSIntCtxSw
    ;----------------------------------------------------------------------------------        
    ; Call OSTaskSwHook();
    ;----------------------------------------------------------------------------------    
    BL         OSTaskSwHook
 
    ;----------------------------------------------------------------------------------            
    ; OSTCBCur = OSTCBHighRdy;
    ;----------------------------------------------------------------------------------        
    LDR        R0, =OSTCBHighRdy
    LDR        R1, =OSTCBCur
    LDR        R0, [R0]
    STR        R0, [R1]
 
    ;----------------------------------------------------------------------------------        
    ; OSPrioCur = OSPrioHighRdy;
    ;----------------------------------------------------------------------------------        
    LDR        R0, =OSPrioHighRdy
    LDR        R1, =OSPrioCur
    LDRB    R0, [R0]
    STRB    R0, [R1]
 
    ;----------------------------------------------------------------------------------        
    ;         SP = OSTCBHighRdy->OSTCBStkPtr;
    ;----------------------------------------------------------------------------------        
    LDR        R0, =OSTCBHighRdy
    LDR        R0, [R0]
    LDR        SP, [R0]
 
    ;----------------------------------------------------------------------------------    
    ; Restore New Task context
    ;----------------------------------------------------------------------------------    
    LDMFD     SP!, {R0}              ;POP CPSR
    MSR     SPSR_cxsf, R0
    LDMFD     SP!, {R0-R12, LR, PC}^    
 
 
 
OS_CPU_IRQ_ISR     
 
    STMFD   SP!, {R1-R3}            ; We will use R1-R3 as temporary registers
;----------------------------------------------------------------------------
;   R1--SP
;    R2--PC 
;   R3--SPSR
;------------------------------------------------------------------------
    MOV     R1, SP
    ADD     SP, SP, #12             ;Adjust IRQ stack pointer
    SUB     R2, LR, #4              ;Adjust PC for return address to task
 
    MRS     R3, SPSR                ; Copy SPSR (Task CPSR)
    MSR     CPSR_cxsf, #SVCMODE:OR:NOINT   ;Change to SVC mode
 
                                    ; SAVE TASK''S CONTEXT ONTO OLD TASK''S STACK
 
    STMFD   SP!, {R2}                ; Push task''s PC 
    STMFD   SP!, {R4-R12, LR}        ; Push task''s LR,R12-R4
 
    LDMFD   R1!, {R4-R6}            ; Load Task''s R1-R3 from IRQ stack 
    STMFD   SP!, {R4-R6}            ; Push Task''s R1-R3 to SVC stack
    STMFD   SP!, {R0}                ; Push Task''s R0 to SVC stack
 
    STMFD   SP!, {R3}                ; Push task''s CPSR
 
    LDR     R0,=OSIntNesting        ;OSIntNesting++
    LDRB    R1,[R0]
    ADD     R1,R1,#1
    STRB    R1,[R0] 
 
    CMP     R1,#1                   ;if(OSIntNesting==1){
    BNE     %F1
 
    LDR     R4,=OSTCBCur            ;OSTCBHighRdy->OSTCBStkPtr=SP;
    LDR     R5,[R4]
    STR     SP,[R5]                 ;}
 
1
    MSR    CPSR_c,#IRQMODE:OR:NOINT    ;Change to IRQ mode to use IRQ stack to handle interrupt
 
    LDR     R0, =INTOFFSET
    LDR     R0, [R0]
 
    LDR     R1, IRQIsrVect
    MOV     LR, PC                          ; Save LR befor jump to the C function we need return back
    LDR     PC, [R1, R0, LSL #2]            ; Call OS_CPU_IRQ_ISR_handler();   
 
    MSR        CPSR_c,#SVCMODE:OR:NOINT   ;Change to SVC mode
    BL         OSIntExit           ;Call OSIntExit
 
    LDMFD   SP!,{R4}               ;POP the task''s CPSR 
    MSR        SPSR_cxsf,R4
    LDMFD   SP!,{R0-R12,LR,PC}^       ;POP new Task''s context
 
IRQIsrVect DCD EINT0_Handle    
 
;*********************************************************************************************************
;                                   CRITICAL SECTION METHOD 3 FUNCTIONS
;
; Description: Disable/Enable interrupts by preserving the state of interrupts.  Generally speaking you
;              would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then
;              disable interrupts.  'cpu_sr' is allocated in all of uC/OS-II''s functions that need to 
;              disable interrupts.  You would restore the interrupt disable state by copying back 'cpu_sr'
;              into the CPU''s status register.
;
; Prototypes : OS_CPU_SR  OSCPUSaveSR(void);
;              void       OSCPURestoreSR(OS_CPU_SR cpu_sr);
;
;
; Note(s)    : 1) These functions are used in general like this:
;
;                 void Task (void *p_arg)
;                 {
;                 #if OS_CRITICAL_METHOD == 3          /* Allocate storage for CPU status register */
;                     OS_CPU_SR  cpu_sr;
;                 #endif
;
;                          :
;                          :
;                     OS_ENTER_CRITICAL();             /* cpu_sr = OSCPUSaveSR();                */
;                          :
;                          :
;                     OS_EXIT_CRITICAL();              /* OSCPURestoreSR(cpu_sr);                */
;                          :
;                          :
;                 }
;
;              2) OSCPUSaveSR() is implemented as recommended by Atmel''s application note:
;
;                    "Disabling Interrupts at Processor Level"
;*********************************************************************************************************
OSCPUSaveSR
    MRS     R0, CPSR                ; Set IRQ and FIQ bits in CPSR to disable all interrupts
    ORR     R1, R0, #0xC0
    MSR     CPSR_c, R1
    MRS     R1, CPSR                ; Confirm that CPSR contains the proper interrupt disable flags
    AND     R1, R1, #0xC0
    CMP     R1, #0xC0
    BNE     OSCPUSaveSR                ; Not properly disabled (try again)
    MOV     PC, LR                    ; Disabled, return the original CPSR contents in R0
 
OSCPURestoreSR
    MSR     CPSR_c, R0
    MOV     PC, LR
 
    END

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/136206.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • QT5.11下载与安装教程[通俗易懂]

    QT5.11下载与安装教程[通俗易懂]一、QT软件下载Qt5.9之后的安装包与之前相比,不再区分VS版本和MinGW版本,而是全都整合到了一个安装包中。因此,与之前的安装包相比,体积也是大了不少,以前是1G多,现在是2G多。QT5.9.0安装包QT5.8.0安装包下载地址:http://download.qt.io/archive/qt/各目录说明如下: ①gdb是针对Android开发的调试器。 ②jom可以百度…

    2022年5月17日
    40
  • ios系统软件迁移到安卓_苹果一键换机到安卓(苹果安卓一键迁移的软件)

    ios系统软件迁移到安卓_苹果一键换机到安卓(苹果安卓一键迁移的软件)去年开始,以iPhone为首的苹果系列产品,在中国销量出现严重下滑。2018年第四季度,苹果出货量下降约300万台,同比下降约22%。全年,iPhone出货量从2017年的3670万台,下降至2018年3420万台。苹果在中国市场销量跌跌不休已是不争事实。产品缺乏创新,价格屡创新高,消费者升级欲望随之降低。虽然整个手机大环境由增量市场转为存量市场,但每年换机的用户量依然庞大。这个现象现已逐步由国内…

    2022年5月26日
    130
  • 常用哈希函数介绍_简单说哈希函数是什么

    常用哈希函数介绍_简单说哈希函数是什么哈希函数介绍什么是哈希?在记录的关键字与记录的存储地址之间建立的一种对应关系叫哈希函数。哈希函数就是一种映射,是从关键字到存储地址的映射。通常,包含哈希函数的算法的算法复杂度都假设为O(1),这就是为什么在哈希表中搜索数据的时间复杂度会被认为是”平均为O(1)的复杂度”.在讲解具体内容前,首先我们要清楚以下几个概念:冲突(碰撞)对于不同的关键字ki、kj,若ki!=kj,但H(ki)=H(kj)的现象叫冲突(collision),即不同的输入却有相同的输出。我们应该尽量避免冲突,因为冲

    2022年10月29日
    0
  • nginx Access日志格式「建议收藏」

    nginx Access日志格式「建议收藏」默认,access日志路径是./logs/access.log,默认的日志格式为combined格式;使用log_format指令可以自定义日志格式;语法log_formatname[escape=default|json|none]string…;escape参数(1.11.8)设置变量的字符转义,json或default风格;默认使用default风格;none关闭转义…

    2022年6月10日
    26
  • 【Java】Java双端队列Deque使用详解

    【Java】Java双端队列Deque使用详解Deque是一个双端队列接口,继承自Queue接口,它们共同的实现类是LinkedList。Deque的功能很强大:代替普通队列Queue:先进先出、队尾进队头出可以作为双端队列:队尾和队头都可以进出还可以作为堆栈使用:先进后出、只能从一端进出注意:Java堆栈Stack类已经过时,Java官方推荐使用Deque替代Stack使用。jdk文档中关于Deque的使用介…

    2022年7月14日
    17

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号