如果nodejs使用非阻塞IO,如何实现fs.readFileSync? [英] If nodejs uses non blocking IO, how is fs.readFileSync implemented?

查看:311
本文介绍了如果nodejs使用非阻塞IO,如何实现fs.readFileSync?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在文件系统库中看到了许多同步功能.例如fs.readFileSync(filename, [options]).

I see a lot of synchronous functions in the file system library. such as fs.readFileSync(filename, [options]).

如果节点具有异步/非阻塞IO并且没有睡眠方法,这些功能将如何实现(以及为什么实现)-我可以使用相同的机制来实现其他同步功能吗?

How (and why) are these functions implemented if node has async/non-blocking IO and no sleep method - and can I use the same mechanism to implement other synchronous functions?

推荐答案

fs.readFileSync()

真的只是

fs.readSync() 

功能.因此,问题是与fs.read()相比,fs.readSync()的实现方式如何.如果您查看这两个函数的实现,它们都将利用绑定模块.在这种情况下,哪个被初始化为

function. So the question is how is fs.readSync() implemented compared to fs.read(). If you look at the implementations of these two functions they both take advantage of the bindings module. Which in this case is intialized to

var binding = process.binding('fs').  

而电话是

binding.read(fd, buffer, offset, length, position, wrapper);//async
var r = binding.read(fd, buffer, offset, length, position);//sync

分别.进入绑定"模块后,我们进入了v8,node _ ######.cc登陆.绑定('fs')的实现可以在节点库代码中的node_file.cc中找到.节点引擎为C ++调用提供了重载,一个实现了回调,一个没有实现. node_file.cc代码利用了req_wrap类.这是v8引擎的包装.在node_file.cc中,我们看到以下内容:

Respectively. Once we're in the "binding" module, we are out in v8, node_#####.cc land. The implementation of binding('fs') can be found in the node repository code, in node_file.cc. The node engine offers overloads for the C++ calls, one taking a callback, one that does not. The node_file.cc code takes advantage of the req_wrap class. This is a wrapper for the v8 engine. In node_file.cc we see this:

#define ASYNC_CALL(func, callback, ...)                           \
  FSReqWrap* req_wrap = new FSReqWrap(#func);                     \
  int r = uv_fs_##func(uv_default_loop(), &req_wrap->req_,        \
      __VA_ARGS__, After);                                        \
  req_wrap->object_->Set(oncomplete_sym, callback);               \
  req_wrap->Dispatched();                                         \
  if (r < 0) {                                                    \
    uv_fs_t* req = &req_wrap->req_;                               \
    req->result = r;                                              \
    req->path = NULL;                                             \
    req->errorno = uv_last_error(uv_default_loop()).code;         \
    After(req);                                                   \
  }                                                               \
  return scope.Close(req_wrap->object_);

#define SYNC_CALL(func, path, ...)                                \
  fs_req_wrap req_wrap;                                           \
  int result = uv_fs_##func(uv_default_loop(), &req_wrap.req, __VA_ARGS__, NULL); \
  if (result < 0) {                                               \
    int code = uv_last_error(uv_default_loop()).code;             \
    return ThrowException(UVException(code, #func, "", path));    \
  }

请注意,SYNC_CALL使用了不同的req-wrap.这是req_wrap.h中找到的ASYNC方法的相关req_wrap构造函数的代码.

Notice that the SYNC_CALL uses a different req-wrap. Here is the code for the relevant req_wrap constructor for the ASYNC method, found in req_wrap.h

ReqWrap() {
    v8::HandleScope scope;
    object_ = v8::Persistent<v8::Object>::New(v8::Object::New());

    v8::Local<v8::Value> domain = v8::Context::GetCurrent()
                                  ->Global()
                                  ->Get(process_symbol)
                                  ->ToObject()
                                  ->Get(domain_symbol);

    if (!domain->IsUndefined()) {
      // fprintf(stderr, "setting domain on ReqWrap\n");
      object_->Set(domain_symbol, domain);
    }

    ngx_queue_insert_tail(&req_wrap_queue, &req_wrap_queue_);
  }

请注意,此函数正在创建一个新的v8范围对象以处理此事件的运行.这是异步内容的异步部分发生的地方. v8引擎启动了一个新的javascript解释环境,以单独处理此特定调用.简而言之,如果不构建/修改自己的节点版本,就无法以与节点相同的方式实现自己的异步/同步版本的调用.话虽这么说,异步实际上仅适用于I/O操作.可能是为了说明为什么您认为自己需要使事情更加同步.通常,如果您认为节点不支持您想做的事情,那么您就不会将回调机制发挥到最大潜力.

Notice that this function is creating a new v8 scope object to handle the running of this event. This is where the asynchronous portion of async stuff happens. The v8 engine launches a new javascript interpreting environment to handle this particular call separately. In short, without building/modifying your own version of node, you cannot implement your own asynchronous/synchronous versions of calls, in the same way that node does. That being said, asynchronous really only applies to I/O operations. Perhaps a description of why you think you need things to be more synchronous would be in order. In general, if you believe node doesn't support something you want to do, you just aren't embracing the callbacks mechanism to it's full potential.

话虽如此,如果您需要异步行为,则可以考虑使用事件节点模块来实现自己的事件处理程序.而且,如果您迫切需要同步执行某些操作,则可以考虑使用本机扩展,但是,我强烈建议您这样做.考虑如何在异步事件循环中工作以这种方式完成所需的工作.接受这种思维方式,或切换到另一种语言.

That being said, you could consider using the events node module to implement your own event handlers if you need async behavior. And you can consider native extensions if there are things you desperately need to do synchronously, however, I highly recommend against this. Consider how you can work within the asynchronous event loop to get what you need to do done this way. Embrace this style of thinking, or switch to another language.

强迫一种语言以一种不想处理的方式来处理事物,这是编写不良代码的绝佳方法.

Forcing a language to handling things a way it doesn't want to handle them is an excellent way to write bad code.

这篇关于如果nodejs使用非阻塞IO,如何实现fs.readFileSync?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