Download - An (abridged) Ruby Plumber's Guide to *nix
An (abridged) Ruby Guide to*nix PlumbingThe fun of a little knowledge applied unwisely
http://slides.games-with-brains.net
unix favours agilityonly build what you need
reuse what you already have
change your tools as [des | requ]ired
use scripts and text files where possible
processesKernel.system
Kernel.spawn
Kernel.fork
Kernel.exec
IO.popen
filesIO.for_fd
IO.sys[open | read | write | seek]
Kernel.select
Fcntl
require 'fcntl'filemode = Fcntl::O_CREAT | Fcntl::O_RDWR | Fcntl::O_APPENDdescriptor = IO.sysopen “test.dat”, filemodefile = IO.for_fd descriptorfile.syswrite “hello”file.sysseek 0file.sysread 10
produces:hello
wrapping a file descriptor
interprocess communicationIO.pipe
sockets
Signal
accessing the *nix kernelKernal.syscall
ruby/dl
a fragile approach
the native syscall is a very primitive interface
error codes
file descriptors & pointer addresses
modifiable buffers
ruby syscall doesn’t support modifiable buffers
but it does wrap errors as Errno exceptions
IO.sysx the hard wayOn MacOS X
file = syscall 5, “test.dat”, 1syscall 4, file, “some text\n”, 10syscall 3, file, “”, 5syscall 6, file
produces:Errno::EFAULT: Bad address
# open O_WRONLY (fcntl.h)# write# read# close
should be Errno::EBADF
posix semaphoresprocess 1
require ‘fcntl’Open, Wait, Post, Close = 268, 271, 273, 269s = syscall Open, “/tmp/s”, Fcntl::O_CREAT, 1911syscall Wait, sputs “locked at #{Time.now}”sleep 50puts “posted at #{Time.now}”syscall Post, ssyscall Close, s
produces:
locked at Thu May 28 01:03:23 +0100 2009posted at Thu May 28 01:04:13 +0100 2009
process 2
Open, Wait, TryWait, Post = 268, 271, 272, 273s = syscall Open, “/tmp/s”begin
t = Time.nowsyscall TryWait, sputs “locked at #{t}”
rescue Exception => eputs “busy at #{t}”syscall Wait, sputs “waited #{Time.now - t} seconds”
end
produces:
busy at Thu May 28 01:03:36 +0100 2009waited 47.056508 seconds
ruby/dl
part of the standard library since ruby 1.8
access to dynamically loaded libraries
.dll on windows
.so and .dylib on unix
supports C-style memory access
and callback functions written in Ruby
memory management
memory pointers encapsulated by DL::PtrData
garbage collected
uses free() or a custom deallocator
handles realloc() automatically
plays nicely with ruby strings and arrays
[String | Array].to_ptr
PtrData.struct! and PtrData.union!
require ‘dl’CRT = DL.dlopen ‘libc.dylib’F = ‘syscall’
def open file, modeCRT[F, ‘IISI’].call(5, file, mode)[0]
end
def write fd, string, bytes = string.lengthCRT[F, ‘IIISI’].call(4, fd, string, bytes)[0]
end
def read fd, bytes = 1buffer = DL.malloc(bytes)CRT[F, ‘IIIsI’].call(3, fd, buffer, bytes)[1][2]
end
def close fdCRT[F, ‘III’].call(6, fd)[0]
end
file = open “test.dat”, 0x0209write file, “text\n”close file
file = open “test.dat”, 0x0000text = read file, 10close file
http://slides.games-with-brains.net
http://www.jbrowse.com/text/rdl_en.html
http://www.kegel.com/c10k.html
http://www.ecst.csuchico.edu/~beej/guide/ipc/
http://beej.us/guide/bgnet/
http://wiki.netbsd.se/kqueue_tutorial
further reading