首页 > 其他分享 >实保护模式、任务、任务内特权集切换

实保护模式、任务、任务内特权集切换

时间:2023-12-12 12:00:47浏览次数:29  
标签:保护模式 0000 MOV 任务 切换 LDT GDT SEL 描述符

保护模式是内核逆向、内核对抗基础。

《80x86汇编汇编语言程序设计》第10章示例5清晰的展示了:实模式/保护模式的切换,任务内特权集切换,任务间切换的底层细节。

保护模式学习代码笔记如下:

;程序名:T10-5.ASM
;功能:演示任务切换和任务内特权级变换
;
INCLUDE 386SCD.ASM;参见实例三
.386P
;全局描述符表
GDTSEG SEGMENT 	PARA 	USE16
    ;全局描述符表标号
                 GDT       LABEL 	BYTE
                 
    ;空描述符
                 DUMMY     DESCRIPTOR 		<>

    ;规范描述符
    ;描述符的含义为,段界限为0FFFFH,基址为0h,属性为R0可读写数据段
                 NORMAL    DESCRIPTOR 		<0FFFFH,0,0,ATDW,0>
    ;NORMAL为GDT第二个描述符,一个描述符结构体的长度位8h,所以NORMAL - 0 = 0008h
    ;0008h = 0000 0000 0000 1000 = 0000000000001 0 00
    ;表示0环GDT中index = 1的描述符
    Normal_SEL   =         NORMAL - GDT

    ;全局描述符表任务定义描述符起始表示
                 EFFGDT    LABEL 	BYTE


    ;演示任务的任务状态段描述符
    ;描述符内容为,段界限为DemoTSSLEN - 1,基址为DemoTSSSEG段,属性为R0环386TSS类型值
                 DEMOTSS   DESCRIPTOR 		<DemoTSSLEN - 1,DemoTSSSEG,,AT386Tss,>
    ;DEMOTSS为GDT第三个描述符,一个描述符结构体的长度位8h,所以DEMOTSS - 0 = 0010h
    ;0010h = 0000 0000 0001 0000 = 0000000000010 0 00
    ;表示RPL=0环GDT中index = 2的描述符
    DemoTSS_SEL  =         DEMOTSS - GDT


    ;演示任务的局部描述符表段描述符
    ;描述符内容为,段界限为DemoLDTLEN - 1,基址为DemoLDTSEG段,属性为R0环局部描述符表段类型值
                 DEMOLDTAB DESCRIPTOR 		<DemoLDTLEN - 1,DemoLDTSEG,,ATLDT,>
    ;DEMOLDTAB为GDT第四个描述符,一个描述符结构体的长度位8h,所以DEMOLDTAB - 0 = 0018h
    ;0018h = 0000 0000 0001 1000 = 0000000000011 0 00
    ;表示RPL=0环GDT中index = 3的描述符
    DemoLDT_SEL  =         DEMOLDTAB - GDT


    ;临时任务的任务状态段描述符
    ;描述符内容为,段界限为TempTSSLEN - 1,基址为TempTSSSEG段,属性为R2环386TSS类型值
                 TEMPTSS   DESCRIPTOR 		<TempTSSLEN - 1,TempTSSSEG,,AT386TSS+DPL2,>
    ;TEMPTSS为GDT第五个描述符,一个描述符结构体的长度位8h,所以TEMPTSS - 0 = 0020h
    ;0020h = 0000 0000 0010 0000 = 0000000000100 0 00
    ;表示RPL=0环GDT中index = 4的描述符
    TempTSS_SEL  =         TEMPTSS - GDT


    ;临时任务代码段
    ;描述符内容为,段界限为0FFFFH,基址为TempCodeSEG段,属性为R0环可执行代码段
                 TEMPCODE  DESCRIPTOR 		<0FFFFH,TempCodeSEG,,ATCE,>
    ;TEMPCODE为GDT第六个描述符,一个描述符结构体的长度位8h,所以TEMPCODE - 0 = 0028h
    ;0028h = 0000 0000 0010 1000 = 0000000000101 0 00
    ;表示RPL=0环GDT中index = 5的描述符
    TempCode_SEL =         TEMPCODE - GDT


    ;子程序代码段描述符
    ;描述符内容为,段界限为SUBRLEN - 1,基址为SUBRSEG段,属性为R0环子程序代码段
                 SUBR      DESCRIPTOR 		<SUBRLEN - 1,SUBRSEG,,ATCE+D32,>
    ;SUBR为GDT第七个描述符,一个描述符结构体的长度位8h,所以SUBR - 0 = 0030h + 3h = 0033h
    ;0033h = 0000 0000 0011 0000 = 0000000000110 0 11
    ;表示RPL=3环GDT中index = 6的描述符
    SUBR_SEL     =         SUBR_GDT + RPL3


    ;显示缓冲区段描述符
    ;描述符内容为,段界限为0FFFFH,基址为0H,属性为R3环显示缓冲区段
                 VIDEOBUFF DESCRIPTOR 		<0FFFFH,0,0,0F00H+ATDW+DPL3,0>
    ;VIDEOBUFF为GDT第八个描述符,一个描述符结构体的长度位8h,所以VIDEOBUFF - 0 = 0038h
    ;0038h = 0000 0000 0011 1000 = 0000000000111 0 00
    ;表示RPL=0环GDT中index = 7的描述符
    Video_SEL    =         VIDEOBUFF - GDT

    ;可用的全局描述符个数
    GDNUM        =         ($ - EFFGDT)/(SIZE DESCRIPTOR)

    ;GDT长度
    GDTLEN       =         $	-	GDT
