os_mutex.c(全)

2023-11-17

  • 无等待地获取互斥型信号量 OSMutexAccept (OS_EVENT  *pevent,INT8U  *perr):
  • 创建互斥型信号量OS_EVENT  *OSMutexCreate (INT8U   prio,INT8U  *perr)
  • 删除信号量OS_EVENT  *OSMutexDel (OS_EVENT  *pevent,INT8U  opt,INT8U  *perr)
  • 等待互斥型信号量void  OSMutexPend (OS_EVENT  *pevent,INT32U  timeout,INT8U  *perr)
  • 释放一个互斥型信号量 OSMutexPost (OS_EVENT *pevent)
  • 查询互斥量OSMutexQuery (OS_EVENT  *pevent,OS_MUTEX_DATA  *p_mutex_data)

 OSMutexAccept (OS_EVENT  *pevent,INT8U     *perr):

若是信号量可用就使用信号量,若是不可用就去执行其他代码, 不阻塞等待。
若是有可用的,那么其操作跟请求互斥信号量OSMutexPend的信号量可用时执行代码部分是一样的。
/*$PAGE*/
/*2018/2/19
*********************************************************************************************************
*                                   ACCEPT MUTUAL EXCLUSION SEMAPHORE
*									无等待地获取互斥型信号量
* Description: This  function checks the mutual exclusion semaphore to see if a resource is available.
*              Unlike OSMutexPend(), OSMutexAccept() does not suspend the calling task if the resource is
*              not available or the event did not occur.
*描述: 检查互斥型信号量,以判断某资源是否可以使用,与 OSMutexPend()不同的是,若资源不能使用,
		则调用 OSMutexAccept()函数的任务并不被挂起, OSMutexAccept()仅查询状态。
* Arguments  : pevent     is a pointer to the event control block
*参数:			pevent:指向事件控制块的指针
*              perr       is a pointer to an error code which will be returned to your application:
*                            OS_ERR_NONE         if the call was successful.
*                            OS_ERR_EVENT_TYPE   if 'pevent' is not a pointer to a mutex
*                            OS_ERR_PEVENT_NULL  'pevent' is a NULL pointer
*                            OS_ERR_PEND_ISR     if you called this function from an ISR
*                            OS_ERR_PIP_LOWER    If the priority of the task that owns the Mutex is
*                                                HIGHER (i.e. a lower number) than the PIP.  This error
*                                                indicates that you did not set the PIP higher (lower
*                                                number) than ALL the tasks that compete for the Mutex.
*                                                Unfortunately, this is something that could not be
*                                                detected when the Mutex is created because we don't know
*                                                what tasks will be using the Mutex.
*				perr:	指向错误码的指针。可以有以下几种选择:
						OS_ERR_NONE:无错误
						OS_ERR_EVENT_TYPE:pevent不是指向mutex类型的指针
						OS_ERR_PEVENT_NULL:pevent为空指针
						OS_ERR_PEND_ISR:在中断服务子程序中调用
						OS_ERR_PIP_LOWER:正在使用mutex的任务优先级高于PIP。
* Returns    : == OS_TRUE    if the resource is available, the mutual exclusion semaphore is acquired
*              == OS_FALSE   a) if the resource is not available
*                            b) you didn't pass a pointer to a mutual exclusion semaphore
*                            c) you called this function from an ISR
*返回值:	==OS_TRUE:资源可以获得,互斥型信号量可以获得
			==OS_FALSE:a)无法获得资源
						b)没有指向互斥型信号量的指针
						c)从中断服务子程序中调用该功能
* Warning(s) : This function CANNOT be called from an ISR because mutual exclusion semaphores are
*              intended to be used by tasks only.
警告:该功能不能从中断中调用,因为互斥型信号量只能被任务调用。
*********************************************************************************************************
*/

#if OS_MUTEX_ACCEPT_EN > 0u
BOOLEAN  OSMutexAccept (OS_EVENT  *pevent,
                        INT8U     *perr)
{
    INT8U      pip;                       /* Priority Inheritance Priority (PIP)优先级继承优先级*/
	#if OS_CRITICAL_METHOD == 3u          /*中断类型被设置为类型3*/
		OS_CPU_SR  cpu_sr = 0u;
	#endif

	#ifdef OS_SAFETY_CRITICAL	/*安全中断*/
		if (perr == (INT8U *)0) {
			OS_SAFETY_CRITICAL_EXCEPTION();
		}
	#endif

	#if OS_ARG_CHK_EN > 0u		/*参数检查*/
		if (pevent == (OS_EVENT *)0) {                    
			*perr = OS_ERR_PEVENT_NULL;
			return (OS_FALSE);
		}
	#endif
    if (pevent->OSEventType != OS_EVENT_TYPE_MUTEX)/*有效化事件控制块类型*/
	{ 
        *perr = OS_ERR_EVENT_TYPE;
        return (OS_FALSE);
    }
    if (OSIntNesting > 0u)		/*判断是否从中断服务子程序中调用*/
	{                          
        *perr = OS_ERR_PEND_ISR;
        return (OS_FALSE);
    }
    OS_ENTER_CRITICAL();		/*进入中断*/
    pip = (INT8U)(pevent->OSEventCnt >> 8u);           /* 从mutex中获得PIP,pip存放在OSEventCnt的高八位中*/
    if ((pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8) == OS_MUTEX_AVAILABLE)/*/获得Mutex的值(0或1),OSEventCnt相与0x00ff后判断。OSEventCnt低8为0xff*/
	{
        pevent->OSEventCnt &= OS_MUTEX_KEEP_UPPER_8;   /*如果Mutex(高8位PIP)有效,将PIP保存到OSEventCnt的高8位(相与0xffoo)*/
        pevent->OSEventCnt |= OSTCBCur->OSTCBPrio;     /*把该任务的优先级写到OSEventCnt的低8位(相或OSTCBPrio)*/
        pevent->OSEventPtr  = (void *)OSTCBCur;        /*将Mutex的事件控制块ECB链接到该任务的任务控制块*/
        if (OSTCBCur->OSTCBPrio <= pip)			/*如果当前TCB的优先级数值不大于pip,即优先级高*/
		{        
            OS_EXIT_CRITICAL();                        /*退出中断*/
            *perr = OS_ERR_PIP_LOWER;			/*将错误类型设置为OS_ERR_PIP_LOWER,无法执行该任务*/
        } 
		else			/*如果当前TCB的优先级小于pip*/
		{	
            OS_EXIT_CRITICAL();	/*退出中断*/
            *perr = OS_ERR_NONE;/*成功调用该函数*/
        }
        return (OS_TRUE);/*检查状态,可以获得互斥型信号量*/
    }
    OS_EXIT_CRITICAL();/*退出中断*/
    *perr = OS_ERR_NONE;/*将错误类型设置为无错误*/
    return (OS_FALSE);	/*检查状态后确认不可以获得互斥型信号量*/
}
#

