第4章第3节 实时事件触发的实时抢…

第9章 中断 第9章 中断 cpsr 中断" TITLE="第9章 中断" /> 中断" TITLE="第9章 中断" /> 9.1.1 s3c2440中断控制器 中断方式:当某件事情发生时,硬件会设置某个寄存器;cpu在每执行完一个指令时,通过硬件查看这个寄存器,如果发生所关注的事件发生了,则中断当前程序流程,跳转到一个固定的地址处理这件事情。 中断" TITLE="第9章 中断" /> 阅读详情

源码请在https://github.com/ifreecoding/MbedRtos.git下载

下面来看一下MDS_TaskDelay函数的代码:

00196  U32 MDS_TaskDelay(U32 uiDelayTick)

00197  {

00198      M_CHAIN* pstrChain;

00199      M_CHAIN* pstrNode;

00200      M_CHAIN* pstrDelayNode;

00201      M_TCBQUE* pstrTaskQue;

00202      M_PRIOFLAG* pstrPrioFlag;

00203      U8 ucTaskPrio;

00204  

00205      

00206      if(gpstrCurTcb == gpstrIdleTaskTcb)

00207      {

00208          return RTN_FAIL;

00209      }

00210  

00211      

00212      if(DELAYNOWAIT != uiDelayTick)

00213      {

00214          

00215          ucTaskPrio = gpstrCurTcb->ucTaskPrio;

00216          pstrChain = &gstrReadyTab.astrChain[ucTaskPrio];

00217          pstrPrioFlag = &gstrReadyTab.strFlag;

00218  

00219          (void)MDS_IntLock();

00220  

00221          

00222          pstrNode = MDS_TaskDelFromSchedTab(pstrChain, pstrPrioFlag, ucTaskPrio);

00223  

00224          

00225          gpstrCurTcb->strTaskOpt.ucTaskSta &= ~((U8)TASKREADY);

00226  

00227          

00228          gpstrCurTcb->strTaskOpt.uiDelayTick = uiDelayTick;

00229  

00230          

00231          if(DELAYWAITFEV != uiDelayTick)

00232          {

00233              gpstrCurTcb->uiStillTick = guiTick + uiDelayTick;

00234  

00235              

00236              pstrTaskQue = (M_TCBQUE*)pstrNode;

00237              pstrDelayNode = &pstrTaskQue->pstrTcb->strDelayQue.strQueHead;

00238  

00239              

00240              MDS_TaskAddToDelayTab(pstrDelayNode);

00241  

00242              

00243              gpstrCurTcb->uiTaskFlag |= DELAYQUEFLAG;

00244          }

00245  

00246          

00247          gpstrCurTcb->strTaskOpt.ucTaskSta |= TASKDELAY;

00248  

00249          (void)MDS_IntUnlock();

00250      }

00251      else 

00252      {

00253          

00254          gpstrCurTcb->strTaskOpt.uiDelayTick = RTN_SUCD;

00255      }

00256  

00257      

00258      MDS_TaskSwiSched();

00259  

00260      

00261      return gpstrCurTcb->strTaskOpt.uiDelayTick;

00262  }

00196行,函数返回值分4种,RTN_SUCD: 任务没有delay,仅发生任务切换,仅在入口参数为0时才会返回该值。RTN_FAIL: 任务delay失败,没有进入delay状态。RTN_TKDLTO: 任务已经进入过delay状态,并且又从delay状态返回到running状态,delay的时间已耗尽, 超时返回。RTN_TKDLBK: 任务delay状态被打断,被其它任务使用MDS_TaskWake函数唤醒。

入口参数uiDelayTick是需要delay的tick数。

00206~00209行,idle任务不能延迟。

00212行,对任务delay的时间进行判断,不是delay 0 tick的情况走下面分支。

00222行,当前任务需要切换到delay状态,从ready表拆除。

00225行,清除任务的ready状态。

00227行,更新当前任务的延迟时间。

00231行,对任务delay的时间进行判断,不是永久delay的情况走下面分支。

00233行,计算该任务需要delay到的tick数值,存入TCB中。

00236行,将当前任务的M_TCBQUE型ready节点指针强制转换为M_TCBQUE型指针。

00237行,从任务的ready节点找到delay节点指针。

00240行,将该任务加入delay表。

00243行,在该任务的TCB中的任务标志uiTaskFlag中设置标志,表明该任务已经处于delay表中。

00247行,增加任务的delay状态。

