libuv初始化的时候会初始化信号处理相关的逻辑。...UV__F_NONBLOCK); if (err) return err; // 设置信号io观察者的处理函数和文件描述符,libuv在poll io时,发现管道读端loop->signal_pipefd...// 信号处理函数,signum为收到的信号,每个子进程收到信号的时候都由该函数处理,然后通过管道通知libuv static void uv__signal_handler(int signum) {...信号的处理就完成了。接下来在libuv的poll io阶段才做真正的处理。回到文章开头我们知道在poll io阶段。...整个信号注册和处理的流程就完成了。整个流程总结如下: 1 libuv初始化的时候,申请一个管道,用于互斥控制,然后执行往里面写一个数据,保存后续的lock和unlock可以顺利执行。
libuv的async.c实现了线程和主线程的通信。在uv_loop_init函数中对async进行初始化。...h->async_cb(h); } } uv__async_io变量变量loop的async_handles队列,通过pending字段判断该async是否被触发,pending字段可以有libuv...如果被触发则执行上层回调,该回调在uv_async_init时传入,这里的回调分为两种,第一种是libuv本身的和用户的。如果async结构体是由用户创建的,则回调函数也是用户设置的。...另外一种就是libuv本身创建的async。例如uv_loop_init时初始化的代码。...err = uv_async_init(loop, &loop->wq_async, uv__work_done); 对于这种情况,回调函数是libuv提供的uv__work_done。
事件循环核心结构体uv_loop_s结构图 libuv结构体结构图
libuv的queue实现得很博大精深。严重考验了c指针的理解。今天就分享一下他的实现。...下面我们接着分析四个举足轻重的宏定义,理解他们就相当于理解了libuv的队列。在分析之前,我们先来回顾一下数组指针和二维数组的知识。...因为libuv的数组只有两个元素。相当于p[2][2]变成了*p[2][1]。所以上面的代码简化为。...在libuv中如下 ? *(QUEUE *) &(((q))[0])解引用取得q下一个节点的地址(作为右值),或者修改当前节点的next域内存里的值(作为左值),类型是void (*)[2]。...这就是libuv队列的亮点了。下面我们看一下这些宏的使用。
libuv在inotify机制的基础上做了一层封装。 今天分析一下libuv中的实现。我们从一个使用例子开始。...并且往libuv插入一个观察者io,libuv会在poll io阶段注册到epoll中。 2 往操作系统注册一个待监听的文件。返回一个id。 3 libuv判断该id是不是在自己维护的红黑树中。...if (size == -1) { assert(errno == EAGAIN || errno == EWOULDBLOCK); break; } // 处理...e + 1) : uv__basename_r(w->path); w->iterating = 1; // 把红黑树中,wd对应节点的handle队列移到queue变量,准备处理...QUEUE_HEAD(&queue); // 通过结构体偏移拿到首地址 h = QUEUE_DATA(q, uv_fs_event_t, watchers); // 从处理队列中移除
libuv实现了一个线程池,该线程池在用户提交了第一个任务的时候初始化,而不是系统启动的时候就初始化。入口代码如下。...0; i < nthreads; i++) if (uv_thread_create(threads + i, worker, &sem)) abort(); // 等待sem信号量为非...有两种方式,libuv内部使用的是uv__work_submit函数。...则回调函数即libuv设置的,没有经过封装。最后提一下libuv提供的取消任务函数。...的线程池就解析完了。
在libuv中,unix域用uv_pipe_t表示。...注册到libuv。等到有读事件到来(有连接到来)。就会执行uv__server_io函数,摘下对应的客户端节点。最后执行connection_cb回调。 这时候,使用unix域成功启动了一个服务。...(handle),(struct sockaddr*)&saddr, sizeof saddr); } while (r == -1 && errno == EINTR); // 忽略错误处理逻辑...错误码是delayed_error if (err) uv__io_feed(handle->loop, &handle->io_watcher); } 本文大致分析了unix域在libuv...libuv在操作系统提供的api的基础上。和libuv的异步非阻塞结合。在libuv中为进程间提供了一种通信方式。后续会继续分析本文提到的内容。unix域在操作系统的实现可以参考unix域源码解析。
执行定时器的时候首先会先移除该定时器,然后如果设置了repeat的话,再次加入到最小堆里,最后执行超时回调。这里有个需要注意的是设置了repeat的定时器,意思...
我们看libuv中如何新建一个socket。...不过libuv并不直接使用这个函数。而是又封装了一层。...而其他流是在uv__stream_io里统一处理。 流的类型分析得差不多了,最后分析一下监听流的处理函数uv__server_io,统一处理其他流的函数是uv__stream_io,这个下次分析。...= -1) { uv__io_stop(loop, &stream->io_watcher, POLLIN); return; } // 定时睡眠一会(可被信号唤醒...则撤销等待可读事件,即处理完一个fd后,再accept下一个。如果2中消费了fd。
前言 在 React源码解析之renderRoot概览 中提到了,当有异常抛出的时候,会执行completeUnitOfWork(): //捕获异常,并处理 catch (thrownValue...ClassComponent,所以执行updateClassComponent()——>finishClassComponent() 补充: 关于completeUnitOfWork(),请看: React源码解析之...completeUnitOfWork 关于workLoop()、performUnitOfWork()和beginWork(),请看: React源码解析之workLoop 关于updateClassComponent...(),请看: React源码解析之updateClassComponent(上) React源码解析之updateClassComponent(下) 我们看下finishClassComponent()...(),让ClassComponent渲染出捕获 error 的 ui 页面 补充: 关于reconcileChildFibers(),请看: React源码解析之FunctionComponent(上)
流的实现在libuv里占了很大篇幅,今天分析一下流的实现。首先看数据结构。流在libuv里用uv_stream_s表示,他属于handle族。继承于uv_handle_s。...uv__tcp_keepalive(fd, 1, 60)) { return UV__ERR(errno); } } // 保存socket对应的文件描述符到io观察者中,libuv...// 如果写完了全部buf,触发回调 if (req->write_index == req->nbufs) { // 写完了本请求的数据,做后续处理...uv__io_active(&stream->io_watcher, POLLIN)) uv__handle_stop(stream); } 我们看一下写完一个请求后,libuv如何处理他。
(x) = SPLAY_NEXT(name, head, x)) 最主要的方法就是这个伸展函数: 先仔细说明下面几个变量的意思: 在遍历过程中,head->sph_root 始终指向目前正在处理的根节点...\ SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ } 总结:虽然伸展树在 libuv
UNUSED static) #define RB_GENERATE_INTERNAL(name, type, field, cmp, attr) \ // 根据节点颜色处理不同的插入后平衡的情况...gparent, field); \ // 但是这时候由于 祖父节点的颜色有可能也是红色 导致 双红问题 则需要继续迭代往上处理...\ // ele的左右子节点不完全都存在的时候 简单的处理清空...那就准备自适应平衡了 // 再分析最后一个最复杂的方法之前 我们需要记住目前得到的信息 parent child 因为被我们删除了一个黑色节点而导致这条路径上黑节点数量变少了一个 不平衡了 下面的方法就是负责处理这种情况的...= NULL); \ (x) = (y)) 总结: 红黑树是libuv中用来管理信号handler的,实现的独立性比较高,可以用于自己以后项目参考。
1.数字信号处理原理 线性系统中,信号只能以乘以一个常数之后再相加的方式进行组合。例如,一个信号不能直接乘以另外一个信号。...如下图所示,根据给出三个信号:x0[n],x1[n],x2[n]相加得到最终的信号x[n]。通过相乘和相加的形式进行信号的组合被称为信号的合成。 与信号合成相反的步骤,叫做信号的分解。...即把原始信号分解为两个或多个信号相加。信号的分解要比信号合成要复杂些。...图1 数字信号处理中,最为关键的步骤是信号的叠加。假设有如下图的输入信号x[n],经过一个线性系统之后,输出信号为y[n]。...之后把各个输入信号分量单独的输入到线性系统中,产生与之对应的输出信号分量:y1[n],y2[n],y3[n]。原始的输入信号经过线性系统之后,得到的输出信号y[n]即为各个输出信号分量的合成。
源码深度剖析四 libevent源代码文件组织 (5)libevent源码深度剖析五 libevent的核心:事件event (6)libevent源码深度剖析六 初见事件处理框架 (7)libevent...源码深度剖析七 事件主循环 (8)libevent源码深度剖析八 集成信号处理 (9)libevent源码深度剖析九 集成定时器事件 (10)libevent源码深度剖析十 支持I/O多路复用技术...(11)libevent源码深度剖析十一 时间管理 (12)libevent源码深度剖析十二 让libevent支持多线程 (13)libevent源码深度剖析十三 libevent信号处理注意点 现在我们已经了解了...(),该函数将在下一段介绍,注册过程如下: 1 取得ev要注册到的信号signo; 2 如果信号signo未被注册,那么就为signo注册信号处理函数evsignal_handler(); 3 如果事件...处理函数evsignal_handler()函数做的事情很简单,就是记录信号的发生次数,并通知event_base有信号触发,需要处理: 1static void evsignal_handler(int
相参积累处理 在信号理论中,相参又称为相干,定义为脉冲之间存在确定的相位关系。简单来说,脉冲间的相位可以互相对照,知道其中一个相位就有办法知道另外一个。...相参处理的意义在于脉冲积累时提高信噪比,提高多普勒频率的准确度。由于雷达回波信号不但有微弱的信号,还会有很强的噪声。雷达的主要目的就是要把微弱的目标信号从噪声中分离出来,设法提高信噪比。...再对每个列向量(即行向量中对应距离单元)做复数FFT处理,共做n次,形成图1 (b)中相参积累后的结果,形成“距离-多普勒”二维分布图。...射频频率:35GHz; 中频频率:70MHz; 采样率:40MHz; 脉冲宽度:50μs; 信号带宽:10MHz; 在MATLAB中对回波经过数字下变频、4倍抽取以及脉冲压缩处理之后,对32个脉冲进行相参积累...图4 相参积累后的信号(目标1的SNR为-5dB,目标2的SNR为2dB) 由上图的二维平面可以直观地看出,两个淹没在噪声中的低SNR信号,通过脉冲压缩与32个脉冲在相参积累后,信噪比得到了极大提升,雷达信号处理机可以对目标进行有效检测
恒虚警CFAR处理 恒虚警率CFAR是ConstantFalse-AlarmRate的缩写。...雷达信号恒虚警率检测就是要求虚警概率保持恒定,这主要是因为在雷达信号检测中,信号的最佳检测通常采用奈曼-皮尔逊准则,即在保持恒定的虚警概率的条件下,使正确检测的概率达到最大值。...对该二维分布图取模值处理后,形成CFAR(恒虚警)平面,若回波中存在目标信号,则二维分布图上会出现目标尖峰,如下图所示。 ?...CFAR处理原理如上图所示。在检测单元的两侧各留出一些保护单元,保护单元的总数略大于目标所占分辨单元数。...CFAR处理原理如上图所示。在检测单元的两侧各留出一些保护单元,保护单元的总数略大于目标所占分辨单元数。
具体的分析可以看linux0.11系统调用过程和fork源码解析这篇文章。下面贴一下代码。...当前需要处理的信号加1,因为ecx保存的是位置,位置是0开始的,信号是1-32 incl %ecx // 入参压栈 pushl %ecx // 执行信号处理函数 call...// 没有处理函数又不是SIGCHLD信号则进程退出 if (!...信号处理的时机是在进程进行系统调用的时候。假设通过kill系统调用给进程发送一个信号。...接着系统就会进入信号处理的流程。
我们写的sql语句只是一个字符串而已,首先需要将其通过词法解析和语法解析生成语法树,Spark1.x版本使用的是scala原生的parser语法解析器,从2.x后改用的是第三方语法解析工具ANTLR4,...我们只需要实现我们需要的节点事件逻辑代码即可,再实例化一个遍历类ParseTreeWalker,antlr会自上而下的遍历所有节点,以完成我们的逻辑处理; Visitor则是主动遍历模式,需要我们显示的控制我们的遍历顺序...通过词法解析和语法解析将SQL语句解析成了ANTLR 4的语法树结构ParseTree。...具体看源码: // 代码1 val spark = SparkSession .builder .appName("SparkSQL Test") .master("local...可以看到代码3中parsePlan方法先执行parse方法(代码4),在代码4中先后实例化了分词解析和语法解析类,最后将antlr的语法解析器parser:SqlBaseParser 传给了代码3中的柯里化函数
源码解析之AQS 标签:源码|多线程 Node节点说明 java.util.concurrent.locks.AbstractQueuedSynchronizer.Node /** * waitStatus...next; // 处于该节点的线程 volatile Thread thread; // 指向下一个处于condition状态的节点 Node nextWaiter; predecessor(); lock源码分析...{ // 线程在此阻塞,等待持有锁的线程释放锁唤醒 LockSupport.park(this); return Thread.interrupted(); } unlock源码分析
领取专属 10元无门槛券
手把手带您无忧上云