Ruby Guide to *nix Plumbing (Eleanor McHugh)

Eleanor McHugh, a physicist by training, will be talking about how to make *nix systems work naturally within the Ruby environment.

The Unix Way

Eleanor actually hates Unix, but recognizes that it’s a very effective operating system for getting things done. It’s DRY: build little things, build them well, don’t build them twice. There’s a natural marriage between agile Ruby and the Unix philosophy.

Unix provides basic services which make it a very useful OS to “muck about with”:

virtual memory

process management

hierarchical file system

user permissions

interprocess communication

Ruby provides some “really lovely” utilities:

Kernel.system

Kernel.spawn

IO.popen

Open3.popen3

However, if you’re doing a lot of IO, you end up doing a lot of select()s and keeping a lot of file descriptors open.

System Calls with Ruby DL

DL, which Ruby delivers out of the box, is a way to wrap a C library with a Ruby call. This is a nice way to access the underlying kernel system calls without relying on the Ruby IO implementations.

This is superior to Ruby’s syscall, in that you can actually get results back from the function call.

Using mmap allows you to do much faster memory reads, rather than do slower file reads.

Using kqueue/epoll/inotify allows you to build evented ruby (like EventMachine, but without EventMachine).

Using pipes allows you to build efficient IPC.

The drawback is that using DL means more verbose code, and more error prone code. (Pointer math FTL!) So, for things like sockets, use the Ruby API unless you specifically need kernel-level eventing.

Multicore

The lack of real thread support in Ruby can be addressed by using multiple processes, held together with IPC (sockets, pipes, memory mapped files). This is the traditional “Unix way” for handling multiple processes.