μC/OS-III---I笔记9---任务等待多个内核对象和任务内建信号量与消息队列
在一个任务等待多个内核对象在之前,信号量和消息队列的发布过程中都有等待多个内核对象判断的函数,所谓任务等待多个内核对象顾名思义就是一任务同时等待多个内核对象而被挂起,在USOC—III中一个任务等待多个内核对象时只能是信号量和消息队列的组合。数据类型是OS_PEND_DATA的数组。
在使任务等待多个内核对象时,先定义一个OS_PEND_DATA 类型的等待数据数组,数组的长度等于等待对象的个数,然后初始化数组元素内的Array[n].PendobjPtr=(OS_PEND_OBJ)某个内核对象,进行初始化后就可以调用对应的函数进行设置了。
任务等待多个内核对象函数:
- OS_OBJ_QTY OSPendMulti (OS_PEND_DATA *p_pend_data_tbl,
- OS_OBJ_QTY tbl_size,
- OS_TICK timeout,
- OS_OPT opt,
- OS_ERR *p_err)
- {
- CPU_BOOLEAN valid;
- OS_OBJ_QTY nbr_obj_rdy;
- CPU_SR_ALLOC();
- #ifdef OS_SAFETY_CRITICAL
- if (p_err == (OS_ERR *)0) {
- OS_SAFETY_CRITICAL_EXCEPTION();
- return ((OS_OBJ_QTY)0);
- }
- #endif
- #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
- if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* Can't pend from an ISR */
- *p_err = OS_ERR_PEND_ISR;
- return ((OS_OBJ_QTY)0);
- }
- #endif
- #if OS_CFG_ARG_CHK_EN > 0u
- if (p_pend_data_tbl == (OS_PEND_DATA *)0) { /* Validate 'p_pend_data_tbl' */
- *p_err = OS_ERR_PTR_INVALID;
- return ((OS_OBJ_QTY)0);
- }
- if (tbl_size == (OS_OBJ_QTY)0) { /* Array size must be > 0 */
- *p_err = OS_ERR_PTR_INVALID;
- return ((OS_OBJ_QTY)0);
- }
- //请求不到时阻塞?
- switch (opt) {
- case OS_OPT_PEND_BLOCKING:
- case OS_OPT_PEND_NON_BLOCKING:
- break;
- default:
- *p_err = OS_ERR_OPT_INVALID;
- return ((OS_OBJ_QTY)0);
- }
- #endif
- //多个内核对象检查,只能是信号量或者是消息
- valid = OS_PendMultiValidate(p_pend_data_tbl, /* -------- Validate objects to be OS_SEM or OS_Q ------- */
- tbl_size);
- if (valid == DEF_FALSE) {
- *p_err = OS_ERR_OBJ_TYPE; /* Invalid, not OS_SEM or OS_Q */
- return ((OS_OBJ_QTY)0);
- }
- /*$PAGE*/
- CPU_CRITICAL_ENTER();
- //检查是否有内核对象已经提交
- nbr_obj_rdy = OS_PendMultiGetRdy(p_pend_data_tbl, /* --------- SEE IF OBJECT(s) HAVE BEEN POSTED ---------- */
- tbl_size);
- //有对象就绪,返回
- if (nbr_obj_rdy > (OS_OBJ_QTY)0) {
- CPU_CRITICAL_EXIT();
- *p_err = OS_ERR_NONE;
- return ((OS_OBJ_QTY)nbr_obj_rdy);
- }
- if ((opt & OS_OPT_PEND_NON_BLOCKING) != (OS_OPT)0) { /* Caller wants to block if not available? */
- CPU_CRITICAL_EXIT();
- *p_err = OS_ERR_PEND_WOULD_BLOCK; /* No */
- return ((OS_OBJ_QTY)0);
- } else {
- if (OSSchedLockNestingCtr > (OS_NESTING_CTR)0) { /* Can't pend when the scheduler is locked */
- CPU_CRITICAL_EXIT();
- *p_err = OS_ERR_SCHED_LOCKED;
- return ((OS_OBJ_QTY)0);
- }
- }
- /* Lock the scheduler/re-enable interrupts */
- OS_CRITICAL_ENTER_CPU_EXIT();
- /* ------ NO OBJECT READY, PEND ON MULTIPLE OBJECTS ----- */
- //插入等待队列,和单独一个内核对象相似
- OS_PendMultiWait(p_pend_data_tbl, /* Suspend task until object posted or timeout occurs */
- tbl_size,
- timeout);
- OS_CRITICAL_EXIT_NO_SCHED();
- //挂起当前任务,之后任务能恢复就在于信号发布或消息队列的发布是将任务加入就绪列表
- OSSched(); /* Find next highest priority task ready */
- CPU_CRITICAL_ENTER();
- switch (OSTCBCurPtr->PendStatus) {
- case OS_STATUS_PEND_OK: /* We got one of the objects posted to */
- *p_err = OS_ERR_NONE;
- break;
- case OS_STATUS_PEND_ABORT: /* Indicate that the multi-pend was aborted */
- *p_err = OS_ERR_PEND_ABORT;
- break;
- case OS_STATUS_PEND_TIMEOUT: /* Indicate that we didn't get semaphore within timeout */
- *p_err = OS_ERR_TIMEOUT;
- break;
- case OS_STATUS_PEND_DEL: /* Indicate that an object pended on has been deleted */
- *p_err = OS_ERR_OBJ_DEL;
- break;
- default:
- *p_err = OS_ERR_STATUS_INVALID;
- break;
- }
- OSTCBCurPtr->PendStatus = OS_STATUS_PEND_OK;
- CPU_CRITICAL_EXIT();
- return ((OS_OBJ_QTY)1);
- }
OSPendMulti ()
其中调用的相关函数也是比较简单全部在OS_Pend_Multi.c文件里。等待多个内和对象实际就是前面的消息队列与多值信号量的组合,原理很简单具体的使用结合前面的相关操作就可以了。
任务内建信号量与消息队列
任务内建的信号量与消息队列是UCOS作者为了方便使用而设计的数据结构放在每一个任务的任务控制块里这样操作更简单更省时,在实践的任务通信中,一个任务发送信号量或者消息给另一个任务是比较常见的,但是多个任务发送给一个任务的情况是比较少见的,而任务内建信号或消息队列不仅在数据结构的设计上更加简单,功能也是有区别的任务内建的对象不会有多个等待任务,等待任务有且仅有一个,他们是任务控制块里的所以不可以被单独删除,任务消息队列或信号量在任务创建时就要配置,在以往我们不使用内建对象时,这些选项都是被设置为0的,创建任务是函数传入参数OS_MSG_QTY就是消息队列的最大长度。任务控制块里的OS_SEM_CTR SemCtr;就是任务内建的多值信号量变量。
内建消息队列和消息对列相同,在任务控制块内有一个MsgQ的变量如图结构:
OSTaskSemPost函数 同样是对opt进行检查,然后选择是否延迟发布,延迟发布最后也是进行相同的发布过程因此可以直接看OS_TaskSemPost函数,此函数的第一个入口参数就是任务控制块地址,如果为0 就默认为当前执行的任务,然后判断任务状态进行操作具体见源码注释。
- ************************************************************************************************************************
- * SIGNAL A TASK
- *
- * Description: This function is called to signal a task waiting for a signal.
- *
- * Arguments : p_tcb is the pointer to the TCB of the task to signal. A NULL pointer indicates that you are sending
- * a signal to yourself.
- *
- * opt determines the type of POST performed:
- *
- * OS_OPT_POST_NONE No option
- * OS_OPT_POST_NO_SCHED Do not call the scheduler
- *
- * p_err is a pointer to an error code returned by this function:
- *
- * OS_ERR_NONE If the requested task is signaled
- * OS_ERR_SEM_OVF If the post would cause the semaphore count to overflow.
- *
- * Returns : The current value of the task's signal counter or 0 if called from an ISR
- ************************************************************************************************************************
- */
- OS_SEM_CTR OSTaskSemPost (OS_TCB *p_tcb,
- OS_OPT opt,
- OS_ERR *p_err)
- {
- OS_SEM_CTR ctr;
- CPU_TS ts;
- #ifdef OS_SAFETY_CRITICAL
- if (p_err == (OS_ERR *)0) {
- OS_SAFETY_CRITICAL_EXCEPTION();
- return ((OS_SEM_CTR)0);
- }
- #endif
- #if OS_CFG_ARG_CHK_EN > 0u
- switch (opt) { /* Validate 'opt' */
- case OS_OPT_POST_NONE:
- case OS_OPT_POST_NO_SCHED:
- break;
- default:
- *p_err = OS_ERR_OPT_INVALID;
- return ((OS_SEM_CTR)0u);
- }
- #endif
- ts = OS_TS_GET(); /* Get timestamp */
- #if OS_CFG_ISR_POST_DEFERRED_EN > 0u
- if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* See if called from an ISR */
- OS_IntQPost((OS_OBJ_TYPE)OS_OBJ_TYPE_TASK_SIGNAL, /* Post to ISR queue */
- (void *)p_tcb,
- (void *)0,
- (OS_MSG_SIZE)0,
- (OS_FLAGS )0,
- (OS_OPT )0,
- (CPU_TS )ts,
- (OS_ERR *)p_err);
- return ((OS_SEM_CTR)0);
- }
- #endif
- ctr = OS_TaskSemPost(p_tcb,
- opt,
- ts,
- p_err);
- return (ctr);
- }
OSTaskSemPost ()
OSTaskSemPend 函数 先检查选项,然后直接if (OSTCBCurPtr->SemCtr > (OS_SEM_CTR)0)判断任务控制块内的信号量是否可用,可用后进行相关的处理后返回可用值(数量),否则调用OS_Pend直接将当前任务阻塞,阻塞选项是任务内建信号量。
- ************************************************************************************************************************
- * WAIT FOR A TASK SEMAPHORE
- *
- * Description: This function is called to block the current task until a signal is sent by another task or ISR.
- *
- * Arguments : timeout is the amount of time you are will to wait for the signal
- *
- * opt determines whether the user wants to block if a semaphore post was not received:
- *
- * OS_OPT_PEND_BLOCKING
- * OS_OPT_PEND_NON_BLOCKING
- *
- * p_ts is a pointer to a variable that will receive the timestamp of when the semaphore was posted
- * or pend aborted. If you pass a NULL pointer (i.e. (CPU_TS *)0) then you will not get the
- * timestamp. In other words, passing a NULL pointer is valid and indicates that you don't
- * need the timestamp.
- *
- * p_err is a pointer to an error code that will be set by this function
- *
- * OS_ERR_NONE The call was successful and your task received a message.
- * OS_ERR_PEND_ABORT
- * OS_ERR_PEND_ISR If you called this function from an ISR and the result
- * OS_ERR_PEND_WOULD_BLOCK If you specified non-blocking but no signal was received
- * OS_ERR_SCHED_LOCKED If the scheduler is locked
- * OS_ERR_STATUS_INVALID If the pend status is invalid
- * OS_ERR_TIMEOUT A message was not received within the specified timeout
- * would lead to a suspension.
- *
- * Returns : The current count of signals the task received, 0 if none.
- ************************************************************************************************************************
- */
- OS_SEM_CTR OSTaskSemPend (OS_TICK timeout,
- OS_OPT opt,
- CPU_TS *p_ts,
- OS_ERR *p_err)
- {
- OS_SEM_CTR ctr;
- CPU_SR_ALLOC();
- #ifdef OS_SAFETY_CRITICAL
- if (p_err == (OS_ERR *)0) {
- OS_SAFETY_CRITICAL_EXCEPTION();
- return ((OS_SEM_CTR)0);
- }
- #endif
- #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
- if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* Not allowed to call from an ISR */
- *p_err = OS_ERR_PEND_ISR;
- return ((OS_SEM_CTR)0);
- }
- #endif
- #if OS_CFG_ARG_CHK_EN > 0u
- switch (opt) { /* Validate 'opt' */
- case OS_OPT_PEND_BLOCKING:
- case OS_OPT_PEND_NON_BLOCKING:
- break;
- default:
- *p_err = OS_ERR_OPT_INVALID;
- return ((OS_SEM_CTR)0);
- }
- #endif
- if (p_ts != (CPU_TS *)0) {
- *p_ts = (CPU_TS )0; /* Initialize the returned timestamp */
- }
- CPU_CRITICAL_ENTER();
- if (OSTCBCurPtr->SemCtr > (OS_SEM_CTR)0) { /* See if task already been signaled */
- OSTCBCurPtr->SemCtr--;
- ctr = OSTCBCurPtr->SemCtr;
- if (p_ts != (CPU_TS *)0) {
- *p_ts = OSTCBCurPtr->TS;
- }
- #if OS_CFG_TASK_PROFILE_EN > 0u
- OSTCBCurPtr->SemPendTime = OS_TS_GET() - OSTCBCurPtr->TS;
- if (OSTCBCurPtr->SemPendTimeMax < OSTCBCurPtr->SemPendTime) {
- OSTCBCurPtr->SemPendTimeMax = OSTCBCurPtr->SemPendTime;
- }
- #endif
- CPU_CRITICAL_EXIT();
- *p_err = OS_ERR_NONE;
- return (ctr);
- }
- if ((opt & OS_OPT_PEND_NON_BLOCKING) != (OS_OPT)0) { /* Caller wants to block if not available? */
- CPU_CRITICAL_EXIT();
- *p_err = OS_ERR_PEND_WOULD_BLOCK; /* No */
- return ((OS_SEM_CTR)0);
- } else { /* Yes */
- if (OSSchedLockNestingCtr > (OS_NESTING_CTR)0) { /* Can't pend when the scheduler is locked */
- CPU_CRITICAL_EXIT();
- *p_err = OS_ERR_SCHED_LOCKED;
- return ((OS_SEM_CTR)0);
- }
- }
- /* Lock the scheduler/re-enable interrupts */
- OS_CRITICAL_ENTER_CPU_EXIT();
- OS_Pend((OS_PEND_DATA *)0, /* Block task pending on Signal */
- (OS_PEND_OBJ *)0,
- (OS_STATE )OS_TASK_PEND_ON_TASK_SEM,
- (OS_TICK )timeout);
- OS_CRITICAL_EXIT_NO_SCHED();
- OSSched(); /* Find next highest priority task ready to run */
- CPU_CRITICAL_ENTER();
- switch (OSTCBCurPtr->PendStatus) { /* See if we timed-out or aborted */
- case OS_STATUS_PEND_OK:
- if (p_ts != (CPU_TS *)0) {
- *p_ts = OSTCBCurPtr->TS;
- #if OS_CFG_TASK_PROFILE_EN > 0u
- OSTCBCurPtr->SemPendTime = OS_TS_GET() - OSTCBCurPtr->TS;
- if (OSTCBCurPtr->SemPendTimeMax < OSTCBCurPtr->SemPendTime) {
- OSTCBCurPtr->SemPendTimeMax = OSTCBCurPtr->SemPendTime;
- }
- #endif
- }
- *p_err = OS_ERR_NONE;
- break;
- case OS_STATUS_PEND_ABORT:
- if (p_ts != (CPU_TS *)0) {
- *p_ts = OSTCBCurPtr->TS;
- }
- *p_err = OS_ERR_PEND_ABORT; /* Indicate that we aborted */
- break;
- case OS_STATUS_PEND_TIMEOUT:
- if (p_ts != (CPU_TS *)0) {
- *p_ts = (CPU_TS )0;
- }
- *p_err = OS_ERR_TIMEOUT; /* Indicate that we didn't get event within TO */
- break;
- default:
- *p_err = OS_ERR_STATUS_INVALID;
- break;
- }
- ctr = OSTCBCurPtr->SemCtr;
- CPU_CRITICAL_EXIT();
- return (ctr);
- }
OSTaskSemPend()
OSTaskQPost函数第一个参数就是要给发布的任务控制块,然后根据消息对列的模式FIFO或者LIFO,下来就是与消息对列相同的提交操作。
任务内建消息队列发布:
- #if OS_CFG_TASK_Q_EN > 0u
- void OS_TaskQPost (OS_TCB *p_tcb,
- void *p_void,
- OS_MSG_SIZE msg_size,
- OS_OPT opt,
- CPU_TS ts,
- OS_ERR *p_err)
- {
- CPU_SR_ALLOC();
- OS_CRITICAL_ENTER();
- if (p_tcb == (OS_TCB *)0) { /* Post msg to 'self'? */
- p_tcb = OSTCBCurPtr;
- }
- *p_err = OS_ERR_NONE; /* Assume we won't have any errors */
- switch (p_tcb->TaskState) {
- case OS_TASK_STATE_RDY:
- case OS_TASK_STATE_DLY:
- case OS_TASK_STATE_SUSPENDED:
- case OS_TASK_STATE_DLY_SUSPENDED:
- OS_MsgQPut(&p_tcb->MsgQ, /* Deposit the message in the queue */
- p_void,
- msg_size,
- opt,
- ts,
- p_err);
- OS_CRITICAL_EXIT();
- break;
- case OS_TASK_STATE_PEND:
- case OS_TASK_STATE_PEND_TIMEOUT:
- case OS_TASK_STATE_PEND_SUSPENDED:
- case OS_TASK_STATE_PEND_TIMEOUT_SUSPENDED:
- if (p_tcb->PendOn == OS_TASK_PEND_ON_TASK_Q) { /* Is task waiting for a message to be sent to it? */
- OS_Post((OS_PEND_OBJ *)0,
- p_tcb,
- p_void,
- msg_size,
- ts);
- OS_CRITICAL_EXIT_NO_SCHED();
- if ((opt & OS_OPT_POST_NO_SCHED) == (OS_OPT)0u) {
- OSSched(); /* Run the scheduler */
- }
- } else {
- OS_MsgQPut(&p_tcb->MsgQ, /* No, Task is pending on something else ... */
- p_void, /* ... Deposit the message in the task's queue */
- msg_size,
- opt,
- ts,
- p_err);
- OS_CRITICAL_EXIT();
- }
- break;
- default:
- OS_CRITICAL_EXIT();
- *p_err = OS_ERR_STATE_INVALID;
- break;
- }
- }
- #endif
OS_TaskQPost ()
总的来说任务内建的信号量或消息对列被创建出来就是有其特点使用简单方便,且管理方便。
任务内建消息队列等待:
- #if OS_CFG_TASK_Q_EN > 0u
- void *OSTaskQPend (OS_TICK timeout,
- OS_OPT opt,
- OS_MSG_SIZE *p_msg_size,
- CPU_TS *p_ts,
- OS_ERR *p_err)
- {
- OS_MSG_Q *p_msg_q;
- void *p_void;
- CPU_SR_ALLOC();
- #ifdef OS_SAFETY_CRITICAL
- if (p_err == (OS_ERR *)0) {
- OS_SAFETY_CRITICAL_EXCEPTION();
- return ((void *)0);
- }
- #endif
- #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
- if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* Can't Pend from an ISR */
- *p_err = OS_ERR_PEND_ISR;
- return ((void *)0);
- }
- #endif
- #if OS_CFG_ARG_CHK_EN > 0u /* ---------------- VALIDATE ARGUMENTS ------------------ */
- if (p_msg_size == (OS_MSG_SIZE *)0) { /* User must supply a valid destination for msg size */
- *p_err = OS_ERR_PTR_INVALID;
- return ((void *)0);
- }
- switch (opt) { /* User must supply a valid option */
- case OS_OPT_PEND_BLOCKING:
- case OS_OPT_PEND_NON_BLOCKING:
- break;
- default:
- *p_err = OS_ERR_OPT_INVALID;
- return ((void *)0);
- }
- #endif
- if (p_ts != (CPU_TS *)0) {
- *p_ts = (CPU_TS )0; /* Initialize the returned timestamp */
- }
- CPU_CRITICAL_ENTER();
- //取出任务内建消息队列
- p_msg_q = &OSTCBCurPtr->MsgQ; /* Any message waiting in the message queue? */
- //获取消息的地址
- p_void = OS_MsgQGet(p_msg_q,
- p_msg_size,
- p_ts,
- p_err);
- //如果获取到了消息
- if (*p_err == OS_ERR_NONE) {
- #if OS_CFG_TASK_PROFILE_EN > 0u
- if (p_ts != (CPU_TS *)0) {
- OSTCBCurPtr->MsgQPendTime = OS_TS_GET() - *p_ts;
- if (OSTCBCurPtr->MsgQPendTimeMax < OSTCBCurPtr->MsgQPendTime) {
- OSTCBCurPtr->MsgQPendTimeMax = OSTCBCurPtr->MsgQPendTime;
- }
- }
- #endif
- CPU_CRITICAL_EXIT();
- //返回消息地址,同时指针形式的传入p_msg_size将消息长度传回
- return (p_void); /* Yes, Return oldest message received */
- }
- if ((opt & OS_OPT_PEND_NON_BLOCKING) != (OS_OPT)0) { /* Caller wants to block if not available? */
- *p_err = OS_ERR_PEND_WOULD_BLOCK; /* No */
- CPU_CRITICAL_EXIT();
- return ((void *)0);
- } else { /* Yes */
- if (OSSchedLockNestingCtr > (OS_NESTING_CTR)0) { /* Can't block when the scheduler is locked */
- CPU_CRITICAL_EXIT();
- *p_err = OS_ERR_SCHED_LOCKED;
- return ((void *)0);
- }
- }
- /* Lock the scheduler/re-enable interrupts */
- OS_CRITICAL_ENTER_CPU_EXIT();
- //没有请求到消息阻塞任务
- OS_Pend((OS_PEND_DATA *)0, /* Block task pending on Message */
- (OS_PEND_OBJ *)0,
- (OS_STATE )OS_TASK_PEND_ON_TASK_Q,
- (OS_TICK )timeout);
- OS_CRITICAL_EXIT_NO_SCHED();
- OSSched(); /* Find the next highest priority task ready to run */
- CPU_CRITICAL_ENTER();
- switch (OSTCBCurPtr->PendStatus) {
- case OS_STATUS_PEND_OK: /* Extract message from TCB (Put there by Post) */
- p_void = OSTCBCurPtr->MsgPtr;
- *p_msg_size = OSTCBCurPtr->MsgSize;
- if (p_ts != (CPU_TS *)0) {
- *p_ts = OSTCBCurPtr->TS;
- #if OS_CFG_TASK_PROFILE_EN > 0u
- OSTCBCurPtr->MsgQPendTime = OS_TS_GET() - OSTCBCurPtr->TS;
- if (OSTCBCurPtr->MsgQPendTimeMax < OSTCBCurPtr->MsgQPendTime) {
- OSTCBCurPtr->MsgQPendTimeMax = OSTCBCurPtr->MsgQPendTime;
- }
- #endif
- }
- *p_err = OS_ERR_NONE;
- break;
- case OS_STATUS_PEND_ABORT: /* Indicate that we aborted */
- p_void = (void *)0;
- *p_msg_size = (OS_MSG_SIZE)0;
- if (p_ts != (CPU_TS *)0) {
- *p_ts = (CPU_TS )0;
- }
- *p_err = OS_ERR_PEND_ABORT;
- break;
- case OS_STATUS_PEND_TIMEOUT: /* Indicate that we didn't get event within TO */
- default:
- p_void = (void *)0;
- *p_msg_size = (OS_MSG_SIZE)0;
- if (p_ts != (CPU_TS *)0) {
- *p_ts = OSTCBCurPtr->TS;
- }
- *p_err = OS_ERR_TIMEOUT;
- break;
- }
- CPU_CRITICAL_EXIT();
- return (p_void); /* Return received message */
- }
- #endif
OSTaskQPend ()
μC/OS-III---I笔记9---任务等待多个内核对象和任务内建信号量与消息队列的更多相关文章
- 18.1-uC/OS-III等待多个内核对象
等待的多个内核对象是指多值信号量和消息队列的任意组合 . 如果想要使用“等待多个内核对象”,就必须事先使能“等待多个内核对象”.“等待多个内核对象” 的使能位于“os_cfg.h”. 1.OSPend ...
- UCOSIII等待多个内核对象
内核对象 内核对象包括信号量.互斥信号量.消息队列和事件标志组 UCOSIII中允许任务同时等待多个信号量和多个消息队列 主结构体 typedef struct os_pend_data OS_PEN ...
- [原创]java WEB学习笔记71:Struts2 学习之路-- struts2常见的内建验证程序及注意点,短路验证,非字段验证,错误消息的重用
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
- 第9章 用内核对象进行线程同步(2)_可等待计时器(WaitableTimer)
9.4 可等待的计时器内核对象——某个指定的时间或每隔一段时间触发一次 (1)创建可等待计时器:CreateWaitableTimer(使用时应把常量_WIN32_WINNT定义为0x0400) 参数 ...
- 基于μC/OS—III的CC1120驱动程序设计
基于μC/OS—III的CC1120驱动程序设计 时间:2014-01-21 来源:电子设计工程 作者:张绍游,张贻雄,石江宏 关键字:CC1120 嵌入式操作系统 STM32F103ZE ...
- Python3+Selenium3+webdriver学习笔记14(等待判断 鼠标事件 )
!/usr/bin/env python -*- coding:utf-8 -*-'''Selenium3+webdriver学习笔记14(等待判断 鼠标事件 )'''from selenium im ...
- uc/os iii移植到STM32F4---IAR开发环境
也许是先入为主的原因,时钟用不惯Keil环境,大多数的教程都是拿keil写的,尝试将官方的uc/os iii 移植到IAR环境. 1.首先尝试从官网上下载的官方移植的代码,编译通过,但是执行会报堆栈溢 ...
- python笔记9 线程进程 threading多线程模块 GIL锁 multiprocessing多进程模块 同步锁Lock 队列queue IO模型
线程与进程 进程 进程就是一个程序在一个数据集上的一次动态执行过程.进程一般由程序.数据集.进程控制块三部分组成.我们编写的程序用来描述进程要完成哪些功能以及如何完成:数据集则是程序在执行过程中所需要 ...
- 消息队列 NSQ 源码学习笔记 (一)
nsqlookupd 用于Topic, Channel, Node 三类信息的一致性分发 概要 nsqlookup 知识点总结 功能定位 为node 节点和客户端节点提供一致的topic, chann ...
随机推荐
- 求得二叉搜索树的第k小的元素
求得二叉搜索树的第k小的元素 给定一个二叉搜索树,编写一个函数 kthSmallest 来查找其中第 k 个最小的元素. 须知:二叉搜索树,又叫二叉排序树,二叉查找树.特点是:左子树的所有元素都小于等 ...
- vue中computed/method/watch的区别
摘要:本文通过官方文档结合源码来分析computed/method/watch的区别. Tips:本文分析的源码版本是v2.6.11,文章中牵涉到vue响应式系统原理部分,如果不是很了解,建议先阅读上 ...
- 理解js闭包9大使用场景
1.返回值(最常用) //1.返回值 最常用的 function fn(){ var name="hello"; return function(){ return name; } ...
- 在vSphere中为不同服务器配置IPMI功能
在vSphere HA中如果要配置并启用DPM功能,需要记录服务器远程管理接口的IP地址(不是ESXi的IP地址,而是另一个独立的IP地址,是与ESXi服务器同一网段的另一个IP地址)与MAC地址.远 ...
- C#高级编程第11版 - 第三章 索引
[1]3.1 创建及使用类 1.构造函数:构造函数的名字与类名相同: 使用 new 表达式创建类的对象或者结构(例如int)时,会调用其构造函数.并且通常初始化新对象的数据成员. 除非类是静态的,否则 ...
- ShardingSphere内核原理 原创 鸽子 架构漫谈 2021-01-09
ShardingSphere内核原理 原创 鸽子 架构漫谈 2021-01-09
- SpringBoot配置文件 application.properties,yaml配置
SpringBoot配置文件 application.properties,yaml配置 1.Spring Boot 的配置文件 application.properties 1.1 位置问题 1.2 ...
- Spark Dataset DataFrame空值null,NaN判断和处理
Spark Dataset DataFrame空值null,NaN判断和处理 import org.apache.spark.sql.SparkSession import org.apache.sp ...
- svn 启动项目报错,项目被lock
问题描述 问题解决 (一)Eclipse SVN 插件处理 (二)SVN 客户端处理 (三)删除lock文件 问题描述 在使用开发工具开发项目时(如Eclipse),在做项目的中途,有时候Eclips ...
- Scala安装后,在IDEA中配置
IDEA中配置Scala 一.设置Module 二.添加Scala的SDK 三.寻找本地scala安装路径 四.测试是否可以新建有Scala Class 五.踩坑填坑记录 5.1:Error:(4, ...