00251~00255行,delay 0 tick时走此分支,任务只切换不延迟,将返回值保存在strTaskOpt中的uiDelayTick变量中。

00258行,任务相关变量、ready表、delay表的操作已经完成,调用MDS_TaskSwiSched函数触发软中断,开始任务调度。

00263行,将strTaskOpt中的uiDelayTick变量作为返回值返回给上级父函数。uiDelayTick变量中的返回值会在248行仅发生任务切换时存入,或者在任务调度函数MDS_TaskDelayTabSched中delay时间耗尽时存入,或者在MDS_TaskWake函数中由其它任务唤醒时存入。

261行与258行在代码编写上是连在一起的,但在执行时可能会有时间间隔,258行会发生任务调度,中间可能会插入其它任务的执行过程。

MDS_TaskWake函数正好与MDS_TaskDelay函数相反,它将处于delay状态的任务从delay表拆除,添加到ready表,并修改任务的一些相关状态变量,代码如下,不再详细介绍。

00270  U32 MDS_TaskWake(M_TCB* pstrTcb)

00271  {

00272      M_CHAIN* pstrChain;

00273      M_CHAIN* pstrNode;

00274      M_PRIOFLAG* pstrPrioFlag;

00275      U8 ucTaskPrio;

00276  

00277      

00278      if(NULL == pstrTcb)

00279      {

00280          return RTN_FAIL;

00281      }

00282  

00283      (void)MDS_IntLock();

00284  

00285      

00286      if(TASKDELAY != (TASKDELAY & pstrTcb->strTaskOpt.ucTaskSta))

00287      {

00288          (void)MDS_IntUnlock();

00289  

00290          return RTN_FAIL;

00291      }

00292  

00293      pstrNode = &pstrTcb->strDelayQue.strQueHead;

00294  

00295      

00296      if(DELAYWAITFEV != pstrTcb->strTaskOpt.uiDelayTick)

00297      {

00298          

00299          (void)MDS_ChainCurNodeDelete(&gstrDelayTab, pstrNode);

00300  

00301          

00302          pstrTcb->uiTaskFlag &= (~((U32)DELAYQUEFLAG));

00303      }

00304  

00305      

00306      pstrTcb->strTaskOpt.ucTaskSta &= ~((U8)TASKDELAY);

00307  

00308      

00309      pstrTcb->strTaskOpt.uiDelayTick = RTN_TKDLBK;

00310  

00311      

00312      ucTaskPrio = pstrTcb->ucTaskPrio;

00313      pstrChain = &gstrReadyTab.astrChain[ucTaskPrio];

00314      pstrPrioFlag = &gstrReadyTab.strFlag;

00315  

00316      

00317      MDS_TaskAddToSchedTab(pstrChain, pstrNode, pstrPrioFlag, ucTaskPrio);

00318  

00319      

00320      pstrTcb->strTaskOpt.ucTaskSta |= TASKREADY;

00321  

00322      (void)MDS_IntUnlock();

00323  

00324      

00325      MDS_TaskSwiSched();

00326  

00327      return RTN_SUCD;

00328  }

现在我们已经拥有了ready和delay两种任务状态,那么在tick中断里就需要对这两个调度表进行操作。这个过程分为2步,先对delay表操作,将delay时间耗尽的任务从delay表拆除,挂入ready表,使之能参与到ready表的调度之中,然后再对ready表进行调度。

来看调度函数的代码:

00345  void MDS_TaskSched(void)

00346  {

00347      M_TCB* pstrTcb;

00348  

00349      

00350      MDS_TaskDelayTabSched();

00351  

00352      

00353      pstrTcb = MDS_TaskReadyTabSched();

00354  

00355      

00356      MDS_TaskSwitch(pstrTcb);

00357  }

有关ready表调度的代码被封装到了353行的MDS_TaskReadyTabSched函数里面,本节新增的delay表调度代码被封装到350行的MDS_TaskDelayTabSched函数里面,下面来看看MDS_TaskDelayTabSched函数的代码:

00399  void MDS_TaskDelayTabSched(void)

00400  {

00401      M_TCB* pstrTcb;

00402      M_CHAIN* pstrChain;

00403      M_CHAIN* pstrNode;

00404      M_CHAIN* pstrDelayNode;

00405      M_CHAIN* pstrNextNode;

00406      M_PRIOFLAG* pstrPrioFlag;

00407      M_TCBQUE* pstrDelayQue;

00408      U32 uiTick;

00409      U8 ucTaskPrio;

00410  

00411      

00412      pstrDelayNode = MDS_ChainEmpInq(&gstrDelayTab);

00413  

00414      

00415      if(NULL != pstrDelayNode)

00416      {

00417          

00418          while(1)

00419          {

00420              

00421              pstrDelayQue = (M_TCBQUE*)pstrDelayNode;

00422              pstrTcb = pstrDelayQue->pstrTcb;

00423              uiTick = pstrTcb->uiStillTick;

00424  

00425              

00426              if(uiTick == guiTick)

00427              {

00428                  

00429                  pstrNextNode = MDS_ChainCurNodeDelete(&gstrDelayTab, pstrDelayNode);

00430  

00431                  

00432                  pstrTcb->uiTaskFlag &= (~((U32)DELAYQUEFLAG));

00433  

00434                  

00435                  pstrTcb->strTaskOpt.ucTaskSta &= ~((U8)TASKDELAY);

00436  

00437                  

00438                  pstrTcb->strTaskOpt.uiDelayTick = RTN_TKDLTO;

00439  

00440                  

00441                  pstrNode = &pstrTcb->strTcbQue.strQueHead;

00442                  ucTaskPrio = pstrTcb->ucTaskPrio;

00443                  pstrChain = &gstrReadyTab.astrChain[ucTaskPrio];

00444                  pstrPrioFlag = &gstrReadyTab.strFlag;

00445  

00446                  

00447                  MDS_TaskAddToSchedTab(pstrChain, pstrNode, pstrPrioFlag,

00448                                        ucTaskPrio);

00449  

00450                  

00451                  pstrTcb->strTaskOpt.ucTaskSta |= TASKREADY;

00452  

00453                  

00454                  if(NULL == pstrNextNode)

00455                  {

00456                      break;

00457                  }

00458                  else 

00459                  {

00460                      pstrDelayNode = pstrNextNode;

00461                  }

00462              }

00463              else 

00464              {

00465                  break;

00466              }

00467          }

00468      }

00469  }

00412行,从delay表中获取第一个子节点pstrDelayNode。

00415行,判断第一个子节点是否为空。

00418行,循环查询delay表中的任务。执行到此行说明delay链表不为空,说明有处于delay状态的任务。

000421行,将M_CHAIN型的指针pstrDelayNode强制转换为M_TCBQUE型的指针pstrDelayQue。

00422行,通过pstrDelayQue获取TCB指针。

00423行,通过TCB指针获取到任务delay状态耗尽时的tick数值。

00426行,被查询的任务delay状态在当前tick已经耗尽,需要从delay状态转换为ready状态,走下面分支。

00429行,将该任务从delay表中拆除。

00432行,从TCB中的任务标志uiTaskFlag中去除任务处于delay表的标志。

00435行,去除任务的delay状态。

00438行,将delay耗尽的返回值存入strTaskOpt中的uiDelayTick变量,供MDS_TaskDelay函数返回时使用。

00441~00451行,将该任务添加到ready表中。

00454~00461行,若下个节点为空,说明delay表已经遍历完毕,退出调度函数。若下个节点不为空则继续查询。

00463~00466行,走到此分支说明当前节点delay时间还没有耗尽,因为delay表是按照delay耗尽时间从少到多的顺序排列的,因此后面节点的时间也不会耗尽,不需要再遍历,直接返回。

下面介绍一下与软中断相关的函数。

Mindows中使用MDS_TaskSwiSched函数触发软中断,MDS_TaskSwiSched函数里面使用MDS_RunInInt函数对芯片当前的状态做了一个判断,避免在中断中触发软中断造成异常,实际触发软中断的函数是MDS_TaskOccurSwi函数。

00137  void MDS_TaskSwiSched(void)

00138  {

00139      

00140      if(RTN_SUCD == MDS_RunInInt())

00141      {

00142          return;

00143      }

00144  

00145      

00146      MDS_TaskOccurSwi(SWI_TASKSCHED);

00147  }

MDS_RunInInt调用了汇编函数MDS_GetChipMode获取芯片的工作模式,若不是USR模式则表明当前是在中断中运行。

00155  U32 MDS_RunInInt(void)

00156  {

00157      

00158      if(MODE_USR != MDS_GetChipMode())

00159      {

00160          return RTN_SUCD;

00161      }

00162      else

00163      {

00164          return RTN_FAIL;

00165      }

00166  }