GDTSEG ENDS
;演示任务的任务状态段
DemoTSSSEG SEGMENT 	PARA 	USE16
               DD 0                   ;链接字
               DD DemoStack0LEN       ;0级堆栈指针
               DW DemoStack0_SEL,0
               DD 0                   ;1级堆栈指针(实例不使用)
               DW ?,0
               DD DemoStack2LEN       ;2级堆栈指针
               DW DemoStack2_SEL,0
               DD 0                   ;CR3
               DW DemoBegin,0         ;EIP
               DD 0                   ;EFLAGS
               DD 0                   ;EAX
               DD 0                   ;ECX
               DD 0                   ;EDX
               DD 0                   ;EBX
               DD DemoStack2LEN       ;ESP
               DD 0                   ;EBP
               DD 0                   ;ESI
               DD 0B8000H             ;EDI
               DW Video_SEL,0         ;ES
               DW DemoCode_SEL,0      ;CS
               DW DemoStack2_SEL,0    ;SS
               DW DemoData_SEL,0      ;DS
               DW ToDLDT_SEL,0        ;FS
               DW ToTTSS_SEL,0        ;GS
               DW DemoLDT_SEL,0       ;LDTR
               DW 0
               DW $ + 2               ;`I/O`许可位图指针
               DB 0FFH                ;`I/O`许可位图结束字节
    DemoTSSLEN =  $
