计算器不能直接的理解高级语言,只能理解机器语言,因此必须把高级语言翻译为机器语言,翻译的方式有两种,一个是编译,一个是解释。java
解释性语言的程序不须要编译,它是在运行程序的时候进行翻译,好比java,专门有一个解释器能够直接执行Java程序,每个语句都是执行的时候才能翻译,编译型就是编译的时候直接编译成机器能够执行的,编译和执行时分开的,可是不能跨平台。由于翻译只作了一次,运行的时候不须要再去翻译,因此编译型语言的程序执行效率高。node
对于解释性语言,程序运行时的控制权在解释器而不在于程序,对于编译型语言程序运行时的控制权在程序。web
后台进程是一直运行的服务端程序,又称为守护进程,一般是在系统后台运行,没有控制终端,不与前台交互,通常做为系统服务使用。其称为后台进程的缘由大部分是由于它没有控制端,没法和前台的用户交互。npm
相对应的前台进程,就是咱们在终端中开启的进程,例如咱们在终端中npm run server.js启动一个webServer,此时启动的进程就是前台进程,当你把当前的命令行终端进行关闭了以后,该进程也便被杀死了。缓存
表面上来看,这两组的概念都差很少,阻塞/非阻塞IO,是操做系统内核对于IO的两种处理方式,对于阻塞IO,好比读取文件,操做系统在读取完文件以后,才会给应用程序返回结果,这一段过程呢,应用程序在等待操做系统的回复,是为应用层面的同步IO。异步
对于非阻塞IO,操做系统在接收到应用程序对于读取文件的请求时,当即返回给应用程序一个结果,可是应用程序怎么知道操做系统完成了IO操做呢?这时候应用程序就会对操做系统发起询问(你到底好了没有?人家都快急死了),发起询问的方法又通过好几种演变,好比read、poll、epoll等,中间多的无非就是根据文件描述符减小询问的次数,整体上来讲这种方式很差。并不能达到咱们理想的异步IO。函数
那么从应用程序方面来将,咱们指望的异步IO,就是应用程序进行了IO操做以后,再也不须要操心操做系统何时返回,去执行下边的代码就好了,当操做执行完了以后呢,直接给应用程序发信息告诉他就好了。Linux系统下原生提供了一种AIO是经过信号或者回调来传递数据的,这个AIO就是咱们的理想的异步IO。可是不幸的是只有Linux中有,并且没法利用系统缓存。操作系统
node(单线程)中对于*nix平台而言,采用的是线程池+epoll异步IO模拟实现应用程序层面的异步IO,主线程进行执行程序,碰到咱们异步IO调用时,将改异步IO分配给线程池中的某一个线程,而后就变成了线程池中的某个线程和操做系统的阻塞IO进行IO操做,当IO线程接收到操做系统的阻塞IO执行的返回结果以后,IO线程再发送时间给主线程。命令行
node中对于window平台而言,是依靠于IOCP来实现的,其内部仍然是线程池原理,不一样之处在于这些线程池由系统内核接手管理。线程
对于异步IO的实现,其中有几个组成部分:事件循环、观察者、请求对象
事件循环是node中的一种执行机制,这种机制是回调执行的基础部分,它保证了咱们的回调函数可以被执行。
观察者是暴露回调函数的窗口,若是总体的场景为饮料工厂的话,咱们的瓶子就是咱们的回调函数,事件循环就是传送带在那一直转,而观察者就是瓶子就如机器的入口,机器就是咱们的应用程序。因此应用程序从观察者这里获取事件,应用程序询问观察者是否还有事件。
请求对象,是应用程序封装的一个对象,里边包含了要作的IO操做类型,以及回调函数。
总体流程就是,异步调用开始以后,应用程序封装一个请求对象,送入咱们的线程池中的某个线程,该线程和操做系统的非阻塞IO经过epoll机制进行工做,这其中,会有观察者在线程池中进行检查,当某个线程的IO操做完成以后,观察者会将回调函数(封装在请求对象中的)放在事件循环上(上段提到的传送带),而后主线程调用回调函数。
参考:《深刻浅出Node.js》
问题思考: