μ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 ...
随机推荐
- 订阅者模式,公众号、B站、快手用了都说好!
大家好,今天和大家来聊一个新的设计模式--订阅者模式. 这个模式在我们的生活当中非常常见,可以说是几乎所有的媒体平台都用或多或少地用到了这个模式.比如公众号,我们来仔细梳理一下公众号这个平台当中的整个 ...
- linux在终端中按下键盘立马反应
想在终端中做个小应用,按下上下左右键能立刻作出反应. 测试程序见下: 1 #include <stdio.h> 2 #include <unistd.h> 3 #include ...
- Vue基础之用插值表达式在视图区显示数据
Vue基础之用插值表达式在视图区显示数据 第一步:当然就是你要引入Vue.js这个脚本文件啦! <script src="https://cdn.jsdelivr.net/npm/vu ...
- ubuntu更新下载软件卡住0% [Connecting to archive.ubuntu.com (2001:67c:1360:8001::23)]
一台ubuntu系统,查看硬件和配置环境的时候发现下载卡住了 根据提示就是有ipv6地址,系统也是配置了ipv6地址的.海外机器,而且可以ping通域名 最佳解决方案 我想出了如何让apt-get再次 ...
- 使用nodejs构建Docker image最佳实践
目录 简介 准备nodejs应用程序 创建Dockerfile文件 创建.dockerignore文件 创建docker image 运行docker程序 node的docker image需要注意的 ...
- Webpack4.0各个击破(8)tapable篇
目录 一. tapable概述 二. tapable-0.2源码解析 2.1 代码结构 2.2 事件监听方法 2.3 事件触发方法 三. tapable1.0概述 一. tapable概述 tapab ...
- 深度学习论文翻译解析(十八):MobileNetV2: Inverted Residuals and Linear Bottlenecks
论文标题:MobileNetV2: Inverted Residuals and Linear Bottlenecks 论文作者:Mark Sandler Andrew Howard Menglong ...
- linux下mysql基于mycat做主从复制和读写分离之基础篇
Linux下mysql基于mycat实现主从复制和读写分离1.基础设施 两台虚拟机:172.20.79.232(主) 172.20.79.233(从) 1.1软件设施 mysql5.6.39 , my ...
- 数字转金额格式* 999999.99 TO 999,999.99
/** * 数字转金额格式 * 999999.99 TO 999,999.99 * @param d * @return */ public static String doubleToStr(dou ...
- Latex安装教程(附美赛论文latex模板)
@ 目录 Latex简介 安装步骤 texlive下载 配置环境变量 配置Texsudio latex版本helloworld 美赛 latex模板 Latex简介 LaTeX(LATEX,音译&qu ...