要注意该函数返回的是一个布尔值,表示能否获得互斥量。

在这个函数中,需要对下面几行进行解释:

 pip = (INT8U)(pevent->OSEventCnt >> 8u);           /* 从mutex中获得PIP,pip存放在OSEventCnt的高八位中*/
 if ((pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8) == OS_MUTEX_AVAILABLE)

pip是priority inheritance priority,优先级继承优先级。对于互斥型信号量,可能存在很多任务争夺一个的情况,此时,可能发生优先级反转现象(可以参考之前文章OS_CORE.C(6),点击打开链接)。pip就是为了防止优先级反转设置的。简单来说,如果当前任务优先级比继承优先级低,不会反转,不需要pip。如果比继承优先级高,会反转,那么将当前任务优先级设置为pip,这样就不会发生反转了。

OSEventCnt的低8位存放的是OS_MUTEX_AVAILABLE,如果if判断后检查结果仍为OS_MUTEX_AVAILABLE,则说明互斥锁没有被占用,这时候就要保存当前运行任务的优先级到OSEventCnt的低8位中,语句为:

pevent->OSEventCnt |= OSTCBCur->OSTCBPrio; 

然后比较一下当前任务的优先级是否比创建时的继承优先级低(优先级值大),如果当前任务的优先级比继承优先级高(数值小),则返回错误,语句为:

if (OSTCBCur->OSTCBPrio <= pip)        /*如果当前TCB的优先级数值不大于pip,即优先级高*/
		{        
            OS_EXIT_CRITICAL();       /*退出中断*/
            *perr = OS_ERR_PIP_LOWER;/*将错误类型设置为OS_ERR_PIP_LOWER,无法执行该任务*/
        } 

因为继承优先级是为了防止优先级翻转而设定,如果当前任务优先级比继承优先级低则不需要担心优先级反转,则返回正确值。


创建互斥型信号量OS_EVENT *OSMutexCreate(INT8U prio,INT8U *perr):

/*$PAGE*/
/*2018/2/19
*********************************************************************************************************
*                                  CREATE A MUTUAL EXCLUSION SEMAPHORE
*									创建互斥型信号量
* Description: This function creates a mutual exclusion semaphore.
*描述:该功能用来新建互斥型信号量。
* Arguments  : prio          is the priority to use when accessing the mutual exclusion semaphore.  In
*                            other words, when the semaphore is acquired and a higher priority task
*                            attempts to obtain the semaphore then the priority of the task owning the
*                            semaphore is raised to this priority.  It is assumed that you will specify
*                            a priority that is LOWER in value than ANY of the tasks competing for the
*                            mutex.
*参数:				--prio:获得互斥型信号量的任务的优先级。
				换句话说,当有任务已经获得了信号量,但是更高优先级任务尝试获得该信号量时,
				占有信号量的任务将其优先级提高到高优先级。。此时任务的优先级比所有竞争mutex的任务优先级都高。
*              perr          is a pointer to an error code which will be returned to your application:
*                               OS_ERR_NONE         if the call was successful.
*                               OS_ERR_CREATE_ISR   if you attempted to create a MUTEX from an ISR
*                               OS_ERR_PRIO_EXIST   if a task at the priority inheritance priority
*                                                   already exist.
*                               OS_ERR_PEVENT_NULL  No more event control blocks available.
*                               OS_ERR_PRIO_INVALID if the priority you specify is higher that the
*                                                   maximum allowed (i.e. > OS_LOWEST_PRIO)
*							--perr:指向错误码的指针,取值如下:
								OS_ERR_NONE:无错误;
								OS_ERR_CREATE_ISR:从中断服务子程序中创建mutex
								OS_ERR_PRIO_EXIST:优先级为PIP的任务已经存在;
								OS_ERR_PEVENT_NULL:没有可用的事件控制块
								OS_ERR_PRIO_INVALID:定义的优先级非法,其值大于OS_LOWEST_PRIO.
* Returns    : != (void *)0  is a pointer to the event control clock (OS_EVENT) associated with the
*                            created mutex.
*              == (void *)0  if an error is detected.
*返回值:	!=0	返回一个指针 ,该指针指向分配给mutex的事件控制块。
			==0 有错误,返回空指针。
* Note(s)    : 1) The LEAST significant 8 bits of '.OSEventCnt' are used to hold the priority number
*                 of the task owning the mutex or 0xFF if no task owns the mutex.
*
*              2) The MOST  significant 8 bits of '.OSEventCnt' are used to hold the priority number
*                 to use to reduce priority inversion.
注释:	1)OSEventCnt的低八位用来表示拥有互斥量任务的优先级,如果没有任务拥有该互斥量,低八位为0xff
		2)OSEventCnt的高八位存放的优先级是用来减少优先级反转
*********************************************************************************************************
*/

