An (abridged) Ruby Plumber's Guide to *nix

14
An (abridged) Ruby Guide to *nix Plumbing The fun of a little knowledge applied unwisely http://slides.games-with-brains.net

description

The Lightning-Talk version of A Ruby Plumber's Guide to *nix.

Transcript of An (abridged) Ruby Plumber's Guide to *nix

Page 1: 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

Page 2: An (abridged) Ruby Plumber's Guide to *nix

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

Page 3: An (abridged) Ruby Plumber's Guide to *nix

processesKernel.system

Kernel.spawn

Kernel.fork

Kernel.exec

IO.popen

Page 4: An (abridged) Ruby Plumber's Guide to *nix

filesIO.for_fd

IO.sys[open | read | write | seek]

Kernel.select

Fcntl

Page 5: An (abridged) Ruby Plumber's Guide to *nix

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

Page 6: An (abridged) Ruby Plumber's Guide to *nix

interprocess communicationIO.pipe

sockets

Signal

Page 7: An (abridged) Ruby Plumber's Guide to *nix

accessing the *nix kernelKernal.syscall

ruby/dl

Page 8: An (abridged) Ruby Plumber's Guide to *nix

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

Page 9: An (abridged) Ruby Plumber's Guide to *nix

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

Page 10: An (abridged) Ruby Plumber's Guide to *nix

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

Page 11: An (abridged) Ruby Plumber's Guide to *nix

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

Page 12: An (abridged) Ruby Plumber's Guide to *nix

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!

Page 13: An (abridged) Ruby Plumber's Guide to *nix

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