MDS_GetChipMode函数是一个汇编函数,CPSR寄存器中的bit4~bit0中保存的就是当前模式,它将CPSR寄存器的bit4~bit0作为函数返回值保存到R0中。

00114      .func MDS_GetChipMode

00115  MDS_GetChipMode:

00116  

00117      MRS    R0, CPSR

00118      AND    R0, R0, #0x1F

00119      BX     R14

00120  

00121      .endfunc

MDS_TaskOccurSwi函数也是一个汇编函数,它有一个入口参数,用来表明该软中断的功能,C语言的函数原型为

MDS_TaskOccurSwi(U32 uiSwiNo);

汇编语言的源代码为:

00127      .func MDS_TaskOccurSwi

00128  MDS_TaskOccurSwi:

00129  

00130      SWI    0

00131      BX     R14

00132  

00133      .endfunc

00130行,执行“SWI”汇编指令,该指令会触发软中断,将PC指针跳转到软中断向量表。在startup.s文件的软中断向量表里面使用MDS_SwiContextSwitch函数作为软中断的服务函数,它的功能与tick中断的MDS_TickContextSwitch函数功能非常相似,都是用来调度任务的,但还是有一些不同的地方。

00054      .func MDS_SwiContextSwitch

00055  MDS_SwiContextSwitch:

00056  

00057      @保存接口寄存器

00058      ADD    R14, R14, #4

00059      STMDB  R13!, {R0 - R3, R12, R14}

00060  

00061      @调用C语言SWI中断处理函数

00062      LDR    R3, =MDS_SwiIsr

00063      MOV    R14, PC

00064      BX     R3

00065  

00066      @保存当前任务的堆栈信息

00067      LDR    R0, =gpstrCurTaskSpAddr

00068      LDR    R14, [R0]

00069      MRS    R0, SPSR

00070      STMIA  R14!, {R0}

00071      LDMIA  R13!, {R0 - R3, R12}

00072      STMIA  R14, {R0 - R14}^

00073      ADD    R14, R14, #0x3C

00074      LDMIA  R13!, {R0}

00075      STMIA  R14, {R0}

00076  

00077      @任务调度完毕, 恢复将要运行任务现场

00078      LDR    R0, =gpstrNextTaskSpAddr

00079      LDR    R14, [R0]

00080      LDMIA  R14, {R0}

00081      MSR    SPSR, R0

00082      LDMIB  R14, {R0 - R14}^

00083      NOP

00084      ADD    R14, R14, #0x40

00085      LDMIA  R14, {R14}

00086      SUB    R14, R14, #4

00087      MOVS   PC, R14

00088  

00089      .endfunc

00058行,将返回的LR寄存器地址多加4字节,这是因为在进入MDS_TickContextSwitch函数时硬件会自动多加4字节,为了使MDS_SwiContextSwitch函数与MDS_TickContextSwitch函数的栈格式相同,这里先多加4字节,在MDS_SwiContextSwitch函数返回前会再多减去4字节。

00062~00064行,调用软中断处理函数MDS_SwiIsr。注意,这里不能使用R0寄存器,因为此时R0中保存的是MDS_TaskOccurSwi函数传递进来的入口参数。

00067~00085行,寄存器组备份还原过程,与MDS_TickContextSwitch函数完全一致。

00086行,函数返回前减去前面多加的4字节。

00087行,软中断调度完成,使用MOVS指令返回,这点与tick中断所使用的ISR中断不同。

MDS_SwiIsr函数才是真正的软中断处理过程,使用C语言编写,所有的软中断处理过程都在这个函数内实现。

00094  void MDS_SwiIsr(U32 uiSwiNo)

00095  {

00096      

00097      if(SWI_TASKSCHED == (SWI_TASKSCHED & uiSwiNo))

00098      {

00099          

00100          MDS_TaskReadySched();

00101      }

00102      else 

00103      {

00104          

00105          MDS_TaskSwitch(gpstrCurTcb);

00106  

00107          switch(uiSwiNo)

00108          {

00109              case SWI_INTENABLE:     

00110  

00111                  MDS_IntEnable();

00112  

00113                  break;

00114  

00115              case SWI_INTDISABLE:    

00116  

00117                  MDS_IntDisable();

00118  

00119                  break;

00120  

00121              

00122  

00123              default:

00124  

00125                  break;

00126  

00127              

00128          }

00129      }

00130  }