OS_EVENT  *OSMutexCreate (INT8U   prio,
                          INT8U  *perr)
{
    OS_EVENT  *pevent;/*指向事件控制块的指针*/
mutex首先会检查传入优先级的任务的TCB有没有已经被使用,如果传入优先级已经被使用,则创建失败,返回错误,如果参数传入的优先级的TCB没有被占用,则设置为reserved,保证该TCB不会被其他任务使用。语句如下:
 OS_ENTER_CRITICAL();/*进入中断*/
    if (OSTCBPrioTbl[prio] != (OS_TCB *)0) /*检查传入优先级的任务的TCB是否被占用*/
	{               
        OS_EXIT_CRITICAL();                              
        *perr = OS_ERR_PRIO_EXIST;                       
        return ((OS_EVENT *)0);
    }
    OSTCBPrioTbl[prio] = OS_TCB_RESERVED;/*如果没有被占用,则设置为reserved*/

再检查是否有空闲的事件控制块,如果没有返回空指针,如果有,进行相关操作:

 pevent = OSEventFreeList;/*得到一个事件控制块 */
    if (pevent == (OS_EVENT *)0) /*如果没有空闲的事件控制块*/
	{                
        OSTCBPrioTbl[prio] = (OS_TCB *)0; /*将优先级表对应的位置清0 */
        OS_EXIT_CRITICAL();/*退出中断*/
        *perr = OS_ERR_PEVENT_NULL; /*将错误码设置为OS_ERR_PEVENT_NULL*/
        return (pevent);/*返回一个空指针*/
    }
	/*如果有空闲的事件控制块*/
    OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr;   /*调整事件空闲列表*/
    OS_EXIT_CRITICAL();/*退出中断*/
    pevent->OSEventType = OS_EVENT_TYPE_MUTEX;/*将事件类型设置为mutex*/
    pevent->OSEventCnt = (INT16U)((INT16U)prio << 8u) | OS_MUTEX_AVAILABLE;
    pevent->OSEventPtr = (void *)0; /*没有任务使用mutex*/
	#if OS_EVENT_NAME_EN > 0u
		pevent->OSEventName    = (INT8U *)(void *)"?";/*如果事件有名称,设置为未命名*/
	#endif
    OS_EventWaitListInit(pevent);/*事件等待列表初始化*/

这几行语句中解释一下:

 pevent->OSEventCnt = (INT16U)((INT16U)prio << 8u) | OS_MUTEX_AVAILABLE;

prio左移8位,将优先级存放在OSEventCnt中的高八位,再与OS_MUTEX_AVAILABLE进行或运算,即OSEventCnt的低八位00与OS_MUTEX_AVAILABLE进行运算,如果运算结果为全ff,则说明可以获得mutex,否则不可以获得。


删除信号量OS_EVENT  *OSMutexDel (OS_EVENT  *pevent,INT8U  opt,INT8U  *perr):(部分代码)

/*$PAGE*/
/*2018/2/19
*********************************************************************************************************
*                                          DELETE A MUTEX
*					   删除信号量
* Description: This function deletes a mutual exclusion semaphore and readies all tasks pending on the it.
*描述:该功能用来删除互斥量并且将所有的任务就绪
* Arguments  : pevent        is a pointer to the event control block associated with the desired mutex.
*参数:						--pevent:指向事件控制块的指针
*              opt           determines delete options as follows:
*                            opt == OS_DEL_NO_PEND   Delete mutex ONLY if no task pending
*                            opt == OS_DEL_ALWAYS    Deletes the mutex even if tasks are waiting.
*                                                    In this case, all the tasks pending will be readied.
*	--opt:两种删除方式:
		OS_DEL_NO_PEND:只有没有任务挂起时才能删除该互斥量;
		OS_DEL_ALWAYS:无论有没有挂起都删除,这种情况下,所有的任务都从挂起状态转化为就绪态。
*              perr          is a pointer to an error code that can contain one of the following values:
*                            OS_ERR_NONE             The call was successful and the mutex was deleted
*                            OS_ERR_DEL_ISR          If you attempted to delete the MUTEX from an ISR
*                            OS_ERR_INVALID_OPT      An invalid option was specified
*                            OS_ERR_TASK_WAITING     One or more tasks were waiting on the mutex
*                            OS_ERR_EVENT_TYPE       If you didn't pass a pointer to a mutex
*                            OS_ERR_PEVENT_NULL      If 'pevent' is a NULL pointer.
*	--perr:指向错误码的指针,可以有以下值:
				OS_ERR_NONE:无错误;
				OS_ERR_DEL_ISR:从中断服务子程序删除;
				OS_ERR_INVALID_OPT:opt为无效值;
				OS_ERR_TASK_WAITING:一个或者多个任务正在等待mutex;
				OS_ERR_EVENT_TYPE:没有指向mutex的指针;
				OS_ERR_PEVENT_NULL:pevent为空指针。
* Returns    : pevent        upon error
*              (OS_EVENT *)0 if the mutex was successfully deleted.
*返回值:如果mutex已经删除,则返回空指针;如果mutex没能删除,则返回pevent
* Note(s)    : 1) This function must be used with care.  Tasks that would normally expect the presence of
*                 the mutex MUST check the return code of OSMutexPend().
*注释:		1)该功能必须小心使用,因为其他任务可能会用到mutex。需要该信号量的任务必须检测OSMutexPend()的返回值。
*              2) This call can potentially disable interrupts for a long time.  The interrupt disable
*                 time is directly proportional to the number of tasks waiting on the mutex.
*		2)调用该函数时不能被中断。中断时间与等待该信号量的任务数量有关。
*              3) Because ALL tasks pending on the mutex will be readied, you MUST be careful because the
*                 resource(s) will no longer be guarded by the mutex.
*		3)因为在删除信号量之后,所有挂起的任务都自动转为就绪态,所以你必须小心,因为资源此时不再被mutex控制。
*              4) IMPORTANT: In the 'OS_DEL_ALWAYS' case, we assume that the owner of the Mutex (if there
*                            is one) is ready-to-run and is thus NOT pending on another kernel object or
*                            has delayed itself.  In other words, if a task owns the mutex being deleted,
*                            that task will be made ready-to-run at its original priority.
                4)重点:在OS_DEL_ALWAYS情况下,我们任务mutex的拥有者(假设只有一个)已经准备运行,
                并且不在其他内核对象中等待(挂起)或者自身延迟。换句话说,如果拥有互斥量的任务被删除了,该任务将会以之前原始的优先级存在。
*********************************************************************************************************
*/

#if OS_MUTEX_DEL_EN > 0u
OS_EVENT  *OSMutexDel (OS_EVENT  *pevent,
                       INT8U      opt,
                       INT8U     *perr)
{
    BOOLEAN    tasks_waiting;/*布尔值看是否有任务正在等待*/
    OS_EVENT  *pevent_return;/*返回值*/
    INT8U      pip; /*继承优先级*/
    INT8U      prio;/*原始优先级*/
    OS_TCB    *ptcb;/*指向TCB的指针*/

先检查是否有任务正在等待信号量。然后选择删除方式,进行删除。

    OS_ENTER_CRITICAL();/*进入中断*/
    if (pevent->OSEventGrp != 0u)/*检查是否有任务正在等待该信号量*/
	{              
        tasks_waiting = OS_TRUE;  
    } 
	else
	{
        tasks_waiting = OS_FALSE;  
    }
    switch (opt) /*选择删除方式*/
	{
        case OS_DEL_NO_PEND:/*没有等待信号量的任务时才删除*/
             if (tasks_waiting == OS_FALSE) /*没有任务等待*/
			 {
				#if OS_EVENT_NAME_EN > 0u
					pevent->OSEventName = (INT8U *)(void *)"?";/*如果有名称,将名称设置为未命名*/
				#endif
                 pip = (INT8U)(pevent->OSEventCnt >> 8u);/*将OSEventCnt的高八位赋值给pip,获得继承优先级*/
                 OSTCBPrioTbl[pip]   = (OS_TCB *)0; /*在优先级表中释放pip所在的tcb */
                 pevent->OSEventType = OS_EVENT_TYPE_UNUSED;/*将事件类型设置为未使用类型*/
                 pevent->OSEventPtr  = OSEventFreeList;/*将事件控制块返回给空闲事件列表 */
                 pevent->OSEventCnt  = 0u;
                 OSEventFreeList  = pevent;/*更新空闲事件列表*/
                 OS_EXIT_CRITICAL();/*退出中断*/
                 *perr = OS_ERR_NONE;
                 pevent_return  = (OS_EVENT *)0;/*信号量已经被删除,返回空指针*/
             } 
			 else/*有任务等待*/
			 {
                 OS_EXIT_CRITICAL();/*退出中断*/
                 *perr = OS_ERR_TASK_WAITING;
                 pevent_return = pevent;
             }
             break;

        case OS_DEL_ALWAYS:/*无论怎样都删除*/
             pip  = (INT8U)(pevent->OSEventCnt >> 8u); /*得到继承优先级*/
             prio = (INT8U)(pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8);/*得到原始的优先级*/
             ptcb = (OS_TCB *)pevent->OSEventPtr;/*指向TCB的指针*/
             if (ptcb != (OS_TCB *)0)/*如果有空闲的TCB*/
			 {                    /* See if any task owns the mutex           */
                 if (ptcb->OSTCBPrio == pip) /*看原始的优先级是否改变了,即是否解决过优先级反转*/
				 {           
                     OSMutex_RdyAtPrio(ptcb, prio); /*原始优先级改变,将其存储。待任务完成后恢复*/
                 }
             }
             while (pevent->OSEventGrp != 0u) /*如果有事件组,即有任务在等待该信号量*/
			 {           
                 (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_MUTEX, OS_STAT_PEND_OK);/*将所有任务转为就绪态*/
             }
			#if OS_EVENT_NAME_EN > 0u
				 pevent->OSEventName = (INT8U *)(void *)"?";/*将事件名称设置为未命名*/
			#endif
             pip = (INT8U)(pevent->OSEventCnt >> 8u);/*获得pip*/
             OSTCBPrioTbl[pip]   = (OS_TCB *)0;    
             pevent->OSEventType = OS_EVENT_TYPE_UNUSED;
             pevent->OSEventPtr  = OSEventFreeList;    
             pevent->OSEventCnt  = 0u;
             OSEventFreeList     = pevent;             
             OS_EXIT_CRITICAL();
             if (tasks_waiting == OS_TRUE) /*如果有任务等待*/
			 {         
                 OS_Sched();/*在就绪任务中找到优先级最高的任务进行调度*/
             }
             *perr = OS_ERR_NONE;
             pevent_return = (OS_EVENT *)0;
             break;

        default:/*其他情况*/
             OS_EXIT_CRITICAL();
             *perr = OS_ERR_INVALID_OPT;/*选择无效*/
             pevent_return = pevent;
             break;
    }
    return (pevent_return);
}
#endif

该函数较为简单,不赘述。


等待互斥型信号量void  OSMutexPend (OS_EVENT  *pevent,INT32U timeout,INT8U  *perr):

/*$PAGE*/
/*2018/2/19
*********************************************************************************************************
*                                  PEND ON MUTUAL EXCLUSION SEMAPHORE
*									等待互斥型信号量
* Description: This function waits for a mutual exclusion semaphore.
*描述:该功能用来等待互斥型信号量
* Arguments  : pevent        is a pointer to the event control block associated with the desired mutex.
*参数:		--pevent:指向事件控制块的指针
*              timeout       is an optional timeout period (in clock ticks).  If non-zero, your task will
*                            wait for the resource up to the amount of time specified by this argument.
*                            If you specify 0, however, your task will wait forever at the specified
*                            mutex or, until the resource becomes available.
*			--timeout:可选择的时间超时片。如果不为0,任务将等待资源直到时间到了该参数规定的时间。超时后,将不再等待。
				如果为0,任务将永远处于等待,直到资源可以获得。
*              perr          is a pointer to where an error message will be deposited.  Possible error
*                            messages are:
*                               OS_ERR_NONE        The call was successful and your task owns the mutex
*                               OS_ERR_TIMEOUT     The mutex was not available within the specified 'timeout'.
*                               OS_ERR_PEND_ABORT  The wait on the mutex was aborted.
*                               OS_ERR_EVENT_TYPE  If you didn't pass a pointer to a mutex
*                               OS_ERR_PEVENT_NULL 'pevent' is a NULL pointer
*                               OS_ERR_PEND_ISR    If you called this function from an ISR and the result
*                                                  would lead to a suspension.
*                               OS_ERR_PIP_LOWER   If the priority of the task that owns the Mutex is
*                                                  HIGHER (i.e. a lower number) than the PIP.  This error
*                                                  indicates that you did not set the PIP higher (lower
*                                                  number) than ALL the tasks that compete for the Mutex.
*                                                  Unfortunately, this is something that could not be
*                                                  detected when the Mutex is created because we don't know
*                                                  what tasks will be using the Mutex.
*                               OS_ERR_PEND_LOCKED If you called this function when the scheduler is locked
*				--perr:指向错误信息的指针。有可能的错误信息如下:
					OS_ERR_NONE:无错误;
					OS_ERR_TIMEOUT:超时错误;
					OS_ERR_PEND_ABORT:等待信号量的任务被取消;
					OS_ERR_EVENT_TYPE:没有指向mutex的指针;
					OS_ERR_PEVENT_NULL:pevent是空指针;
					OS_ERR_PEND_ISR:从中断服务子程序中调用该功能;
					OS_ERR_PIP_LOWER:当前任务优先级比pip高。
* Returns    : none
*返回值:无
* Note(s)    : 1) The task that owns the Mutex MUST NOT pend on any other event while it owns the mutex.
*注释:1)拥有信号量的任务不能再其他事件中处于挂起状态。
*              2) You MUST NOT change the priority of the task that owns the mutex
		2)不能改变拥有mutex的任务的优先级。
*********************************************************************************************************
*/

void  OSMutexPend (OS_EVENT  *pevent,
                   INT32U     timeout,
                   INT8U     *perr)
{
    INT8U      pip;   /*继承优先级*/
    INT8U      mprio; /*拥有信号量的任务的优先级*/
    BOOLEAN    rdy;    /*标志任务是否就绪*/
    OS_TCB    *ptcb;/*指向TCB的指针*/
    OS_EVENT  *pevent2;/*指向事件控制块的指针*/
    INT8U      y;
检测互斥量是否为可获得的。如果可获得,则判断当前任务的优先级和pip优先级高低。如果不可获得,需要判断两次:第一判断拥有互斥量任务的优先级与pip优先级高低;第二判断拥有互斥量任务的优先级与当前任务优先级的高低。

如果检测互斥量是可获得的,表示没有任务使用互斥锁,这时候运行该函数的任务将获得互斥锁并退出。如果不是可获得的,表示一个新的任务在尝试获得互斥锁,并且互斥锁已经被占用时的操作。代码如下:

OS_ENTER_CRITICAL();/*进入中断*/
    pip = (INT8U)(pevent->OSEventCnt >> 8u);/*获得PIP,继承优先级*/
     /*检测互斥量是否为可获得的*/
    if ((INT8U)(pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8) == OS_MUTEX_AVAILABLE)
	{
        pevent->OSEventCnt &= OS_MUTEX_KEEP_UPPER_8;/*修改高8位的数据,这个时候高8位数据不变,还是表示继承优先级,低8位清零*/
        pevent->OSEventCnt |= OSTCBCur->OSTCBPrio;/*将申请任务的优先级保存在低8位之中。低八位不可能全部都为零,
						所以依旧可以表示信号量是否被占用*/
        pevent->OSEventPtr  = (void *)OSTCBCur;   /*OSEventPtr指针指向任务控制块 */
        if (OSTCBCur->OSTCBPrio <= pip)/*如果当前任务的优先级比pip优先级高*/
		{               
            OS_EXIT_CRITICAL();                         
            *perr = OS_ERR_PIP_LOWER;
        }
		else		/*当前任务优先级低*/
		{
            OS_EXIT_CRITICAL();
            *perr = OS_ERR_NONE;
        }
        return;
    }

上面这一段代码是互斥量为可获得的。

下面这段代码为互斥量不可获得的:

/*如果该互斥量不可获得*/
    mprio = (INT8U)(pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8);  /*得到拥有互斥量的任务的优先级*/
    ptcb  = (OS_TCB *)(pevent->OSEventPtr); /* 指针指向拥有互斥量的TCB*/
	
    if (ptcb->OSTCBPrio > pip)  /*获得互斥量的任务的优先级比pip优先级低*/
	{   
        if (mprio > OSTCBCur->OSTCBPrio)/*获得互斥量任务的优先级比当前任务优先级低*/
		{
            y = ptcb->OSTCBY;
            if ((OSRdyTbl[y] & ptcb->OSTCBBitX) != 0u) /*看拥有互斥量的任务是否就绪*/
			{       
                OSRdyTbl[y] &= (OS_PRIO)~ptcb->OSTCBBitX;/*如果就绪,将其从就绪表中移除*/
                if (OSRdyTbl[y] == 0u)
				{                        
                    OSRdyGrp &= (OS_PRIO)~ptcb->OSTCBBitY;/*从就绪组中移除*/
                }
                rdy = OS_TRUE;/*将就绪标志设置为true*/
            } 
			else/*拥有互斥量的任务没就绪*/
			{
                pevent2 = ptcb->OSTCBEventPtr;/*pevent2指向拥有互斥量的事件*/
                if (pevent2 != (OS_EVENT *)0) /*如果该事件不为空,将其从事件表中删除*/
				{           
                    y = ptcb->OSTCBY;
                    pevent2->OSEventTbl[y] &= (OS_PRIO)~ptcb->OSTCBBitX;
                    if (pevent2->OSEventTbl[y] == 0u) {
                        pevent2->OSEventGrp &= (OS_PRIO)~ptcb->OSTCBBitY;
                    }
                }
                rdy = OS_FALSE; /*将其就绪状态设置为false*/
            }
            ptcb->OSTCBPrio = pip;  /*将有互斥量的任务的优先级改为pip */
			#if OS_LOWEST_PRIO <= 63u
			ptcb->OSTCBY    = (INT8U)( ptcb->OSTCBPrio >> 3u);
			ptcb->OSTCBX    = (INT8U)( ptcb->OSTCBPrio & 0x07u);
			#else
			ptcb->OSTCBY    = (INT8U)((INT8U)(ptcb->OSTCBPrio >> 4u) & 0xFFu);
			ptcb->OSTCBX    = (INT8U)( ptcb->OSTCBPrio & 0x0Fu);
			#endif
            ptcb->OSTCBBitY = (OS_PRIO)(1uL << ptcb->OSTCBY);
            ptcb->OSTCBBitX = (OS_PRIO)(1uL << ptcb->OSTCBX);

			
            if (rdy == OS_TRUE)/*就绪状态为true*/
			{/*如果该任务处于就绪态,那么这个任务已不是处在它原来优先级上的就绪态*/           
                OSRdyGrp |= ptcb->OSTCBBitY;
                OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
            } 
	    else/*就绪状态为false*/
	    {
                pevent2 = ptcb->OSTCBEventPtr;
                if (pevent2 != (OS_EVENT *)0) /*将事件控制块添加到事件等待列表中*/
		{      
                    pevent2->OSEventGrp |= ptcb->OSTCBBitY;
                    pevent2->OSEventTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
                }
            }
            OSTCBPrioTbl[pip] = ptcb;/*使占用mutex的任务以PIP优先级进入就绪态*/
        }
    }

上述过程如下图所示:


此外还想多说一句:

 OSTCBPrioTbl[pip] = ptcb;/*使占用mutex的任务以PIP优先级进入就绪态*/

下面这行语句为什么一定要让任务以pip优先级进入就绪态?

个人理解是:对互斥量的操作中,pip的设置是为了防止优先级反转。在操作时,要时刻保持任务是以最高优先级存在,否则就可能发生反转。

如果互斥量不可获取,进行完上面的判断和操作后,后续的操作为:

    OSTCBCur->OSTCBStat |= OS_STAT_MUTEX;  /*无法获得互斥量,将该任务挂起*/
    OSTCBCur->OSTCBStatPend  = OS_STAT_PEND_OK;/*挂起状态设置为OS_STAT_PEND_OK*/
    OSTCBCur->OSTCBDly = timeout;
    OS_EventTaskWait(pevent); /*任务处于阻塞状态,知道事件发生或超时*/ 
    OS_EXIT_CRITICAL();/*退出中断*/
    OS_Sched(); /* 找到就绪的最高优先级任务进行调度*/
    OS_ENTER_CRITICAL();/*进入中断*/
    switch (OSTCBCur->OSTCBStatPend)/*看挂起的原因是什么?超时还是任务被取消*/
	{       
        case OS_STAT_PEND_OK:
             *perr = OS_ERR_NONE;
             break;

        case OS_STAT_PEND_ABORT:
             *perr = OS_ERR_PEND_ABORT;      
             break;
        case OS_STAT_PEND_TO:
        default:
             OS_EventTaskRemove(OSTCBCur, pevent);
             *perr = OS_ERR_TIMEOUT; 
             break;
    }
    OSTCBCur->OSTCBStat =  OS_STAT_RDY;      /*将任务状态设置为就绪态*/
    OSTCBCur->OSTCBStatPend =  OS_STAT_PEND_OK;  /*清除挂起状态 */
    OSTCBCur->OSTCBEventPtr = (OS_EVENT  *)0;    /* 清除事件指针*/
#if (OS_EVENT_MULTI_EN > 0u)
    OSTCBCur->OSTCBEventMultiPtr = (OS_EVENT **)0;
#endif
    OS_EXIT_CRITICAL();/*退出中断*/
}

释放一个互斥型信号量OSMutexPost (OS_EVENT *pevent):

/*$PAGE*/
/*2018/2/19
*********************************************************************************************************
*                                  POST TO A MUTUAL EXCLUSION SEMAPHORE
*									释放一个互斥型信号量
* Description: This function signals a mutual exclusion semaphore
*描述:调用OSMutexPost()可以发出mutex
* Arguments  : pevent              is a pointer to the event control block associated with the desired mutex.
*参数:			--pevent:指向有互斥量的事件控制块的指针。
* Returns    : OS_ERR_NONE             The call was successful and the mutex was signaled.
*              OS_ERR_EVENT_TYPE       If you didn't pass a pointer to a mutex
*              OS_ERR_PEVENT_NULL      'pevent' is a NULL pointer
*              OS_ERR_POST_ISR         Attempted to post from an ISR (not valid for MUTEXes)
*              OS_ERR_NOT_MUTEX_OWNER  The task that did the post is NOT the owner of the MUTEX.
*              OS_ERR_PIP_LOWER        If the priority of the new task that owns the Mutex is
*                                      HIGHER (i.e. a lower number) than the PIP.  This error
*                                      indicates that you did not set the PIP higher (lower
*                                      number) than ALL the tasks that compete for the Mutex.
*                                      Unfortunately, this is something that could not be
*                                      detected when the Mutex is created because we don't know
*                                      what tasks will be using the Mutex.
	返回值:OS_ERR_NONE:调用成功,发出mutex;
			OS_ERR_EVENT_TYPE:没有指向mutex的指针;
			OS_ERR_PEVENT_NULL:pevent为空指针;
			OS_ERR_POST_ISR:从中断服务子程序中调用;
			OS_ERR_NOT_MUTEX_OWNER:发出信号的任务没有占用互斥量。
			OS_ERR_PIP_LOWER:拥有互斥量的任务的优先级比pip高。
*********************************************************************************************************
*/

INT8U  OSMutexPost (OS_EVENT *pevent)
{
    INT8U      pip;/*继承优先级*/
    INT8U      prio;
	#if OS_CRITICAL_METHOD == 3u 
		OS_CPU_SR  cpu_sr = 0u;
	#endif

    if (OSIntNesting > 0u)
	{                      
        return (OS_ERR_POST_ISR);    
    }
	#if OS_ARG_CHK_EN > 0u
		if (pevent == (OS_EVENT *)0) {                 
			return (OS_ERR_PEVENT_NULL);
		}
	#endif
    if (pevent->OSEventType != OS_EVENT_TYPE_MUTEX) { 
        return (OS_ERR_EVENT_TYPE);
    }

    OS_ENTER_CRITICAL();/*进入中断*/
    pip = (INT8U)(pevent->OSEventCnt >> 8u); /*获取pip*/
    prio = (INT8U)(pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8);/*获取拥有互斥量的任务的原始优先级*/
    if (OSTCBCur != (OS_TCB *)pevent->OSEventPtr)/*当前任务没有占有互斥量*/
	{  
        OS_EXIT_CRITICAL();/*退出中断*/
        return (OS_ERR_NOT_MUTEX_OWNER);//发出mutex的任务实际上并不占用mutex
    }
    if (OSTCBCur->OSTCBPrio == pip) /*当前任务优先级是pip,不需要提高优先级*/
	{               
        OSMutex_RdyAtPrio(OSTCBCur, prio); /*保存任务原始优先级,任务完成后进行恢复*/
    }
    OSTCBPrioTbl[pip] = OS_TCB_RESERVED;	/*将pip对应在优先级表上的值设为reserved*/
    if (pevent->OSEventGrp != 0u) /*如果有任务正在等待互斥量,将最高优先级任务设置为就绪态*/
	{           
        prio = OS_EventTaskRdy(pevent, (void *)0, OS_STAT_MUTEX, OS_STAT_PEND_OK);/*转为就绪态任务的优先级*/
        pevent->OSEventCnt &= OS_MUTEX_KEEP_UPPER_8;  /*新占用mutex的任务保存高8位(PIP) */
        pevent->OSEventCnt |= prio;/*将新任务优先级存放在低八位*/
        pevent->OSEventPtr = OSTCBPrioTbl[prio];/*指针指向新任务的TCB*/
        if (prio <= pip) /*当前任务比pip优先级高*/
		{               
            OS_EXIT_CRITICAL();/*退出中断*/  
            OS_Sched();/*找到最高优先级任务进行调度*/
            return (OS_ERR_PIP_LOWER);/*返回错误值*/
        } 
		else/*当前任务比pip优先级低*/
		{
            OS_EXIT_CRITICAL();/*退出中断*/
            OS_Sched();/*找到最高优先级任务进行调度*/
            return (OS_ERR_NONE);/*返回无错*/
        }
    }
	/*如果没有任务等待互斥量*/
    pevent->OSEventCnt |= OS_MUTEX_AVAILABLE; /*互斥量是可获得的 */
    pevent->OSEventPtr  = (void *)0;
    OS_EXIT_CRITICAL();
    return (OS_ERR_NONE);
}

该函数实际上是通知是否mutex为空闲的。如果当前的任务没有占用该互斥量,返回OS_ERR_NOT_MUTEX_OWNER,即发出mutex的任务不占用互斥量。如果当前任务占用互斥量,看看是否有任务正在等待这个互斥量。如果有任务等待,那么在当前任务完成之前,将等待列表中的优先级最高的任务转为就绪态。等当前任务完成,该任务就可以执行了。如果没有任务等待该互斥量,就只简单的发出“该互斥量是可获得的”信号即可。


查询互斥量信息OSMutexQuery (OS_EVENT  *pevent, OS_MUTEX_DATA  *p_mutex_data):

/*$PAGE*/
/*2018/2/19
*********************************************************************************************************
*                                     QUERY A MUTUAL EXCLUSION SEMAPHORE
*										查询互斥量
* Description: This function obtains information about a mutex
*描述:该功能获得关于互斥量的信息。
* Arguments  : pevent          is a pointer to the event control block associated with the desired mutex
*参数:		--pevent:指向需要互斥量的事件控制块的指针
*              p_mutex_data    is a pointer to a structure that will contain information about the mutex
*			-- p_mutex_data :指向结构体的指针,该结构体包含互斥量的信息
* Returns    : OS_ERR_NONE          The call was successful and the message was sent
*              OS_ERR_QUERY_ISR     If you called this function from an ISR
*              OS_ERR_PEVENT_NULL   If 'pevent'       is a NULL pointer
*              OS_ERR_PDATA_NULL    If 'p_mutex_data' is a NULL pointer
*              OS_ERR_EVENT_TYPE    If you are attempting to obtain data from a non mutex.
	返回值:OS_ERR_NONE:调用成功,消息也被发出。
			OS_ERR_QUERY_ISR:从中断服务子程序中调用该函数;
			OS_ERR_PEVENT_NULL:pevent为空指针;
			OS_ERR_PDATA_NULL:p_mutex_data为空指针;
			OS_ERR_EVENT_TYPE:获得消息对象错误。
*********************************************************************************************************
*/

#if OS_MUTEX_QUERY_EN > 0u
INT8U  OSMutexQuery (OS_EVENT       *pevent,
                     OS_MUTEX_DATA  *p_mutex_data)
{
    INT8U       i;
    OS_PRIO    *psrc;
    OS_PRIO    *pdest;
    OS_ENTER_CRITICAL();/*进入中断*/
    p_mutex_data->OSMutexPIP  = (INT8U)(pevent->OSEventCnt >> 8u);/*获取pip*/
    p_mutex_data->OSOwnerPrio = (INT8U)(pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8);/*获取拥有互斥量的任务的优先级*/
    if (p_mutex_data->OSOwnerPrio == 0xFFu) /*如果占用mutex任务的优先级为255时*/
	{
        p_mutex_data->OSValue = OS_TRUE; /*当前mutex的值。1表示可以使用。*/
    } 
	else
	{
        p_mutex_data->OSValue = OS_FALSE;//当前mutex的值。0表示不能使用
    }
	/*将事件(互斥型信号量)结构中的等待任务列表复制到pdata数据结构中*/
    p_mutex_data->OSEventGrp  = pevent->OSEventGrp; /*等待事件的任务组中的内容传送到状态数据结构中*/
    psrc = &pevent->OSEventTbl[0];/*保存pevent->OSEventTbl[0]对应的地址*/
    pdest = &p_mutex_data->OSEventTbl[0];/*保存pdata->OSEventTbl[0]对应的地址*/
    for (i = 0u; i < OS_EVENT_TBL_SIZE; i++) 
	{
        *pdest++ = *psrc++;/*地址指针继续下移一个类型地址,获取互斥型信号量的值*/
    }
    OS_EXIT_CRITICAL();/*退出中断*/
    return (OS_ERR_NONE);
}
#endif
将任务恢复到之前到优先级static  void  OSMutex_RdyAtPrio (OS_TCB  *ptcb,INT8U  prio):

该功能是将之前为了防止优先级反转而提高的任务的优先级恢复。


到此,OS_mutex.c文件就看完了。

这个文件重点是介绍信号量的获取、建立、删除、挂起等待、查询和释放(通知)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

os_mutex.c(全) 的相关文章

  • UCOSII中的任务切换原理介绍

    1 多任务的引入 之所以引入多任务 xff0c 主要在于提高程序运行的效率 多任务的过程 xff0c 能够有效地发挥交换式任务的运作效率 类似的 xff0c 由于一个任务里面也有瓶颈的地方 xff0c 为了把瓶颈的地方抠出来 xff0c 让
  • UCOSII学习---五、任务通信之信号量

    一 xff1a 信号量的理解 xff1a 信号量的本质是数据操作锁 xff0c 它本身不具有数据交换的功能 xff0c 而是通过控制其他的通信资源 xff08 文件 xff0c 外部设备 xff09 来实现进程间通信 xff0c 它本身只是
  • STM32上使用UCOSII--消息队列和信号量集

    有关UCOS任务的介绍 xff1a STM32上使用UCOSII 任务 有关UCOS信号量和邮箱的介绍 xff1a STM32上使用UCOSII 信号量和邮箱 一 消息队列 使用消息队列可以在任务之间传递多条消息 消息队列由三个部分组成 x
  • ucosii中消息队列、消息邮箱、信号量的区别

    1 用信号量进行行为同步时 xff0c 只能提供同步的时刻信息 xff0c 不能提供内容信息 若被控制方要求得到控制方的内容信息时 xff0c 可以使用消息邮箱或消息队列 2 但由于消息邮箱里只能存放一条消息 xff0c 所以使用消息邮箱进
  • ucosii消息队列学习

    近期在学习ucosii的内容使用的平台为STM32F103C8T6最小系统板 今日关于消息队列的使用遇到了一些问题 基本情况 xff1a 移植代码为正点原子ucosiii消息队列 信号量集和软件定时器例程 主要新建两个任务post task
  • UCOSII 消息队列、信号量集、软件定时器

    1 消息队列 xff1a 作用 xff1a 在任务之间传递多条信息 组成 xff1a 事件控制块 消息队列 消息 消息队列数据结构 队列控制块的结构定义 xff1a typedef struct os q struct os q OSQPt
  • Ucosii消息邮箱使用

    设置任务优先级 define LED TASK Prio 6 define LED1 TASK Prio 5 用到的UCOSII函数 消息邮箱创建函数 xff1a OS EVENT OSMboxCreate void msg 请求消息邮箱函
  • ucosii消息队列使用

    ucosii消息队列简介 ucosii的消息队列源码定义在os q c文件 xff1b 接口全部声明在ucos ii h xff0c 总共有如下接口 xff1a span class token keyword void span span
  • 基于UCOSII的RS485通信(STM32F107)

    一 实现效果 基于ucosii实时操作系统的RS485通信 xff0c 采用USART 43 DMA进行收发 xff0c 二 开发环境 开发工具 xff1a KEIL V5开发板 STM32f107RC采用方式 xff1a USART 43
  • UCOSII 使用笔记

    UCOS使用总结 1 UCOS 是抢占式系统 xff0c 换句话来说 xff0c 优先级高的能够被准时执行 xff0c 优先级低的很容易被高优先级抢占 xff0c 导致执行任务延迟 2 UCOS一般为64个优先级 xff0c 有些可以到25
  • 从零开始学习UCOSII操作系统4--任务管理

    从零开始学习UCOSII操作系统4 任务管理 1 重讲任务 1 任务可以是一个无限的循环 xff0c 也可以在一次执行完毕后被删除 这里需要注意的是 xff0c 任务的代码并不是真正的删除了 xff0c 而是UCOSII不再理会该任务代码
  • 从零开始学习UCOSII操作系统7--信号量

    从零开始学习UCOSII操作系统7 信号量 参考博客 xff1a 64 http blog csdn net gatiemehttps blog csdn net gatieme article details 21071379 前言 xf
  • 从零开始学习UCOSII操作系统15--总结篇

    从零开始学习UCOSII操作系统15 总结篇 前言 xff1a 在大学的时候 xff0c 我们班级上面都有很多人觉得学习UCOSII 包括UCOSIII 是没什么厉害的 xff0c 因为很多人都喜欢去学习Linux操作系统 xff0c 但是
  • 再读 ucosII源码(邵贝贝):任务之间的通讯与同步--邮箱

    邮箱简介 xff1a 邮箱是 C OS II中另一种通讯机制 xff0c 它可以使一个任务或者中断服务子程序向另一个任务发送一个指针型的变量 该指针指向一个包含了特定 消息 的数据结构 为了在 C OS II中使用邮箱 xff0c 必须将O
  • ucosII的书籍

  • UCOSII里面为什么调用OS_ENTER_CRITICAL()或OS_EXIT_CRITICAL()会出错,出错信息为:undeclared identifier `cpu_sr‘

    可以观察到OSTickISR Init 函数内部调用了OS ENTER CRITICAL 和OS EXIT CRITICAL 并且 1 该OSTickISR Init 函数所在的 C文件包含了includes h文件 include inc
  • stm32 ucos/ii移植,程序执行到OSStart()内部的OSStartHighRdy()语句时跑飞问题解决方法之一

    stm32 ucos ii移植 程序执行到OSStart 内部的OSStartHighRdy 语句时跑飞问题解决办法之一 网络上的一些解决办法 stm32程序遇到OSStartHang的问题解决方法总结 但并不适合我遇到的情况 我的情况是已
  • windows下的gcc使用

    文章目录 缘起 正文 安装gcc 使用gcc来编译c语言程序 直接编译生成 exe文件 在cmd里面使用gcc编译器编译c文件流程 利用gcc编译多个c语言源文件 第一步建立文件 编译文件 链接 运行 gcc基本参数 参考文献 缘起 在wi
  • os_mutex.c(全)

    无等待地获取互斥型信号量 OSMutexAccept OS EVENT pevent INT8U perr 创建互斥型信号量OS EVENT OSMutexCreate INT8U prio INT8U perr 删除信号量OS EVENT
  • uCOSii中的互斥信号量

    uCOSii中的互斥信号量 一 互斥型信号量项管理 MUTUAL EXCLUSION SEMAPHORE MANAGEMENT OSMutexAccept 无条件等待地获取互斥型信号量 OSMutexCreate 建立并初始化一个互斥型信号

随机推荐

  • hp打印机怎么连接电脑_小白使用手册

    工作中 总是离不开文印 文印难题也是在所难免 而对于文印小白来说 只有在打印机一切正常的情况下才能顺利使用打印机 当打印机出现一点 异常 时 就变得不知所措 比如 电脑如何通过无线网络设置打印机 手机如何连接打印机等 问题 遇到这些问题不用
  • 华为od机考真题-跳跃比赛

    def dfs nums i 0 if len nums lt i 1 return 0 return min dfs nums i j 1
  • 视频瞳孔跟踪之星团模型

    视频瞳孔跟踪之星团模型 http www cnblogs com ren19930504 p 4319156 html 视频瞳孔跟踪之星团模型 1 预处理 1 1去除图像噪声 使用5 5的高斯平滑处理散粒噪声 使用 模型处理线路噪声 是第
  • 【华为OD机试真题2023B卷 JAVA&JS】分积木

    华为OD2023 B卷 机试题库全覆盖 刷题指南点这里 分积木 知识点位运算线性表 时间限制 1s 空间限制 32MB 限定语言 不限 题目描述 Solo和koko是两兄弟 妈妈给了他们一大堆积木 每块积木上都有自己的重量 现在他们想要将这
  • 003:打印ASCII码

    003 打印ASCII码 描述 输入一个除空格以外的可见字符 保证在函数scanf中可使用格式说明符 c读入 输出其ASCII码 输入 一个除空格以外的可见字符 输出 一个十进制整数 即该字符的ASCII码 样例输入 A 样例输出 65 这
  • 毕设教学 多分类与数据预测分析算法 - python

    文章目录 0 前言 机器学习 基于逻辑回归 LightGBM XGBoost额的分类预测 一 基于逻辑回归的分类预测 1 逻辑回归的介绍和应用 1 1 逻辑回归的介绍 1 2逻辑回归的应用 2 Demo实践 Step1 库函数导入 Step
  • 加快edge网页的下载速度

    1 edge flags enable parallel downloading 2 点击enabled
  • tomcat8.5之后版本,远程无法登录管理页面

    1 修改 webapps magager META INF context xml文件 注意是webapp下manager发布包里的 不是conf下的context xml 隐藏其中的内容
  • python参数之间用什么分割_如何根据python的两个参数在美丽的汤中分割

    我使用beutifulsoup来提取文档中图像的地址 但是文档中的链接需要清理 特别是大多数图像都有类似的链接 image jpg amp 随机文本和我想要的信息https www webaddress com image jpg file
  • SpringIOC

    一 Sping理解 Spring 是个java企业级应用的开源开发框架 Spring主要用来开发Java应用 但是有些扩展是针对构建J2EE平台的web应用 Spring 框架目标是简化Java企业级应用开发 并通过POJO为基础的编程模型
  • hmcl启动器怎么联机_HMCL 启动器教程 #1 安装启动器

    HMCL 和其他第三方 Minecraft 启动器的安装流程比别的软件都难多了 它们不提供核善的安装程序 所以格外麻 quan 烦 tui 下面是 HMCL 详细安装教程 安装 Java 运行时环境 JRE 注意选择正确的版本 创建一个空的
  • Java架构直通车——RabbitMQ集群架构模式

    文章目录 RabbitMQ四种架构模式 主备模式 远程模式 镜像模式 多活模式 RabbitMQ四种架构模式 主备模式 主备模式也被称为warren 兔子窝 一个主 备方案 主节点挂掉后 从节点提供服务 和ActiveMQ利用Zookeep
  • Ubuntu使用Disks图形化工具挂载新磁盘

    步骤一 Disks工具 搜索Ubuntu系统自带的Disks软件 步骤二 格式化 打开图形界面 点击齿轮按钮 格式化磁盘 给磁盘取名 比如 satadisk 点击next 下一步按钮 点击Format 开始格式化 步骤三 挂载 挂载磁盘 我
  • 这些选品神器,跨境卖家都在用

    相信许多跨境电商商家至今不懂得如何选品 不会选 选什么类目 在哪选 今天给大家整理一波实用选品工具 赶紧来码住 1 TikTok 在国外流行着这么一句话 TikTok mademe buyit TikTok有超过 20亿的流量 有各种红人博
  • 【Unity】UI的MVP框架理解,浅谈框架

    Unity UI的MVP框架理解 浅谈框架 引入框架 简单谈谈MVP框架 框架结构 框架流程 最后的碎碎念 引入框架 什么是框架 很多课程都会提到所谓的框架 进入实习前 总觉得那是很大的 可能需要有某些组件或者其他不一样的东西来作为基础进行
  • Self -Attention、Multi-Head Attention、Cross-Attention

    Self Attention Transformer结构图 上图是论文中 Transformer 的内部结构图 左侧为 Encoder block 右侧为 Decoder block 红色圈中的部分为 Multi Head Attentio
  • 测试基础技能五:判定表法项目实战,售货机购买橙汁和啤酒案例分享

    测试基础技能五 判定表法项目实战 有一个处理单价为5角钱的饮料的自动售货机软件测试用例的设计 其规格说明如下 若投入5角钱或1元钱的硬币 押下 橙汁 或 啤酒 的按钮 则相应的饮料就送出来 若售货机没有零钱找 则一个显示 零钱找完 的红灯亮
  • 第一章-信息收集

    第一章 信息收集 第一节 收集域名信息 1 1 域名介绍 域名 Domain Name 是由一串用点分隔的名字组成的Internet上某一台计算机或计算机组的名称 用于在数据传输时标识计算机的电子方位 例如 学院域名 51cto com 对
  • python如何在xpath中传递2个参数或变量,定位下拉框列表值为新增值,li标签下拉列表值定位方法

    最近在写自动化脚本中遇到一种场景 需要定位下拉框数据的某个值 要先自动生成这个值 然后在下拉框中找到这个值 如下场景 我需要先用脚本自动生成一组手机号 用户名 然后再在这个下拉框中找到自动生成新添加的这组数据并选择它 思路 1 先定位一组固
  • os_mutex.c(全)

    无等待地获取互斥型信号量 OSMutexAccept OS EVENT pevent INT8U perr 创建互斥型信号量OS EVENT OSMutexCreate INT8U prio INT8U perr 删除信号量OS EVENT