DemoTSSSEG ENDS
;演示任务的局部描述符表LDT
DemoLDTSEG SEGMENT 	PARA 	USE16
    ;局部描述符表标号
                   DemoLDT    LABEL 	BYTE


    ;0级堆栈段描述符(32位段)
    ;描述符内容为,段界限为DemoStack0LEN - 1,基址为DemoStack0SEG段,属性为R0环32位可读写数据段
                   DEMOSTACKO DESCRIPTOR 		<DemoStack0LEN,,DemoStack0SEG,ATDW + D32,>
    ;DEMOSTACK0为LDT第一个描述符,一个描述符结构体的长度位8h,所以0 * 8 - 0 = 0h + 4h = 04h
    ;04h = 0000 0000 0000 0100 = 0000000000000 1 00
    ;表示RPL=0环LDT中index = 0的描述符
    DemoStackO_SEL =          (DEMOSTACK0 - DemoLDT) + TIL


    ;1级堆栈段描述符(32位段,DPL=2)
    ;描述符内容为,段界限为DemoStack1LEN - 1,基址为DemoStack1SEG段,属性为R2环32位可读写数据段
                   DEMOSTACK2 DESCRIPTOR 		<DemoStack2LEN - 1,DemoStack2SEG,ATDW+D32+DPL2,>
    ;DEMOSTACK1为LDT第二个描述符,一个描述符结构体的长度位8h,所以1*8 - 0 = 0008h + 4h = 0ch + 0001h = 0Dh
    ;0Dh = 0000 0000 0000 1101 = 0000000000001 1 01
    ;表示RPL=1环LDT中index = 1的描述符
    DemoStack2_SEL =          (DEMOSTACK2 - DemoLDT) + TIL + RPL2


    ;演示代码段描述符(32位段,DPL=2)
    ;描述符内容为,段界限为DemoCodeLEN - 1,基址为DemoCodeSEG段,属性为R2环32位可读写数据段
                   DEMOCODE   DESCRIPTOR 		<DemoCodeLEN - 1,DemoCodeSEG,,ATCE+D32+DPL2,>
    ;DEMOCODE为LDT第三个描述符,一个描述符结构体的长度位8h,所以2*8 - 0 = 0010h + 4h = 14h + 0001h = 15h
    ;15h = 0000 0000 0001 0101 = 0000000000010 1 01
    ;表示RPL=1环LDT中index = 2的描述符
    DemoCode_SEL   =          (DEMOCODE - DemoLDT) + TIL + RPL2


    ;演示数据段描述符(32位段,DPL=3)
    ;描述符内容为,段界限为DemoDataLEN - 1,基址为DemoDataSEG段,属性为R3环32位可读写数据段
                   DEMODATA   DESCRIPTOR 		<DemoDataLEN - 1,DemoDataSEG,,ATDW+D32+DPL3,>
    ;DEMODATA为LDT第四个描述符,一个描述符结构体的长度位8h,所以3*8 - 0 = 0018h + 4h = 1Ch
    ;1Ch = 0000 0000 0001 1100 = 0000000000011 1 00
    ;表示RPL=0环LDT中index = 3的描述符
    DemoData_SEL   =          (DEMODATA - DemoLDT) + TIL


    ;把LDT作为普通数据段描述的描述符(DPL=2)
    ;描述符内容为,段界限为DemoLDTLEN - 1,基址为DemoLDTSEG段,属性为R2环32位可读写数据段
                   TODLDT     DESCRIPTOR 		<DemoLDTLEN - 1,DemoLDTSEG,,ATDW+DPL2,>
    ;TODLDT为LDT第五个描述符,一个描述符结构体的长度位8h,所以4*8 - 0 = 0020h + 4h = 24h
    ;24h = 0000 0000 0010 0100 = 0000000000100 1 00
    ;表示RPL=0环LDT中index = 4的描述符
    ToDLDT_SEL     =          (TODLDT - DemoLDT) + TIL


    ;把TSS作为普通数据段描述的描述符(DPL=2)
    ;描述符内容为,段界限为TempTSSLEN - 1,基址为TempTSSSEG段,属性为R2环386TSS类型值
                   TOTTSS     DESCRIPTOR 		<TempTSSLEN - 1,TempTSSSEG,,ATDW+DPL2,>
    ;TOTTSS为LDT第六个描述符,一个描述符结构体的长度位8h,所以5*8 - 0 = 0028h + 4h = 2Ch
    ;2Ch = 0000 0000 0010 1100 = 0000000000101 1 00
    ;表示RPL=0环LDT中index = 5的描述符
    ToTTSS_SEL     =          (TOTTSS - DemoLDT)	+	TIL

    ;演示任务的LDT描述符个数
    DemoLDNUM      =          ($	-	DemoLDT)/(SIZE DESCRIPTOR)


    ;指向子程序SUBRB的调用门(DPL=3)
    ;TOSUBR为门描述符,含义为,SUBRB为偏移低16位,SUBR_SEL为目标选择子,0为参数计数器,AT386CGAT+DPL3为3环386调用门类型值,0为偏移高16位
                   TOSUBR     GATE 			<SUBRB,SUBR_SEL,0,AT386CGAT+DPL3,0>
    ;TOSUBR为LDT第七个描述符,一个描述符结构体的长度位8h,所以6 * 8 - 0 = 0030h + 4h = 34h
    ;34h = 0000 0000 0011 0100 = 0000000000110 1 10
    ;表示RPL=2环LDT中index = 6的描述符
    TOSUBR_SEL     =          (TOSUBR - DemoLDT) + TIL + RPL2


    ;指向临时任务Temp的任务门(DPL=3)
    ;TOTEMPT为门描述符,含义为,0为偏移低16位,TempTSS_SEL为目标选择子,0为参数计数器,AT386CGAT+DPL3为3环386调用门类型值,0为偏移高16位
                   TOTEMPT    GATE 			<0,TempTSS_SEL,0,ATTASKGAT+DPL3,0>
    ;TOTEMPT为LDT第八个描述符,一个描述符结构体的长度位8h,所以7 * 8 - 0 = 0038h + 4h = 38h
    ;38h = 0000 0000 0011 1000 = 0000000000111 1 00
    ;表示RPL=0环LDT中index = 7的描述符
    ToTempT_SEL    =          (TOTEMPT - DemoLDT) + TIL

    ;演示任务的LDT长度
    DemoLDTLEN     =          $ 	- 	DemoLDT