00094行,入口参数uiSwiNo从MDS_TaskOccurSwi函数开始,被保存在R0中,经历了MDS_SwiContextSwitch函数传递给MDS_SwiIsr函数。

00097行,软中断调度的中断走此分支。

00100行,在软中断中调度任务,只需要调度ready表。delay表的调度是以tick为周期的,在tick中断中才能调度。

00102行,非软中断调度产生的软中断走此分支。

00105行,更新调度中所使用的全局变量。尽管是非软中断调度,但由于该函数的上级函数MDS_SwiContextSwitch会对寄存器组进行备份、恢复,因此此处也需要更新一下调度中所使用的全局变量。

00107行,选择不同的软中断命令分支。

00109~00113行,解锁中断命令,调用MDS_IntEnable函数解锁中断。MDS_IntEnable函数是汇编函数,直接修改CPSR中的全局中断控制位允许中断产生。

00115~00119行,锁中断命令,调用MDS_IntDisable函数锁中断。MDS_IntDisable函数是汇编函数,直接修改CPSR中的全局中断控制位禁止中断产生。

00121~00127行,用户可以将自定义的软中断命令放在此处执行。

MDS_IntEnable和MDS_IntDisable函数直接操作的对象是SVC模式下SPSRSVC寄存器,当程序从SVC模式返回到USR模式时,SPSRSVC寄存器就会被恢复到CPSR中,达到修改CPSR寄存器控制中断产生的目的。

00139      .func MDS_IntEnable

00140  MDS_IntEnable:

00141  

00142      MRS    R0, SPSR

00143      LDR    R1, =(CPSR_IRQENABLE & CPSR_FIQENABLE)

00144      AND    R0, R0, R1

00145      MSR    SPSR, R0

00146      BX     R14

00147  

00148  .endfunc

00154      .func MDS_IntDisable

00155  MDS_IntDisable:

00156  

00157      MRS    R0, SPSR

00158      LDR    R1, =(CPSR_IRQDISABLE | CPSR_FIQDISABLE)

00159      ORR    R0, R0, R1

00160      MSR    SPSR, R0

00161      BX     R14

00162  

00163      .endfunc

提供给用户使用的锁中断函数是MDS_IntLock,解锁中断函数是MDS_IntUnlock,它们同软中断调度函数一样,都是通过调用MDS_TaskOccurSwi函数触发软中断,通过入口参数区分功能,在软中断服务函数MDS_SwiIsr里实现自己的功能。

00650  U32 MDS_IntLock(void)

00651  {

00652      

00653      if(NULL == gpstrCurTcb)

00654      {

00655          return RTN_SUCD;

00656      }

00657  

00658      

00659      if(RTN_SUCD == MDS_RunInInt())

00660      {

00661          return RTN_SUCD;

00662      }

00663  

00664      

00665      if(0 == guiIntLockCounter)

00666      {

00667          MDS_TaskOccurSwi(SWI_INTDISABLE);

00668  

00669          guiIntLockCounter++;

00670  

00671          return RTN_SUCD;

00672      }

00673      

00674      else if(guiIntLockCounter < 0xFFFFFFFF)

00675      {

00676          guiIntLockCounter++;

00677  

00678          return RTN_SUCD;

00679      }

00680      else 

00681      {

00682          return RTN_FAIL;

00683      }

00684  }

00653~00656行,在还没有进入操作系统状态前不能执行此函数。

00659~00662行,在中断中不能执行此函数。

00665~00672行,guiIntLockCounter变量里存放的是锁中断、解锁中断的次数,初始化为0,当guiIntLockCounter为0时,说明是第一次执行该函数,只有第一次执行该函数时才操作硬件寄存器,执行锁中断动作。

需要注意一点,669行guiIntLockCounter变量自加需要在667行MDS_TaskOccurSwi函数之后执行,因为MDS_IntLock函数可能会重入,这样做在函数重入时,不会使guiIntLockCounter变量计数产生错误。

00674~00679行,guiIntLockCounter变量没有溢出则做自加操作,返回锁中断成功,是一个虚假的锁中断过程。

00680~00683行,guiIntLockCounter变量溢出,返回成功。

00693  U32 MDS_IntUnlock(void)

