μ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 ...
随机推荐
- SEO大杀器rendertron安装
前段时间做SEO的优化,使用的是GoogleChrome/rendertron,发现这个安装部署的时候还是会有一些要注意的地方,做个记录 为什么要使用rendertron 目前很多网站都是使用 vue ...
- Py第一次练习,第二次练习
有两个列表 l1 = [11,22,33] l2 = [22,33,44] 1.获取内容相同的元素列表2.获取l1中有l2中没有的元素列表3.获取l1和l2中不同的元素列表 l ...
- 【UltraISO】中文破解版
下载链接:https://cn.ultraiso.net/uiso9_cn.exe简体中文版专用: 注册名:Guanjiu 注册码:A06C-83A7-701D-6CFC多国语言版专用: ...
- JMETER-正则表达式提取与查看变量是否提取正确
一.应用场景说明: 在一个线程组中,B请求需要使用A请求返回的数据,也就是常说的关联,将上一个请求的响应结果作为下一个请求的参数,则需要对A请求的响应报文使用后置处理器,其中最方便最常用的就是正则表达 ...
- 计算机网络安全 —— C# 使用谷歌身份验证器(Google Authenticator)(五)
一.Google Authenticator 基本概念 Google Authenticator是谷歌推出的一款动态口令工具,旨在解决大家Google账户遭到恶意攻击的问题,在手机端生成动态口令后, ...
- kettle 连接oracle12c问题解决办法:
在oracle的安装文件目录......\NETWORK\ADMIN\sqlnet.ora 文件中添加该语句:SQLNET.ALLOWED_LOGON_VERSION_SERVER = 8window ...
- 从零开始学Java (四)输入输出
这块内容对于有基础的人没啥好说的... 1 System.out.print("C"); 2 System.out.println(); 上边和下边等价 1 System.out. ...
- 在nodejs中创建cluster
目录 简介 cluster集群 cluster详解 cluster中的event cluster中的方法 cluster中的属性 cluster中的worker 总结 在nodejs中创建cluste ...
- jQuery——操作DOM
所谓Web体验,就是Web服务器与Web浏览器之间的合作.过去,都是由服务器生成HTML文档,然后浏览器负责解释并显示该文档.后来,我们可以用CSS技术来动态修改页面的外观. ###操作属性 jQue ...
- DOS windows 使用bat脚本获取 IP MAC 系统信息
@echo select disk 0 >dpjs.txt @echo detail disk >>dpjs.txt diskpart /s dpjs.txt@echo ------ ...