DemoLDTSEG ENDS
;演示任务的0级堆栈(32位段)
DemoStackOSEG SEGMENT 	PARA 	USE32
    DemoStackOLEN =  1024
                  DB DemoStack0LEN 	DUP (0)
DemoStackOSEG ENDS
;演示任务的2级堆栈(32位段)
DemoStack2SEG SEGMENT 	PARA 	USE32
    DemoStack2LEN =  512
                  DB DemoStack2LEN 	DUP (0)
DemoStack2SEG ENDS
;演示任务的数据段(32位段)
DemoDataSEG SEGMENT 	PARA 	USE32
    Message     DB 'Value=',0
    DemoDataLEN =  $
DemoDataSEG ENDS
;子程序段(32位段)
;CPL=0
;使用0级堆栈
SUBRSEG SEGMENT 	PARA 	USE32
            ASSUME     CS:SUBRSEG
SUBRB PROC 	FAR
            PUSH       EBP
            MOV        EBP,ESP
            PUSHAD                     ;保护现场
    ;从堆栈(0级)中取提示信息串偏移
    ;为什么是+12?
    ;+4是外层EIP
    ;+8是外层CS
    ;+12是第2个参数,Message起始地址
            MOV        EAX,[EBP+12]
            MOV        ESI,EAX
            MOV        AH,7
            JMP        SHORT SUBR2
    SUBR1:                             ;输出message信息与TempTask.TREIP
            STOSW
    SUBR2:  
            LODSB
            OR         AL,AL
            JNZ        SUBR1           ;从堆栈(0级)中取显示值
            MOV        EDX.[EBP+16]
            MOV        ECX,8
    SUBR3:  
            ROL        EDX,
            MOV        AL,DL
            CALL       HTOASC
            STOSW
            LOOP       SUBR3
            POPAD                      ;恢复现场
            POP        EBP
            RET        8               ;ret 8 堆栈平衡
SUBRB ENDP
HTOASC PROC
            AND        AL,0FH
            ADD        AL,90H
            DAA
            ADC        AL,40H
            DAA
            RET
            HTOASCENDP
    SUBRLEN =          $