00694  {

00695      

00696      if(NULL == gpstrCurTcb)

00697      {

00698          return RTN_SUCD;

00699      }

00700  

00701      

00702      if(RTN_SUCD == MDS_RunInInt())

00703      {

00704          return RTN_SUCD;

00705      }

00706  

00707      

00708      if(guiIntLockCounter > 1)

00709      {

00710          guiIntLockCounter--;

00711  

00712          return RTN_SUCD;

00713      }

00714      

00715      else if(1 == guiIntLockCounter)

00716      {

00717          guiIntLockCounter--;

00718  

00719          MDS_TaskOccurSwi(SWI_INTENABLE);

00720  

00721          return RTN_SUCD;

00722      }

00723      else 

00724      {

00725          return RTN_FAIL;

00726      }

00727  }

MDS_IntUnlock函数与MDS_IntLock函数,非常相似,只有当guiIntLockCounter变量为1时才操作硬件寄存器,执行解锁中断动作。

本节操作系统部分的内容就介绍到这里。

Autodesk激活无无网络选项?许可类型与脱机激活排查修复指南 软件许可激活是保障正版授权正常使用的核心环节,常见的授权模式包括单机版许可和网络版许可,两者在认证机制和应用场景上有所区别。单机版离线授权依托 FlexNet Licensing Service 等底层服务组件,在断网或内网环境下为用户提供可靠的技术支持与授权验证路径。然而在实际部署中,激活窗口并不总是显示“无网络激活方式”入口,这可能与许可类型选择、网络环境干扰、组件安装残留或系统时间偏差有关。理解入口的动态呈现逻辑与排查顺序,有助于在 AutoCAD、Revit 等 Autodesk 产品中高效解决脱机 阅读详情

相关推荐

开源:AI+无人机巡检系统项目调研

本文系统梳理了主流开源无人机巡检技术栈,涵盖飞控系统(PX4/ArduPilot)、地面站软件(QGroundControl)、AI视觉识别(VisDrone/MPID/CPLID数据集)、三维重建(OpenDroneMap/COLMAP)和仿真模拟(AirSim/Gazebo)五大领域。通过对比各项目的技术特点、开发语言、开源协议及商用友好度,为无人机巡检产品开发提供完整的技术选型参考。重点推荐PX4飞控、DroneKit开发API等商用友好项目,同时分析了GPL/AGPL协议项目的开源要求。

lovehu6686的博客 2450

第4章第2节&nbsp;定时器触发的实时抢占…

源码请在https://github.com/ifreecoding/MbedRtos.git下载 本节中新增的重要内容已经介绍的差不多了,下面我们来看看使用tick中断的任务上下文切换过程。 在本节中,tick中断被配置为使用Timer1产生IRQ中断。产生tick中断时,硬件会自动将PC指针指向I

ifreecoding的博客 518

Windows10内核逆向-2-KiSystemCall64的调用流程剖析

本文深入剖析了Windows 10 x64系统中KiSystemCall64函数的完整调用流程。从用户态触发syscall指令开始,详细讲解了如何通过swapgs切换内核栈、构建KTRAP_FRAME陷阱帧、进行SMAP/CFG等安全检查,到最终通过SSDT寻址并执行目标系统服务的全过程,揭示了系统调用从Ring 3到Ring 0切换的核心机制与安全设计。

weixin_29209805的博客 82

第3章第4节&nbsp;使用Wanlix编写交通红…

源码请在https://github.com/ifreecoding/MbedRtos.git下载 第4节使用Wanlix编写交通红绿灯控制系统 至此我们已经实现了一个非常简单、小巧的操作系统——Wanlix,简单到它只具备任务切换这一项任务管理功能,而且需要用户自己主动切换,实时性较差。但无

ifreecoding的博客 554

CTF命令执行绕过实战:从空格过滤到无回显外带的7种核心姿势

命令执行漏洞是Web安全中的常见高危漏洞,其核心原理在于应用程序未对用户输入进行充分过滤,导致攻击者能够注入并执行系统命令。在真实环境中,安全防护措施(如WAF、输入过滤函数)普遍存在,因此漏洞利用的关键技术在于“绕过”这些过滤机制。理解过滤器的运作逻辑(如黑名单、白名单、转义、长度限制)是成功绕过的前提。通过系统学习**空格绕过**、**命令黑名单绕过**、**编码混淆**等基础技巧,并结合**无回显外带**、**反弹Shell**等高级利用链,安全研究人员能够有效应对复杂防护场景。本文以CTFshow

weixin_29315091的博客 370

医学影像处理实战:如何用Python+SimpleITK搞定DICOM/NIfTI重采样(附完整代码)

