首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

深入理解Node.js 进程与线程(8000长文彻底搞懂)

Node.js 做耗时的计算时候,如何避免阻塞? Node.js如何实现多进程的开启和关闭? Node.js可以创建线程吗? 你们开发过程中如何实现进程守护的?...原因是child_process操作子进程时,可以隐式的创建多个TCP服务器,对比上面的两幅图应该能理解我说的内容。...父进程在实际创建子进程之前,会创建 IPC通道并监听它,然后才 真正的创建出 子进程,这个过程中也会通过环境变量(NODECHANNELFD)告诉子进程这个IPC通道的文件描述符。...Node.js句柄传递 讲句柄之前,先想一个问题,send句柄发送的时候,真的是将服务器对象发送给了子进程?...以优雅的方式结束进程 kill -l PID -l选项告诉kill命令用好像启动进程的用户已注销的方式结束进程。

2.6K10

深入理解Node.js 进程与线程(8000长文彻底搞懂)

Node.js 做耗时的计算时候,如何避免阻塞? Node.js如何实现多进程的开启和关闭? Node.js可以创建线程吗? 你们开发过程中如何实现进程守护的?...原因是child_process操作子进程时,可以隐式的创建多个TCP服务器,对比上面的两幅图应该能理解我说的内容。...父进程在实际创建子进程之前,会创建 IPC通道并监听它,然后才 真正的创建出 子进程,这个过程中也会通过环境变量(NODECHANNELFD)告诉子进程这个IPC通道的文件描述符。...Node.js句柄传递 讲句柄之前,先想一个问题,send句柄发送的时候,真的是将服务器对象发送给了子进程?...以优雅的方式结束进程 kill -l PID -l选项告诉kill命令用好像启动进程的用户已注销的方式结束进程。