SUBRSEG ENDS
;演示任务的代码段(32位段)
;从R0切换过来,CPL=2
DemoCodeSEG SEGMENT 	PARA 	USE32
                ASSUME CS:DemoCodeSEG
    DemoBegin:  
    ;表示在特权级向内层变换时,需从外层堆栈依次复制2个双字参数到内层堆栈
                MOV    FS:ToSUBR.DCOUNT,2
    ;向堆栈(2级)中压入参数
    ;TempTask 是临时任务TSS,当前要通过调用们进行特权集切换,现将返回地址压入对账
    ;将提示信息前缀压入堆栈
                PUSH   DWORD PTR GS:TempTask.TREIP
                PUSH   OFFSET Message
    ;通过调用门调用子程序 SUBRB
    ;选择子 TOSUBR_SEL RPL=2
    ;选择子 TOSUBR_SEL 指向的 TOSUBR 调用门 DPL=3 可以调用
    ;执行调用门 TOSUBR
    ;调用门指向 SUBR_SEL 选择子,RPL=0,且偏移为 SUBRB
    ;SUBR_SEL 选择子 RPL=3 指向的段为 SUBRSEG DPL=0
    ;特权集进行切换,堆栈也进行了切换
                CALL32 ToSUBR_SEL,0
    ;SUBRB的返回,`CPL=0`变换为`CPL=2`,堆栈也回到2级堆栈
    ;把指向规范数据段描述符的选择子填入临时任务TSS
                ASSUME DS:TempTSSSEG
                PUSH   GS
                POP    DS
                MOV    AX,Normal.SEL
                MOV    TempTask.TRDS,AX
                MOV    TempTask.TRES.AX
                MOV    TempTask.TRFS,AX
                MOV    TempTask.TRGS,AX
                MOV    TempTask.TRSS,AX
    ;通过任务切换到临时任务
    ;CPL=2
    ;ToTempT_SEL RPL=0
    ;ToTempT_SEL 指向的 TempTSS_SEL DPL=3,偏移为0
    ;TempTSS_SEL RPL=0 指向 TempTSSSEG DPL=2
    ;跳转TSS.CS TSS.EIP
    ;跳转CS:TempCodeSEG,EIP:ToReal
                JUMP32 ToTempT_SEL,0
    DemoCodeLEN =      $
DemoCodeSEG ENDS
;临时任务的任务状态段
TempTSSSEG SEGMENT 	PARA 	USE16
               TempTask TASKSS	<>
               DB       0FFH
    TempTSSLEN =        $
TempTSSSEG ENDS
;临时任务的代码段
TempCodeSEG SEGMENT 	PARA 	USE16
                 ASSUME CS:TempCodeSEC
    Virtual:     
    ;将 TempTSS 装载到 TR
    ;TempTSS_SEL 的 RPl=0
    ;TempTSS_SEL 指向的 TEMPTSS 的 DPL=2
                 MOV    BX,TempTSS_SEL
                 LTR    BX                          ;要把临时任务的现场保存到临时任务的`TSS`,这就要求`TR`指向临时任务的`TSS`
    ;CPL=0
    ;DemoTSS_SEL 的 RPL= 0
    ;DemoTSS_SEL 指向 DemoTSSSEG 的 DPL=0
    ;DemoTSSSEG 为定义的TSS段,预定义的CS=DemoCode_SEL,EIP=DemoBegin
    ;DemoCode_SEL 为指向 DemoCodeSEG 的选择子,RPL=2,DPL=2
    ;采用段间转移指令`JMP`,直接指向演示任务的`TSS`,切换到演示任务,切换动作包括
    ;1:把临时任务的执行现场保存到临时任务的`TSS`中
    ;2:从演示任务的`TSS`中恢复演示任务的现场
    ;3:把演示任务的`LDT`描述符选择子装载到`LDTR`等
                 JUMP16 DemoTSS_SEL,0               ;直接切换到演示任务
    ;TSS中的CS:TempCodeSEG,EIP:ToReal
    ToReal:                                         ;准备返回实方式
                 CLTS                               ;清空TS
    ;清任务切换标志
                 MOV    EAX,CR0
                 AND    EAX,0FFFFFFFEH
                 MOV    CR0,EAX                     ;PE位置0,返回实模式
    ;返回实方式
                 JUMP16 <SEG Real>,<OFFSET Real>
    TempCodel_EN =      $
TempCodeSEG ENDS
;实方式数据段
RDataSEG SEGMENT 	PARA 	USE16
             VGDTR PDESC <GDTLEN-1,>
    SPVAR    DW    ?
    SSVAR    DW    ?
