NodeOS / NodeOS

Lightweight operating system using Node.js as userspace
http://node-os.com
MIT License
6.95k stars 608 forks source link

Complete Linux/POSIX Interface #21

Open groundwater opened 10 years ago

groundwater commented 10 years ago

As part of this project, I would like to complete a Linux and/or POSIX system call interface in node. This should take the form of many small modules, rather than one big module providing everything.

The lowest levels should not do much more than wrap native syscalls, mapping arguments between the Javascript and C types.

I have kind of started this, but I think it's worth forking out as its own ongoing project.

cc @aulvi

groundwater commented 10 years ago

So, I have thought about using ffi for this, but given how stable syscalls are, I think it's worth wrapping them at the C layer.

I do think it's worth using a library like nan or node addon layer to abstract away the v8-specifics.

My biggest question here is organization. I think any organization is fine, as long as it's clear and easy to find modules. I don't mind a little manual work either, e.g. if a data type is defined in one module, but consumed in another, if it keeps things simple.

I think the todos are:

Any suggestions or example for item (1) are appreciated.

cc/ @jwerle

jwerle commented 10 years ago

I really prefer NAL over NAN. NAN has a lot of magic I don't like, and NAL just feels like C :].

If we use NAL or NAN I think it is worth creating some common interface on top of it that will yield some sort of paradigm for adopters to use. Much like how commonjs became what is today from its acceptance/adoption.

How are you thinking about defining how users interface with syscalls ?

Right now there structure is defined:

+-----------+
| hardware  |
+-----------+
| kernel    |
+-----------+
| init/root | <---  this piece is node-os
+-----------+
| userland  |
+-----------+

What do we want to expose after init/root ? I assume this is where low level bindings will occur, right before userland.

miketheprogrammer commented 10 years ago

I have to say, In terms of abstraction layers. Isn't the node team planning to release its own abstraction layer @ 1.0 If so I would suggest waiting for that time. Stabilizing nodeos around 1.0 and using the provided abstraction layer. The closer to core the project stays, the more maintainable it should be imo.

@jwerle yea NAN is just macros, and its definitely a leaky abstraction, and only for those wanting to target all node versions.

groundwater commented 10 years ago

syscalls are just exposed in node modules. If your app needs to call ioctl for example, it needs to require the sys-ioctl (or whatever we call it) module and use our defined api.

I do this already in a very janky fashion, see src-reboot for an example.

@jwerle it doesn't really make sense to talk about exposing syscalls after init. They are exposed as a node module that can be included in any node process. The modules are hosted on npm, and can be included by processes run as root, such as init, or any other user process.

@miketheprogrammer if NAL is going to merge into 1.0, it's relatively easy to keep those things in lock-step. I'll consult lord-master @tjfontaine on the matter.

tjfontaine commented 10 years ago

all this talk of syscalls and node gives me visions of Go, in any event node-addon-layer will be included in v1.0 and it will also be a module that works against v0.8~v0.12

groundwater commented 10 years ago

I guess node-addon-layer is the winner.

miketheprogrammer commented 10 years ago

Sounds great. I would love to contribute in any way that I can. Let the mad science run free. On Mar 3, 2014 8:38 PM, "Jacob Groundwater" notifications@github.com wrote:

I guess node-addon-layer is the winner.

Reply to this email directly or view it on GitHubhttps://github.com/NodeOS/NodeOS/issues/21#issuecomment-36583122 .

groundwater commented 10 years ago

I pulled this from the syscall Wikipedia page where they break system calls down into one of 5 categories. This seems like a good starting point.

If this doesn't break down naturally into small modules, I would consider a mega-monster module. It would be easier to manage that mega module from a build/test/integrate point of view.

jwerle commented 10 years ago

@groundwater I think that is a good starting point too

miketheprogrammer commented 10 years ago

@groundwater I would consider each of the 5 categories their own mega monster module. A self contained unit of functionality, even if they have cross dependencies it would be nice for them to be logically seperate.

aulvi commented 10 years ago

Agreed. On Mar 4, 2014 7:15 AM, "Michael Hernandez" notifications@github.com wrote:

@groundwater https://github.com/groundwater I would consider each of the 5 categories their own mega monster module. A self contained unit of functionality, even if they have cross dependencies it would be nice for them to be logically seperate.

Reply to this email directly or view it on GitHubhttps://github.com/NodeOS/NodeOS/issues/21#issuecomment-36634290 .

groundwater commented 10 years ago

Update, for simple argument passing, we can map integers and strings between JS-C++ pretty easily.

For syscalls requiring more complex data structures, we're going to use node buffers. The buffer can be written to directly from JavaScript, and the C++ side can extract the buffer point.

The JS side

var b = new Buffer(x);
var ret = ioctl(fd, SIOCGIFNAME, b);

if (ret) {
  // b is a buffer containing a valid c-struct
  success(b);
} else {
  fail();
}

The C++ side

static Handle<Value> Ioctl(const Arguments& args) {
  HandleScope scope;

  // no error checking here sucka
  // don't pass in bad data

  int sfd = Handle<Number>::Cast(args[0])->Value();
  int com = Handle<Number>::Cast(args[1])->Value();

  // this should be a buffer
  Local<Object> buffer = args[2]->ToObject();

  // extract the pointer to the head of the buffer
  // if we did things right, this should point to our struct
  void* req = buffer->GetIndexedPropertiesExternalArrayData();

  // this is the syscall
  int res = ioctl(sfd, com, req);

  // bubble the return back to JS land
  return scope.Close(Integer::New(res));
}

I'm kind of just jotting notes down, I'll fill in the details soon.

groundwater commented 10 years ago

Thanks to @tjfontaine for some pointers on a better way to write this

#include <sys/ioctl.h>
#include <v8.h>
#include <node.h>

using namespace v8;
using namespace node;

namespace NodeOS
{

  static Handle<Value> Ioctl(const Arguments& args) {
    HandleScope scope;

    // error checks
    if (!args[0]->IsInteger())
      return ThrowException(Exception::TypeError(String::New("Argument 0 Must be an Integer")));

    if (!args[1]->IsInteger())
      return ThrowException(Exception::TypeError(String::New("Argument 1 Must be an Integer")));

    if (!Buffer::HasInstance(args[2]))
      return ThrowException(Exception::TypeError(String::New("Argument 2 Must be a Buffer")));

    // convert arguments
    int   sfd = args[0]->IntegerValue();
    int   com = args[1]->InteverValue();
    void* req = Buffer::Data(args[2]);

    // syscall
    int res = ioctl(sfd, com, req);

    // return value
    return scope.Close(Integer::New(res));
  }

}
santigimeno commented 10 years ago

@groundwater I was thinking about implementing a ioctl module along these lines and found your code here. Are you planning on publishing a standalone ioctl module? Thanks!

groundwater commented 10 years ago

Hey @santigimeno I'm looking at moving all my syscall stuff through ffi.

If you wanted to run with an ioctl module, I'm all for it. Maybe I can even leverage it. If you wanted to discuss the idea too, I have a few lessons learned I can share.

Point me to a repo if you start something, I'll try to contribute.

santigimeno commented 10 years ago

@groundwater here's my initial work: https://github.com/santigimeno/node-ioctl. There are some examples here: https://github.com/santigimeno/node-ioctl/tree/master/examples

groundwater commented 10 years ago

@santigimeno sorry I didn't reply to this earlier. This is awesome.

I want to start a collection of these on http://npkg.org, where we can list done, and wanted modules. See #31.

mitsukaki commented 8 years ago

This is a really good idea! Someone please grab charge of this