94120
  • 您找到你想要的搜索结果了吗?
    是的
    没有找到

    深入理解Node.js 进程与线程(8000长文彻底搞懂)

    Node.js 做耗时的计算时候,如何避免阻塞? Node.js如何实现多进程的开启和关闭? Node.js可以创建线程吗? 你们开发过程中如何实现进程守护的?...原因是child_process操作子进程时,可以隐式的创建多个TCP服务器,对比上面的两幅图应该能理解我说的内容。...父进程在实际创建子进程之前,会创建 IPC通道并监听它,然后才 真正的创建出 子进程,这个过程中也会通过环境变量(NODECHANNELFD)告诉子进程这个IPC通道的文件描述符。...Node.js句柄传递 讲句柄之前,先想一个问题,send句柄发送的时候,真的是将服务器对象发送给了子进程?...以优雅的方式结束进程 kill -l PID -l选项告诉kill命令用好像启动进程的用户已注销的方式结束进程。

    1.1K30

    Node.js的底层原理

    3 子进程结束的时候,新的事件循环也就结束了,从而回到旧的事件循环。 进程间通信 接下来我们看一下父子进程间怎么通信呢?...但是如果主进程在fork子进程之后,打开了一个文件,他想告诉子进程,那怎么办呢?如果仅仅是把文件描述符对应的数字传给子进程,子进程是没有办法知道这个数字对应的文件的。...下面我们看看Node.js是如何实现线程间通信的。了解Node.js线程间通信之前,我们先看一下一些核心数据结构。 1 Message代表一个消息。...,当可写事件触发的时候,Libuv会遍历等待发送队列,逐个节点发送,成功发送后,Libuv会把节点移到发送成功队列,并往pending阶段插入一个节点,在pending阶段,Libuv就会执行发送完成队列里每个节点的会调通知调用方发送结束...发起一个查找操作的时候,Node.js会往线程池提及一个任务,然后就继续处理其他事情,同时,线程池的子线程会调用库函数做dns查询,查询结束后,子线程会把结果交给主线程。这就是整个查找过程。 ?

    2.1K20

    字节大佬带你深入分析Node.js的底层原理

    然后主进程就在新的事件循环中执行,旧的事件循环就被阻塞了。 子进程结束的时候,新的事件循环也就结束了,从而回到旧的事件循环。 5.2 进程间通信 接下来我们看一下父子进程间怎么通信呢?...但是如果主进程在 fork 子进程之后,打开了一个文件,他想告诉子进程,那怎么办呢?如果仅仅是把文件描述符对应的数字传给子进程,子进程是没有办法知道这个数字对应的文件的。...下面我们看看 Node.js 是如何实现线程间通信的。了解 Node.js 线程间通信之前,我们先看一下一些核心数据结构。 Message 代表一个消息。...最后把该 socket 注册到 epoll 中,等待连接的到来。 那么 Node.js 是如何处理连接的呢?...发起一个查找操作的时候,Node.js 会往线程池提及一个任务,然后就继续处理其他事情,同时,线程池的子线程会调用底层函数做 DNS 查询,查询结束后,子线程会把结果交给主线程。

    2.7K30

    面试官问:Node 与底层之间如何执行异步 IO 调用?

    本文你能学到: Node.js 与底层之间是如何执行异步I/O调用的?和事件循环怎么联系上的呢? 为什么说 Node 高性能,Node 的异步I/O 对高性能助力了什么?...如果面试官再问事件循环还有Node与底层之间如何执行异步I/O,我觉得你把本文的流程说清楚,应该能加分!本文对事件循环中的具体步骤没有详细讲解,每个步骤看官方文档更佳。...在 linux 下通过 epoll 实现这个过程,也就是由 libuv 自行实现。 IOCP 的另一个应用场景在之前Node.js进程与线程那篇文章也有写过。...通过创建一定数量的线程,让他们时刻准备就绪等待新任务的到达,而任务执行结束之后再重新回来继续待命。 这就是线程池最核心的设计思路,「复用线程,平摊线程的创建与销毁的开销代价」。...在创建TCP链接的过程中,libuv直接参与Tcp_wrap.cc函数中的 TCPWrap::listen() 调用uv_listen()开始到执行uv_io_start()结束。

    1.1K20

    深入浅出FaaS的两种进程模型

    当函数执行完之后,函数实例也随之结束自己的使命,FaaS 应用缩容到 0,然后开始进入节能模式 其实这里会有一些疑问:函数执行完之后实例能否不结束,让它继续等待下一次函数被调用呢?...是的,本身 FaaS 也考虑到了这种情况,所以从运行函数实例的进程角度来看,就有两种模型。我也画了张图,方便你理解。 用完即毁型:函数实例准备好后,执行完函数就直接结束。...常驻进程型:函数实例准备好后,执行完函数不结束,而是返回继续等待下一次函数被调用。这里需要注意,即使 FaaS 是常驻进程型,如果一段时间没有事件触发,函数实例还是会被云服务商销毁 ?...,持续监听 HTTP 事件,直到被云服务商控制的父进程关闭回收 当 HTTP 事件发生时,我们的 Web 服务主进程跟之前一样,创建一个子进程来处理这个请求事件。...其实从另外一个角度看,触发器就是一个常驻进程型模型一直在等待,只不过这个触发器是由云服务商处理罢了。

    53620

    深入浅出FaaS的两种进程模型

    当函数执行完之后,函数实例也随之结束自己的使命,FaaS 应用缩容到 0,然后开始进入节能模式 其实这里会有一些疑问:函数执行完之后实例能否不结束,让它继续等待下一次函数被调用呢?...是的,本身 FaaS 也考虑到了这种情况,所以从运行函数实例的进程角度来看,就有两种模型。我也画了张图,方便你理解。 用完即毁型:函数实例准备好后,执行完函数就直接结束。...常驻进程型:函数实例准备好后,执行完函数不结束,而是返回继续等待下一次函数被调用。...,持续监听 HTTP 事件,直到被云服务商控制的父进程关闭回收 当 HTTP 事件发生时,我们的 Web 服务主进程跟之前一样,创建一个子进程来处理这个请求事件。...其实从另外一个角度看,触发器就是一个常驻进程型模型一直在等待,只不过这个触发器是由云服务商处理罢了。

    97871

    Event Loop(node.js)

    所以 Node.js 的执行可以简单地分成两个阶段: 初始化代码执行 事件循环 初始化代码执行里,执行所有的同步操作代码。所谓同步操作,就是永远一步步执行、没有结果不继续执行后面代码的操作。...对应的异步操作是不等待结果就继续执行后面代码的操作。一般异步操作都带有一个回调函数,而回调函数里的操作不包括在上面说的「后面代码」里,而是异步操作完成以后希望要执行的操作,它们需要排队等待被执行。...在执行完所有同步代码以后,Node.js 查看回调队列里有没有任务,有的话就执行,没有的话就等待异步操作完成,因为带有回调任务的异步操作完成时会将回调任务入队到回调队列,这样就有任务可以执行了。...所以可以很自然地推理出,如果回调队列为空且没有需要等待完成的异步操作,这个 Node.js 进程就结束了。事实也是如此。 由上也可以知道,所有的用户代码最终都是在同一线程也就是主线程上面顺序执行的。...但是它们的存在又确实是必要的: 用户要在事件循环继续之前处理错误、清理资源 在当前执行栈之后且在事件循环之前需要执行一个回调 官方文档举了这样一个例子: const EventEmitter = require

    81920

    【Linux】进程控制

    当为0的时候表示的成功,程序结束不需要知道什么别的消息,但是非0失败的时候,就应该知道为什么程序会执行不到结果,为什么程序出现错误。...2、4、如何终止 1、main函数return,表示进程终止(非main函数,return,函数结束) 2、代码调用exit函数(注意:在代码的任意位置调用exit,都表示进程终止) 3、_exit—system...此时子进程本身就是软件,父进程本质是在等待某种软件条件就绪,那么此时该如何理解阻塞等待子进程呢?...本质就是子进程让父进程放在自己的等待队列中,让状态设置为S状态,当子进程全部调度结束的时候,再把父进程放出,在开始执行父进程。...这样的状态就像是张三是一个父进程,一直在等待着李四的子进程运行结束,结束了张三才能继续他自己原本的事情。

    7110

    CompletableFuture 异步处理

    程序本就不应该浪费等待的时间,⽽应该更加⾼效地利⽤,在等待的时间执⾏其他任务,回复到达后在继续执⾏ 第⼀个任务。 如果程序调⽤某个⽅法,等待其执⾏全部处理后才能继续执⾏,我们称其为同步。...异步编程相对于单体线程而言,不像单体编程那样等上面的代码执行完才能执行下面的 ,他是可以同时多部分一起进行执行行的,在代码运行过程能大大节省时间提升效率,提升用户体验; CompletableFuture...典型的异步编程模型比如Node.js 举个通俗的例子: 你打电话问书店老板有没有《黑道是怎么炼成》这本书,如果是同步通信机制,书店老板会说,你稍等,”我查一下",然后开始查啊查,等查好了(可能是5秒,...阻塞:进程给CPU传达一个任务之后,一直等待CPU处理完成,然后才执行后面的操作。 非阻塞:进程给CPU传达任我后,继续处理后续的操作,隔断时间再来询问之前的操作是否完成。这样的过程其实也叫轮询。...阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态.阻塞调用是指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回。

    8110

    Linux:进程的创建、终止和等待

    1.3 fork函数存在的意义 fork函数常规用法: 1、一个父进程希望复制自己,使父子进程同时执行不同的代码段。例如,父进程等待客户端请求,生成子进程来处理请求。...所以进程结束后应该优先判断该进程是否异常了,然后才能确定退出码能不能用!!   ...,还可以发生在父进程在等待子进程结束从而获取他的状态。       ...于是这次你换了一个思路,在小张告诉你再等会的时候,你就要求他不要挂断电话,直到下楼的时候再挂,这样我可以随时知道你的情况      这个过程其实就是阻塞!!...,没等待完一个子进程就去统计一下 2、创建很多的子进程,但是具体哪个先去执行是由调度器决定的,但是我们必须知道的就是最后一个结束的必然就是父进程,因为子进程都是他创建的,所以他理所应当去回收所有的子进程

    20110

    【Linux修炼】11.进程的创建、终止、等待、程序替换

    ,这样在main()函数中调用fork函数时,从fork返回的两个执行流就会分别执行main()调用fork之后的代码,因此我们之前所了看到的两个结果就是父子进程对应的执行流所造成的。...任意地方调用 exit(code)退出 code为退出码,下面就演示一下: 结果显而易见,当我们查看这个进程是如何结束的,直接观察退出码: 此外,在函数内部exit时,进程也会直接结束,函数也不会有返回值...对于阻塞等待,我们上面已经演示过,那么下面就直接上非阻塞状态的过程: 对于这段代码,设计理念是这样的:子进程在执行期间,父进程则会一直等待并通过while的方式去轮询非阻塞状态,直到子进程退出。...二、函数的具体原理及演示 下面就来演示其他几个例子: execlp(const char *file, const char *arg, …) p:path,不用告诉我程序的路径,只有告诉这个函数传入的名字...在上面实现的shell模拟代码中,我们fork出了子进程,子进程有自己的工作目录,因此cd更改的是子进程的工作目录,子进程执行完毕,继续用的是父进程,就是我们的shell,因此在这个过程中父进程也就是shell

    6.2K00

    【Linux系统编程】—— 进程替换及其在操作系统中的应用与实现

    一张图片先了解大概其原理: 单进程替换 这张图描述了操作系统在进程替换过程中如何通过 PCB 保存进程的状态、如何管理进程的内存(如代码段、数据段和页表)、以及如何将这些信息存储到磁盘中,并在需要时进行恢复...父进程部分 wait(NULL); // 等待子进程结束 printf("父进程继续运行......\n"); run_process(&process); // 父进程继续运行 // 等待所有子进程结束 wait(NULL); }...进程开始运行... 进程进入 I/O 等待... 保存进程状态... 磁盘读取完成,恢复进程... 恢复进程状态... 进程继续执行并结束。 父进程继续运行... 进程开始运行......进程进入 I/O 等待... 保存进程状态... 磁盘读取完成,恢复进程... 恢复进程状态... 进程继续执行并结束。

    8700

    Docker 容器环境下 Node.js 应用程序的优雅退出

    ) 为 npm 的进程 ID,到这里也需你就知道了 npm start 的启动机制,认为 npm 会将 Node.js 服务做为自己的子进程启动,暂时是没有问题的,继续往下看。...,控制台执行 curl http://localhost:30010/delay 请求,同时我又新打开另一个控制台立即执行 kill -15 68970 这个时间是在 5 秒中之内,可以看到我的请求得到了一个错误的响应...,即进程树的概念,当容器退出时也会通过信号量来通知 PID=1 的进程,然后这个会通知自己的子进程等等,这个涉及 Unix 进程相关知识,父进程会等待所有子进程结束,并获取到最终的状态。...消除中间的 sh 进程 这种方案是在 npm 启动之后,消除 npm 与 node 之间的 sh 进程, execnode app.js,简单解释下 exec 会用新的进程去替换之前的进程,这样之前的...Egg 框架的项目中进行测试时,并没有如上的这些问题,以下是在容器内打印的进程树,可以看到 npm 的进程 id 为 1,之后就直接为 node 进程,这应该是框架内自己做的处理,感兴趣的可以去研究下实现机制

    1.9K00

    并发模型比较

    A 调完 B,就在调用处等待(阻塞),直到 B 方法返回才继续执行剩下的代码,这就是阻塞调用。而非阻塞是 A 方法调用 B 方法,B 方法立即返回,A 可以继续执行下面的代码,不会被该调用阻塞。...多进程 主进程监听和管理连接,当有客户请求的时候,fork 一个子进程来处理连接,父进程继续等待其他客户的请求。但是进程占用服务器资源是比较多的,服务器负载会很高。 Apache 是多进程服务器。...Node.js的事件循环对开发者不可见,由 libev 库实现,libev 不断检查是否有活动的、可供检测的事件监听器,直到检查不到时才退出事件循环,程序结束。...这种机制的缺点是,会造成大量回调函数的嵌套,代码可读性不佳。因为没有多线程,在多核的机器上,也没办法实现并行执行。...参考: 如何理解 Golang 中“不要通过共享内存来通信,而应该通过通信来共享内存”? Golang源码探索(二) 协程的实现原理 Goroutine(协程)为何能处理大并发?

    2K00

    Dcoker 容器环境下 Node.js 应用程序的优雅退出

    ) 为 npm 的进程 ID,到这里也需你就知道了 npm start 的启动机制,认为 npm 会将 Node.js 服务做为自己的子进程启动,暂时是没有问题的,继续往下看。...,控制台执行 curl http://localhost:30010/delay 请求,同时我又新打开另一个控制台立即执行 kill -15 68970 这个时间是在 5 秒中之内,可以看到我的请求得到了一个错误的响应...,即进程树的概念,当容器退出时也会通过信号量来通知 PID=1 的进程,然后这个会通知自己的子进程等等,这个涉及 Unix 进程相关知识,父进程会等待所有子进程结束,并获取到最终的状态。...消除中间的 sh 进程 这种方案是在 npm 启动之后,消除 npm 与 node 之间的 sh 进程, execnode app.js,简单解释下 exec 会用新的进程去替换之前的进程,这样之前的...Egg 框架的项目中进行测试时,并没有如上的这些问题,以下是在容器内打印的进程树,可以看到 npm 的进程 id 为 1,之后就直接为 node 进程,这应该是框架内自己做的处理,感兴趣的可以去研究下实现机制

    1.3K10

    并发模型比较

    在讨论几种 I/O 模型之前,先介绍一下同步/异步、阻塞/非阻塞的概念,以及操作系统的知识。 ---- 同步/异步?阻塞/非阻塞?...A 调完 B,就在调用处等待(阻塞),直到 B 方法返回才继续执行剩下的代码,这就是阻塞调用。而非阻塞是 A 方法调用 B 方法,B 方法立即返回,A 可以继续执行下面的代码,不会被该调用阻塞。...多进程 主进程监听和管理连接,当有客户请求的时候,fork 一个子进程来处理连接,父进程继续等待其他客户的请求。但是进程占用服务器资源是比较多的,服务器负载会很高。 Apache 是多进程服务器。...Node.js的事件循环对开发者不可见,由 libev 库实现,libev 不断检查是否有活动的、可供检测的事件监听器,直到检查不到时才退出事件循环,程序结束。...这种机制的缺点是,会造成大量回调函数的嵌套,代码可读性不佳。因为没有多线程,在多核的机器上,也没办法实现并行执行。

    2.9K00

    Linux系统编程:进程控制(创建,终止,等待)

    1.在fork返回之前,创建了子进程的 PCB数据结构,以及拷贝了一份父进程的地址空间和页表;此时页表是出于只读,一旦修改就会写实拷贝; 2.在修改之前,虚拟地址都是一样的,且映射的物理地址也是一样的;...查看上一个进程的退出码 1.在main函数中return 2.调用exit 3.调用_exit 2.2main函数返回值 main函数虽然是主函数,但毕竟也是个函数,最后的返回值即使告诉操作系统是否正常结束...退出码的作用就是告诉父进程,子进程的退出状态-是正常结束了还是出现错误终止了; 2.为什么要用退出码判断进程是否出错,直接printf不好吗?...,有的时候我们需要知道子进程的结果,然后继续执行后序的代码,这个时候就需要等待子进程完成任务后,获取子进程的退出码看看他完成的怎么样了; 2.避免僵尸进程:子进程先父进程结束会出现僵尸状态,造成进程卡死...,那么父进程将不会一直阻塞,而是会返回0后继续执行后面的代码,如果子进程退出了,那么返回子进程的PID; 返回值: 正常执行(没有设置WNOHANG):此时和wait一样; 等待成功就会返回子进程pid

    11410

    Linux系统编程:进程状态和进程优先级nice

    为了方便理解,讲一个故事: 比方说我们现在编译了一段代码,需要将1GB的文件写入磁盘中,内存需要跟磁盘建立联系,磁盘在被写入之前需要判断该行为是否可以被执行,比方说现在磁盘中的空间不足1GB,那么这个请求就应该被驳回...当磁盘想要回应的时候却发现那个等待自己的进程没有了,那么现在写入失败了怎么办?我是应该继续尝试呢,还是丢掉呢??此时不同的操作系统有不同的做法。 比如是在银行,某些数据丢失导致损失了几个亿!!...这个时候法官 叫来了 操作系统、进程、磁盘 三个人,来这个过程应该是谁的错,第一嫌疑人是操作系统,因为操作系统杀进程了,操作系统说:“请问我是否履行了自己的职责,我是否是在比较极端的情况下去杀进程的,...磁盘说:“这不怪我,我就是个跑腿的,我在写入的时候就告诉他可能会失败了,所以我让他在那里等我的结果,可是他人不见了,而是丢失是因为我还有其他工作得做,如果我有错的话,那我们是不是得把磁盘所有逻辑都改了?...子进程先父进程结束,而父进程并没有回收子进程的资源,这个时候子进程就会保持僵尸状态等待父进程回收; 如果父进程到了最后也不回收子进程,是不是就会造成泄露?

    6600
    领券