RDataSEG ENDS
;实方式代码段
RCodeSEG SEGMENT 	PARA 	USE16
             ASSUME CS:RCodeSEG,DS:RDataSEG,ES:RDataSEG
    Start:   
             MOV    AX,RDataSEG
             MOV    DS,AX                                  ;装载实模式数据段
             CLD                                           ;设置方向标志
             CALL   INIT_GDT                               ;初始化GDT
             MOV    AX,DemoLDTSEG
             MOV    FS,AX
             MOV    CX,DemoLDNUM
             MOV    SI,OFFSET DemoLDT
             CALL   INIT_LDT                               ;初始化演示任务LDT
  
             MOV    SSVAR,SS
             MOV    SPVAR,SP                               ;保存实方式下的堆栈指针


             LGDT   QWORD PTR VGDTR                        ;装载GDTR
             CLI                                           ;关中断
             MOV    EAX,CR0
             OR     EAX,1
             MOV    CR0,EAX                                ;CR0的PE位置为1,切换到保护模式
    ;切换到保护方式
    ;CPL=0 TempCode_SEL(RPL=0) 可以调用
    ;TempCode_SEL 指向的 TempCodeSEG DPL=0,可以跳转
             JUMP16 <TempCode_SEL>,<OFFSET Virtual>
    Real:    
    ;又回到实方式
             MOV    AX,RDataSEG
             MOV    DS,AX
             LSS    SP,DWORD PTR SPVAR                     ;将源操作数加载到目标操作数中,并且 TR 寄存器的内容更新为源操作数
             STI                                           ;开中断
             MOV    AX,4C00H
             INT    21H
    ;初始化全局描述符表的子程序
    ;(1)把定义时预置的段值转换成32位段基地址并置入描述符内相应字段
    ;(2)初始化为GDTR准备的伪描述符
INIT_GDT PROC 	NEAR
             PUSH   DS
             MOV    AX,GDTSEG                              ;定义的GDT段段值挪到AX中
             MOV    DS,AX                                  ;定义的GDT段段值挪到DS中
             MOV    CX,GDNUM                               ;GDNUM是初始化的描述符个数
             MOV    SI,OFFSET EFFGDT                       ;EFFGDT是开始偏移
    ;将描述符中的基址扩展到32位
    INITG:   
             MOV    AX,[SI].BASEL                          ;取出预置的段值
             MOVZX  EAX,AX                                 ;将初始化进去的16位段值扩展到32位
             SHL    EAX,4                                  ;段值左移4位
             SHLD   EDX,EAX,16                             ;分解到2个16位寄存器
             MOV    [SI].BASEL,AX
             MOV    [SI].BASEM,DL                          ;置入描述符相应字段
             MOV    [SI].BASEH,DH
             ADD    SI,SIZE DESCRIPTOR                     ;调整到下一描述符
             LOOP   INITG                                  ;所有描述符处理完后,退出循环
    ;描述符中的基址扩展完成
             POP    DS
    ;初始化为GDTR准备的伪描述符
             MOV    BX,16
             MOV    AX,GDTSEG
             MUL    BX
             MOV    WORD PTR VGDTR.BASE,AX
             MOV    WORD PTR VGDTR.BASE+2,DX               ;VGDTR初始化完成
             RET
INIT_GDT ENDP
    ;初始化演示任务局部描述符表的子程序
    ;把定义时预置的段值转换成32位段基地址并置入描述符内相应字段
    ;入口参数:FS:SI=第一个要初始化的描述符
    ;CX=要初始化的描述符个数
INIT_LDT PROC
    ;将初始化进去的16位段值扩展到32位
    ILDT:    
             MOV    AX,FS:[SI].BASEL
             MOVZX  EAX,AX
             SHL    EAX,4
             SHLD   EDX,EAX.16
             MOV    FS:[SI].BASEL,AX
             MOV    FS:[SI].BASEM,DL
             MOV    FS:[SI].BASEH,DH
             ADD    SI,SIZE DESCRIPTOR
             LOOP   ILDT
    ;将初始化进去的16位段值扩展到32位结束
             RET
INIT_LDT ENDP
RCodeSEG ENDS
	END Start

标签:保护模式,0000,MOV,任务,切换,LDT,GDT,SEL,描述符
From: https://www.cnblogs.com/ylc0x01/p/17896495.html