本文详细介绍了如何使用Python和SimpleITK库实现医学影像(DICOM/NIfTI格式)的智能重采样技术。通过实战代码演示,帮助读者掌握医学图像处理中的关键步骤,包括环境搭建、数据准备、核心算法实现和质量验证,解决医学AI领域中的影像标准化难题。

linux的博客 981

第4章第7节&nbsp;二进制信号量(一)

目前更新到5.3节,请在http://dl.dbank.com/c02ackpwp6下载5.3节的全部文档 本节源代码请在http://dl.dbank.com/c0fp2g5z9s下载   第7节 二进制信号量 某些资源在同一时刻只可以被一个任务操作,实时操作系统的任务抢占特性会导致这些资源可能被多个任务同时操作,从而产生错误。本节将讲述二进制信号量的原理,可以利用二进制信号量保护这些资源

ifreecoding的博客 2039

从防御者视角复盘:用WinArpAttacker和Wireshark在Windows上模拟并检测ARP欺骗攻击

本文详细解析了Windows平台下的ARP欺骗攻击与防御策略,通过WinArpAttacker和Wireshark工具模拟攻击并检测异常流量。文章涵盖实验环境搭建、攻击原理深度解析、流量特征分析及企业级防御方案,帮助安全运维人员全面掌握ARP攻击检测与防护技术。

weixin_30918633的博客 121

[转]*PyQt4&nbsp;精彩实例分析*&nbsp;实例10&nbsp;…

原文:http://blog.youkuaiyun.com/chumpklutz/article/details/6061077 本实例使用一个简单的例子说明如何在程序开发中使用Designer生成.ui文件。本实例利用Qt Designer生成了3个简单的ui,在使用时,两个ui插入到主程序的QTabWidget中,另一个ui由按钮触发弹出,如下图所示。主程序窗口TestDialog采用的是手动编写代码的

PandaraWen 宝盒 567

西安交通大学SQ轴承数据集(文末附数据)

西安交通大学SQ轴承数据集

qq_43271683的博客 1万+

爬虫面试:关于爬虫破解验证码的13个经典面试题

​解释:验证码是一种用于区分人类用户和自动化程序(如爬虫)的技术,通常通过显示图形、文字或音频等方式,要求用户完成特定任务(如识别扭曲的字母、点击特定区域等)。​作用:防止恶意爬虫滥用网站资源、进行批量注册、登录破解等行为,保护网站的安全性和数据的完整性。

数据知道的博客 1万+

第2章第1节&nbsp;ARM7芯片基本结构

源码请在https://github.com/ifreecoding/MbedRtos.git下载 第1节ARM7芯片基本结构 ARM7芯片构架比较简单,32bits线性地址空间统一排列,任何地址都是唯一的,不同的片上资源及外设被分配到不同的地址空间,不同数据结构的指针固定为4字节长度,这相对51芯片来说方便很多也清晰很多,从用户编程的角度来看入手比较简单,因此本手册首先选用

ifreecoding的博客 900

智能体开发套件(ADK)介绍

city } ---") city_normalized = city . lower() . replace(" " , "") # 模拟天气数据库 mock_weather_db = {

lpfasd123的博客 1406

第4章第7节&nbsp;二进制信号量(三)

目前更新到5.3节,请在http://dl.dbank.com/c02ackpwp6下载5.3节的全部文档 本节源代码请在http://dl.dbank.com/c0fp2g5z9s下载   图53列出了多个不同状态的任务与这些调度表之间的关系,任务1被信号量sem1阻塞,处于非永久pend态,strDelayQue结构中的strQueHead节点被挂接到delay表,strTcbQue结构中的

ifreecoding的博客 647

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

flex4&nbsp;读书笔记&nbsp;Chapter&nbsp;4

原文地址:读书笔记 Chapter 4">flex4 读书笔记 Chapter 4作者:搏拼 1、flex包含一个基于组件的开发模型,你只需要按需求继承现有的组件并扩展相关的方法就可开发你的应用。 2、可视化组件包括以下主要特性:尺寸、事件、样式、效果、皮肤。 3、flex定义了两套组件。一套为Spark,放在spark.*包下。一套为MX,放在mx.*包下。Spark是在flex4中新添加的,

lanyanai的专栏 887

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

对&nbsp与select标签的认识