相关文章

  • 任务冻结 【ChatGPT】
    https://www.kernel.org/doc/html/v6.6/power/freezing-of-tasks.html任务冻结什么是任务冻结?任务冻结是一种机制,通过该机制可以在休眠或系统范围挂起(在某些架构上)期间控制用户空间进程和一些内核线程。它是如何工作的?任务冻结使用三个任务级标志,即PF_NOFREEZE、PF_FROZEN......
  • Unity3D 任务系统的架构与设计详解
    前言Unity3D是一款非常强大的游戏引擎,它提供了丰富的功能和工具,使得游戏开发变得更加简单和高效。在游戏开发中,任务系统是一个非常重要的组件,它可以使游戏更加有趣和挑战性。在本文中,我们将详细介绍Unity3D任务系统的架构与设计,包括技术详解和代码实现。对惹,这里有一个游戏开......
  • FreeRTOS中的事件组:实现任务同步与通信的强大工具
    引言:在实时嵌入式系统中,任务同步和通信是至关重要的,而FreeRTOS提供的事件组(EventGroups)机制为实现这一目标提供了一种高效且灵活的解决方案。本篇博客将深入研究FreeRTOS中的事件组,详细介绍其原理、使用方法,以及在实际应用中的一些最佳实践。事件组原理:事件组是FreeRTOS中的一种......
  • 我国民航飞机维修技术与优化措施——任务书
    一、 论文(设计)方向:1.了解我国民航飞机维修的过程;2.根据有关了解,给出相应的改变措施和建议。二、 主要参考资料: [1]林福智,民航飞机维修技术和方法D数字化用户,2019,25(9):115.[2]周多武.民航飞机维修技术和方法探讨D.军民两用技术与产品,2018(24):208.[3]王峥:基于民航飞机维修技术和方......
  • Oracle切换undo后如何确定使用旧undo的会话信息
     Oracle切换undo后如何确定使用旧undo的会话信息 背景是这样的,最近RAC的磁盘组90%报警,存储空间只能再加2T空间。而这套RAC的DATA组用了normal冗余,不知道当初哪个大聪明这么搞的,底层还是做了RAID10的。领导也不知道不懂这么设置的。因此,这新的2T创建新磁盘组且使用extern......
  • 已删除但未消失的图片(Excel与WPS切换时产生的问题)
    问题:一个完全空的工作簿为何会非常大?问题分析:将工作簿后缀名改成rar,打开..xl/media,可以看到有很多图片,这些图片造成了文件大。进一步的问题:这些图片哪里来的,藏在何处。过程:这是Excel与WPS操作同一工作簿产生的问题。第一步:使用WPS打开工作簿,在其中插入嵌入到单元格的图片第......
  • 公式识别任务各个链条全部打通
    引言随着LaTeX-OCR模型转换问题的解决,公式识别任务中各个链条已经全部打通。小伙伴们可以放开膀子干了。解决业界问题的方案,并不是单独训练一个模型就完事了,而是有着上下游的依赖。这就像工厂中流水线作业一样,一个小东西的生产是依赖无数个中间阶段才完成的。一个模型应用到产......
  • Linux p15 定时任务调度
    【学习课程】:【【小白入门通俗易懂】2021韩顺平一周学会Linux】https://www.bilibili.com/video/BV1Sv411r7vd/?p=14&share_source=copy_web&vd_source=2c07d62293f5003c919b2df9b2e0549e定时任务调度一、crond任务调度基本介绍crontab进行定时任务的设置概述任务调......
  • 计划任务与日志
    [root@localhost~]#systemctlenablecrond[root@localhost~]#psaux|grepcrondroot62420.30.01263801656?Ss16:270:00/usr/sbin/crond-ncrond进程每分钟会处理一次计划任务存储位置[root@localhost~]#ls/var/spool/cron......
  • scrum|敏捷开发之任务看板
    上篇文章中,我讲了敏捷第一步-每日站立会,讲了我们平时是怎么开站立会的,其实15-30分钟就够了,绝对不是时间长得让你想拄拐那种。本文我们开始讲敏捷开发中的看板。没有看板之前,我们真的是在白板上画泳道,写卡片,挪动卡片,在白板前开站立会。现在支持任务看板的产品也越来越多了,大家开站......