对&nbsp与select标签的认识初学JavaScript,在做表单的时候遇到一点问题,我也就写着玩玩哈,这都是些我个人的认解。 &nbsp(空格)每个网页的&nbsp(空格)显示宽度各不相同,比如:Mozilla Firefox 显示空格宽度是汉字的1/2,而谷歌 显示空格宽度是1个汉字。 所以我们可以用 对span 设置margin-left=2em 注意:span 中的字体大小要与外部字

shichao1994的博客 314

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

jquery选择器&nbsp;参数为变量&nbsp;如何解决

$(function(){    alert(123);    var v=4;    var test=$("input[type='radio'][value='"+v+"']");//直接拼接字符串就可以了   console.info(test);    var testValue=test.attr({"checked":true});    console.info(testVal

nihousheng的专栏 848

oracle细粒度审计&nbsp;第&nbsp;3&nbsp;部分

oracle细粒度审计 第 3 部分 安全性和身份管理 现实问题的细粒度审计,第 3 部分 作者:Arup Nanda 现在您已经掌握了各种环境中的 FGA,下面您将了解到它如何能够在 Oracle Database 10g 中起到更大的作用 在本系列的前两个部分中,我向您介绍了细粒度审计 (FGA) 的概念,它用来在 Oracle9i Database 和更高版本中跟踪选定的语句。我还说

塔山上的山 364

phpMyAdmin&nbsp;3.5.0&nbsp;正式版发布

phpMyAdmin 3.5.0 正式版发布,该版本改进了浏览器的支持,包括表格编辑、记住历史表、记住最后排序的表和列宽等等,对很多操作进行 Ajax 处理,重新组织的服务器状态页,改进对存储过程、事件和触发器的支持,改进对 OpenGIS 支持 等等。 主要包括: 浏览器模式改进,包括表格式编辑,自动记忆最近使用过的数据表,自动记忆最近排序,可调整的列宽,更加紧凑的导航栏 操作 Ajax 化

tomora的专栏 550

wince6.0&nbsp;+S3C6410&nbsp;中断…

首先:介绍一下wince中断处理过程, 1、当一个中断发生后,发送到内核异常处理器(ExceptionHandler) 2、内核的中断支持处理器调用OAL层函数OEMInterruptDisable 屏蔽中断(..\hal\Cfw.c)      屏蔽掉所有优先级等于或是小于当前优先级的中断 3、内核调用ISR,ISR  返回中断号(逻辑中断标识符)给内核。       内核的处

caoshunxin01的专栏 192

AS3中&nbsp;Event&nbsp;类的target和cu…

原文地址:Event 类的target和currentTarget属性">AS3中 Event 类的target和currentTarget属性作者:笨鱼小宇  在事件处理过程中,会自动生成事件类的实例,并传给侦听器函数。通过这个参数就可以使用事件类的属性和方法。其中target与currentTarget属性是两个很相似的属性。  对于简单的事件处理过程,分清target与currentTa

211

Wince6.0&nbsp;s3c6410触摸屏驱动分析

Wince6.0 s3c6410触摸屏驱动分析     一、wince 触摸屏驱动概述... 3 二、触摸屏驱动接口分析... 4 2.1  Windows CE触摸屏驱动工作过程... 4 2.2 触摸屏驱动程序的实现... 4 2.3四线电阻式触摸屏的工作原理... 4 三、wince 6.0 触摸屏驱动分析... 6 3.1  TouchPanelEnable() 函数分析... 6 3.

无语僧 1854

jquery插件uploadify3.1&nbsp;上传组件

最近在测试使用一个jquery插件uploadify,最新版3.1 在网上找到一些资料,整理收藏一些.   onSelect : function(file) {}//这个方法就是当选择了图片了触发的事件 onUploadComplete : function(file) {}//这个方法是当图片上传完成后触发的事件 $(function() {  $('#file_upload').uploa

tobesili2012的专栏 508

[转]GCC&nbsp;4.6&nbsp;warning:&nbsp;variable&nbsp;…

Fedora 15 安装后,GCC 版本号升级至 4.6: $ gcc --version   gcc (GCC) 4.6.0 20110530 (Red Hat 4.6.0-9) Copyright (C) 2011 Free Software Foundation, Inc. This is free software; see the source for copying condi

Elta学习 878
上一篇: 第4章第3节&nbsp;实时事件触发的实时抢…
下一篇: 第4章第3节&nbsp;实时事件触发的实时抢…
ifreecoding
博客等级 码龄15年 148粉丝 33原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值