<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"><channel><title>Practicing Ruby</title><link>http://blog.rubybestpractices.com/</link><description>Solve Interesting Problems -- Write Better Code</description><language>en-us</language><item><title>USP: Handling excessive CPU Usage within a Process</title><description>&lt;p&gt;If you&amp;#8217;ve ever had issues with a runaway process eating up &lt;span class="caps"&gt;CPU&lt;/span&gt; time and want to kill it automatically, it&amp;#8217;s possible to use Process.{get,set}rlimit and a signal handler for &lt;span class="caps"&gt;SIGXCPU&lt;/span&gt; to accomplish this.&lt;/p&gt;
&lt;p&gt;The following snippet of code implements an example of a &lt;span class="caps"&gt;CPU&lt;/span&gt; limiter.  This self-contained example aborts itself once &lt;span class="caps"&gt;CPU&lt;/span&gt; utilization reaches 50%.&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
# Users of older Rubies may want to use Process::RLIMIT_CPU
# instead of :CPU in this code.

soft, hard = Process.getrlimit(:CPU)
last_update = Time.now
max_cpu_time = 5

# this signal handler runs once we've hit max_cpu_time:
trap(:XCPU) do

 # Calculate CPU utilization based on elapsed (wall clock) time
 # and max_cpu_time
 elapsed = Time.now - last_update
 cpu_usage = max_cpu_time / elapsed
 puts "CPU utilization: #{"%0.2f" % (cpu_usage * 100)}"
 if cpu_usage &amp;gt; 0.5 # 50%
   abort "CPU utilization exceeded 50%"
 end

 # If we're below our CPU usage threshold, install a new limit based on
 # current Process.times
 last_update = Time.now
 t = Process.times
 Process.setrlimit(:CPU, max_cpu_time + t.utime.round + t.stime.round, hard)

 # We now return to our regularly scheduled looping ...
end


# Install an initial limit for max_cpu_time using existing process times
t = Process.times
Process.setrlimit(:CPU, max_cpu_time + t.utime.round + t.stime.round, hard)

# The signal handler registered for :XCPU will run automatically
# after the CPU time hits max_cpu_time seconds
loop do
 # do something to use the CPU...
 100000.times { 1 + 1 }

 # you can change the amount of time slept to influence CPU utilization
 sleep 0.01
end
&lt;/pre&gt;
&lt;p&gt;I learned this example a few years ago from reading the PulseAudio source code:&lt;/p&gt;
&lt;pre name="code" class="shell"&gt;
       $ git clone git://git.0pointer.de/pulseaudio
       $ $EDITOR src/daemon/cpulimit.c
&lt;/pre&gt;
&lt;p&gt;GPLv3 does &lt;em&gt;not&lt;/em&gt; cover this message, which is CC0: To the extent possible under law, Eric Wong has waived all copyright and related or neighboring rights to the contents of this message.&lt;/p&gt;</description><author>normalperson@yhbt.net (Eric Wong)</author><pubDate>Tue, 27 Mar 2012 01:11:00 -0400</pubDate><link>http://blog.rubybestpractices.com/posts/ewong/017-Handling-excessive-CPU-Usage-within-a-Process.html</link><guid>http://blog.rubybestpractices.com/posts/ewong/017-Handling-excessive-CPU-Usage-within-a-Process.html</guid></item><item><title>USP: Implementing signal handlers - some caveats</title><description>&lt;h2&gt;Signal handlers may run at any time&lt;/h2&gt;
&lt;p&gt;If your program receives a signal, Ruby will invoke the associated signal handler as soon as it is able to.  This means a signal handler can hijack your existing code flow just about anywhere in your program (including inside methods of any libraries you use).  Normal code execution resumes once the signal handler finishes execution.&lt;/p&gt;
&lt;p&gt;This is a big difference from most event-driven programming frameworks where callbacks for a given object/event fire synchronously and will not step over existing code flow.&lt;/p&gt;
&lt;h2&gt;Reentrancy vs thread-safety&lt;/h2&gt;
&lt;p&gt;While reentrancy and thread-safety are related concepts, it is absolutely critical to understand is they are &lt;span class="caps"&gt;NOT&lt;/span&gt; the same, and one does not imply the other.&lt;/p&gt;
&lt;p&gt;(There are existing articles on this, so I won&amp;#8217;t dive into this more.)&lt;/p&gt;
&lt;h2&gt;Signal handlers must be reentrant&lt;/h2&gt;
&lt;p&gt;When writing a signal handler, you must ask yourself:&lt;/p&gt;
What happens when another signal arrives while this handler is still running?
&lt;p&gt;Since signal handlers are invoked as soon as possible, they can even run while another (or the same) signal handler is running.  Thus signal handlers must be able to tolerate reentrancy.&lt;/p&gt;
&lt;p&gt;Back to thread-safety: some constructs required for thread-safety fail horribly when used in situations that require reentrancy.  Most mutex implementations (including the Ruby Mutex class) deadlock when used inside a signal handler.&lt;/p&gt;
&lt;p&gt;Consider the following snippet:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
       lock = Mutex.new

       # XXX this is an example of what NOT to do inside a signal handler:
       trap(:USR1) do
         lock.synchronize do
           # if a second SIGUSR1 arrives here, this block of code
           # will fire again.   Attempting Mutex#synchronize twice
           # the same thread leads to a deadlock error
         end
       end
&lt;/pre&gt;
&lt;p&gt;Thus, you must ensure any code you use inside a signal handler is reentrant-safe.  Even using the Logger class in the Ruby standard library (which can call Mutex#synchronize) can deadlock inside a signal handler.&lt;/p&gt;
&lt;h2&gt;Signal reliability&lt;/h2&gt;
&lt;p&gt;Signals are not completely reliable in Ruby (nor many applications, for that matter).  If multiple, identical signals are received in a short time frame, you&amp;#8217;re guaranteed to fire a handler for /at least/ one of the signals, but not all of the signals received.&lt;/p&gt;
&lt;p&gt;This is because Ruby implementations must&lt;sup class="footnote" id="fnr1"&gt;&lt;a href="#fn1"&gt;1&lt;/a&gt;&lt;/sup&gt; block signals from firing while manipulating internal data structures.  When normal signals get blocked, they do not queue up in the OS kernel and instead only get a boolean bit set.&lt;/p&gt;
&lt;p&gt;&lt;sup class="footnote" id="fnr1"&gt;&lt;a href="#fn1"&gt;1&lt;/a&gt;&lt;/sup&gt; &amp;#8211; back to reentrancy, temporarily blocking signals to ensure reentrant-safe data manipulation is analogous to using a mutex lock to accomplish thread-safe data manipulation.&lt;/p&gt;
&lt;h2&gt;Untrappable, unblockable signals&lt;/h2&gt;
&lt;p&gt;Regardless of the Ruby runtime state, &lt;span class="caps"&gt;SIGSTOP&lt;/span&gt; still suspend a process immediately (until &lt;span class="caps"&gt;SIGCONT&lt;/span&gt; is received), and cannot be trapped by the Ruby runtime (or any userspace process).&lt;/p&gt;
&lt;p&gt;Similarly, &lt;span class="caps"&gt;SIGKILL&lt;/span&gt; terminates a process immediately.  Processes are are given no chance to stop or react to them.  Thus, no blocks registered via Kernel#at_exit, &lt;span class="caps"&gt;END&lt;/span&gt;, nor object finalizers can run upon &lt;span class="caps"&gt;SIGKILL&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;Sending &amp;#8220;Ctrl-Z&amp;#8221; from a terminal generates &lt;span class="caps"&gt;SIGTSTP&lt;/span&gt;, not &lt;span class="caps"&gt;SIGSTOP&lt;/span&gt;, and &lt;span class="caps"&gt;SIGTSTP&lt;/span&gt; is trappable.&lt;/p&gt;
&lt;h2&gt;Deferred signal handling&lt;/h2&gt;
&lt;p&gt;&lt;span class="caps"&gt;POSIX&lt;/span&gt; defines a very small number of C functions that are safe to use inside a signal handler&lt;sup class="footnote" id="fnr2"&gt;&lt;a href="#fn2"&gt;2&lt;/a&gt;&lt;/sup&gt;.  As Ruby programmers have little direct control over which C functions they end up calling, Ruby implementations (at least modern ones) implement deferred signal handling.&lt;/p&gt;
&lt;p&gt;Thus Ruby implementations register trap signals using C functions (via sigaction(2)) and dispatch Ruby signal handlers out when the VM/interpreter is in a safe state.&lt;/p&gt;
&lt;p&gt;Modern versions of Perl (and presumably other high-level languages) also use deferred signal handling.&lt;/p&gt;
&lt;p&gt;Even with deferred signal handling implemented by the language runtime, it is still a good idea to &lt;em&gt;also&lt;/em&gt; implement deferred signal handling in your Ruby applications to avoid the same reentrancy pitfalls.&lt;/p&gt;
&lt;p&gt;&lt;sup class="footnote" id="fnr2"&gt;&lt;a href="#fn2"&gt;2&lt;/a&gt;&lt;/sup&gt; &amp;#8211; Linux signal(7) manpage is one place that lists these functions&lt;/p&gt;
&lt;p&gt;License: GPLv3 or later, http://www.gnu.org/licenses/gpl-3.0.txt&lt;/p&gt;</description><author>normalperson@yhbt.net (Eric Wong)</author><pubDate>Tue, 27 Mar 2012 00:25:00 -0400</pubDate><link>http://blog.rubybestpractices.com/posts/ewong/016-Implementing-Signal-Handlers.html</link><guid>http://blog.rubybestpractices.com/posts/ewong/016-Implementing-Signal-Handlers.html</guid></item><item><title>USP: Unix signals - primitive interprocess communication</title><description>&lt;p&gt;Signals are the most basic way for processes to communicate with each other on a Unix system.  Each process has signal handlers configured by default, so some actions (e.g. killing a process) are always available.&lt;/p&gt;
&lt;p&gt;There are two distinct classes of signals defined by &lt;span class="caps"&gt;POSIX&lt;/span&gt;:&lt;/p&gt;
standard and real-time
&lt;p&gt;Currently, Ruby implementations (that I&amp;#8217;m aware of) only deal with standard signals.  Ruby implementations also control the signal mask and will temporarily block/unblock signals to perform critical operations in the interest of (portable) thread/async-safety.&lt;/p&gt;
&lt;p&gt;Operating systems have a pre-defined list of signals.  This list of signals is available for all processes to send and receive.  Each signal has a human-readable name (e.g.  &amp;#8220;&lt;span class="caps"&gt;KILL&lt;/span&gt;&amp;#8221; or &amp;#8220;&lt;span class="caps"&gt;SIGKILL&lt;/span&gt;&amp;#8221;) and non-negative number (e.g. 9) associated with it.  To see which ones are supported by both Ruby and your OS, the &amp;#8220;Signal.list&amp;#8221; method returns a Hash mapping their names to respective signal numbers.&lt;/p&gt;
&lt;p&gt;Some signals (e.g. &lt;span class="caps"&gt;SEGV&lt;/span&gt;, &lt;span class="caps"&gt;VTALRM&lt;/span&gt;) may be reserved by the Ruby implementation for internal use.  Other signals (&lt;span class="caps"&gt;STOP&lt;/span&gt;, &lt;span class="caps"&gt;KILL&lt;/span&gt;) may not be blocked, ignored, or handled at all by any userspace process.&lt;/p&gt;
&lt;p&gt;Signals may be assigned (and reassigned) handler functions (aka &amp;#8220;callbacks&amp;#8221;) which execute upon delivery of a signal.  Those of you familiar with event-driven programming models will realize signals are another type of event (not much unlike I/O) which you may define callbacks for.&lt;/p&gt;
&lt;p&gt;However, writing signal handlers requires more care and attention than &amp;#8220;normal&amp;#8221; code in your application.  The universal wisdom is to keep signal handlers simple and short, regardless of the programming language you&amp;#8217;re writing in.&lt;/p&gt;
&lt;p&gt;While Ruby helps users avoid many of the low-level details and caveats of implementing signal handling, there are still pitfalls to be aware of and avoid.&lt;/p&gt;
&lt;h2&gt;Methods for working with signals in Ruby&lt;/h2&gt;
&lt;p&gt;&amp;#8220;Process.kill&amp;#8221; maps to the kill(2) / killpg(2) system calls for sending signals to processes or process groups.  &amp;#8220;Signal.trap&amp;#8221; (Kernel#trap) is analogous (but not directly mapped to sigaction(2) (or signal(2)).&lt;/p&gt;
&lt;p&gt;Read more about them via ri or rdoc.&lt;/p&gt;
&lt;p&gt;&lt;cite&gt;License: &lt;a href="http://www.gnu.org/licenses/gpl-3.0.txt"&gt;GPLv3&lt;/a&gt; (or later, at the discretion of Eric Wong)&lt;/cite&gt;&lt;/p&gt;</description><author>normalperson@yhbt.net (Eric Wong)</author><pubDate>Tue, 20 Mar 2012 21:56:00 -0400</pubDate><link>http://blog.rubybestpractices.com/posts/ewong/015-Signals.html</link><guid>http://blog.rubybestpractices.com/posts/ewong/015-Signals.html</guid></item><item><title>USP: Unix processes and their attributes</title><description>&lt;p&gt;Processes are kernel objects that run user space code.  As we&amp;#8217;ve established before, each Unix process is identified by an integer process identifer (&lt;span class="caps"&gt;PID&lt;/span&gt;) and has a file descriptor table.&lt;/p&gt;
&lt;h2&gt;PIDs&lt;/h2&gt;
&lt;p&gt;Each process knows two PIDs: its own and its parent&amp;#8217;s (&lt;span class="caps"&gt;PPID&lt;/span&gt;).&lt;/p&gt;
&lt;p&gt;Process.pid and $$ are wrappers for the getpid(2) syscall and Process.ppid is a wrapper for getppid(2).  While the &lt;span class="caps"&gt;PID&lt;/span&gt; of a process never changes, its parent &lt;span class="caps"&gt;PID&lt;/span&gt; (&lt;span class="caps"&gt;PPID&lt;/span&gt;) may change.&lt;/p&gt;
&lt;h2&gt;$0 / $PROGRAM_NAME&lt;/h2&gt;
&lt;p&gt;Each process has a name, this variable may be reassigned to change the name of this process in the output in tools like ps(1).&lt;/p&gt;
&lt;p&gt;Ruby does not expose $EXECUTABLE_NAME ($^X) like Perl does, however $PROGRAM_NAME is set to the executable name for Ruby programs at startup.&lt;/p&gt;
&lt;h2&gt;&lt;span class="caps"&gt;ARGV&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;This is an Array of command-line arguments given to a process.  ARGV[0] in Ruby is the first argument given to the executable, not the executable name.  Thus "ARGV[0]" in Ruby is "argv[1]" to C programmers.&lt;/p&gt;
&lt;p&gt;Modifying this array will not affect the name of the process in tools like ps(1).  Command-line option parsing libraries like &amp;#8216;optparse&amp;#8217; and &amp;#8216;getoptlong&amp;#8217; in the Ruby standard library may modify &lt;span class="caps"&gt;ARGV&lt;/span&gt;.&lt;/p&gt;
&lt;h2&gt;Signal mask / handlers&lt;/h2&gt;
&lt;p&gt;Ruby implementations have internal system-level signal handlers that may later dispatch Ruby code (registered via Signal.trap).  Signal handlers written in Ruby are not subject to the limitations of system-level signal handlers.&lt;/p&gt;
&lt;h2&gt;&lt;span class="caps"&gt;ENV&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;This Hash-like object holds process environment variables.  Environment variables are global to the process and are used to share information with system libraries and child processes in a language-independent manner.&lt;/p&gt;
&lt;p&gt;Null-terminated C strings are mapped to Ruby Strings in both the keys and values of this Hash-like object.&lt;/p&gt;
&lt;p&gt;While the system environment appears Hash-like, but it is not exposed as a hash to user space, so it does not have the same performance / algorithmic complexity as a Ruby Hash.&lt;/p&gt;
&lt;h2&gt;Working directory (Dir.pwd, Dir.chdir)&lt;/h2&gt;
&lt;p&gt;All processes have a working directory it runs in.&lt;/p&gt;
&lt;h2&gt;Process.times&lt;/h2&gt;
&lt;p&gt;Each process keeps track of &lt;span class="caps"&gt;CPU&lt;/span&gt; time spent in user space and the system (kernel) as well as the accumulated times of its children.  Process.times is used to implement the Benchmark module in the Ruby standard library.&lt;/p&gt;
&lt;h2&gt;Usage counters (getrusage(2))&lt;/h2&gt;
&lt;p&gt;There is no Ruby &lt;span class="caps"&gt;API&lt;/span&gt; for getrusage(2), unfortunately, however some GC implementations may use it to provide profiling statistics.&lt;/p&gt;
&lt;h2&gt;Process.getrlimit / Process.setrlimit&lt;/h2&gt;
&lt;p&gt;These get and set process resource limits such as the maximum number of open file descriptors, resident set size, niceness, &lt;span class="caps"&gt;CPU&lt;/span&gt; time, etc.  They are wrappers for the respective getrlimit(2) and setrlimit(2) syscalls.&lt;/p&gt;
&lt;h2&gt;User IDs / Group IDs&lt;/h2&gt;
&lt;p&gt;Each process has a real, effective and saved &lt;span class="caps"&gt;UID&lt;/span&gt; and GIDs.&lt;/p&gt;
&lt;p&gt;Process::&lt;span class="caps"&gt;UID&lt;/span&gt;.change_privilege and Process::&lt;span class="caps"&gt;GID&lt;/span&gt;.change_privilege are the most portable and easiest ways to change the &lt;acronym title="s"&gt;&lt;span class="caps"&gt;UID&lt;/span&gt;&lt;/acronym&gt; and &lt;acronym title="s"&gt;&lt;span class="caps"&gt;GID&lt;/span&gt;&lt;/acronym&gt; of a process.&lt;/p&gt;
&lt;h2&gt;umask (File.umask)&lt;/h2&gt;
&lt;p&gt;The umask is the file mode creation mask of the process.  This governs the filesystem permissions of newly-created files (File.open) and directories (Dir.mkdir).&lt;/p&gt;
&lt;p&gt;(I don&amp;#8217;t plan to write much about Unix credentials / permissions, if anybody else wants to contribute an article it would be greatly appreciated.  It&amp;#8217;s not a subject that&amp;#8217;s ever interested me.&lt;/p&gt;
&lt;p&gt;On the other hand, part of me dies whenever I see a directory tree where somebody ran &amp;#8220;chmod -R 777 .&amp;#8221; on because they didn&amp;#8217;t understand Unix permissions&amp;#8230;)&lt;/p&gt;
&lt;p&gt;&lt;cite&gt;License: &lt;a href="http://www.gnu.org/licenses/gpl-3.0.txt"&gt;GPLv3&lt;/a&gt; (or later, at the discretion of Eric Wong)&lt;/cite&gt;&lt;/p&gt;</description><author>normalperson@yhbt.net (Eric Wong)</author><pubDate>Fri, 11 Nov 2011 22:37:00 -0500</pubDate><link>http://blog.rubybestpractices.com/posts/ewong/014-Unix-processes-and-their-attributes.html</link><guid>http://blog.rubybestpractices.com/posts/ewong/014-Unix-processes-and-their-attributes.html</guid></item><item><title>USP: IO#dup and the dup(2) system call</title><description>&lt;h2&gt;IO#dup vs. Object#dup&lt;/h2&gt;
&lt;p&gt;IO#dup is Object#dup in Ruby: it creates a shallow copy of an existing object.  To create a shallow copy, the IO#initialize_copy callback method performs the dup(2) syscall on the underlying file descriptor the IO object wraps.&lt;/p&gt;
&lt;p&gt;Like Object#dup in Ruby, dup(2) is a shallow clone that does not copy the underlying open file object in the kernel, but creates a new reference to an existing kernel object.&lt;/p&gt;
&lt;p&gt;Thus, two (or more) file descriptors in the same process can refer to the same open file in the kernel.&lt;/p&gt;
&lt;p&gt;Before calling IO#dup, we have a 1:1:1 relationship:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;one Ruby IO object&lt;/li&gt;
	&lt;li&gt;one file descriptor&lt;/li&gt;
	&lt;li&gt;one open file object in the kernel&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;
    [Ruby]    user space   |  kernel space
    ------------------------------------------------
                           |
    io_orig ----------- fd[orig] ----&amp;gt; file object
                           |
    ------------------------------------------------
    (file descriptors (fd) are the bridge here kernel and user space)
&lt;/pre&gt;
&lt;p&gt;After we call IO#dup, we have two 2:2:1 relationship:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;two Ruby IO objects&lt;/li&gt;
	&lt;li&gt;two file descriptors&lt;/li&gt;
	&lt;li&gt;one file object in the kernel&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;
    [Ruby]    user space   |  kernel space
    ------------------------------------------------
                           |
    io_orig ----------- fd[orig] -\
                           |       &amp;gt;---&amp;gt; file object
    io_copy ----------- fd[copy] -/
                           |
    ------------------------------------------------
&lt;/pre&gt;
&lt;p&gt;IO#dup can be called on the same IO object any number times, so there may be an N:N:1 relationship as long as the process (and system) resource limits are not exceeded.&lt;/p&gt;
&lt;p&gt;Most kernel-level (but not user space) changes to one IO object are immediately visible in the IO object(s) it was copied from (or copied to).&lt;/p&gt;
&lt;h2&gt;Effect on &lt;span class="caps"&gt;IPC&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;IO#dup means IO#close / close(2) will only remove a &lt;em&gt;reference&lt;/em&gt; to the file object in the kernel.  Only when the last file descriptor for a given file object is closed is the actual file object closed and released in the kernel.&lt;/p&gt;
&lt;p&gt;For applications relying on receiving an end-of-file condition (from a socket or pipe), IO#dup&lt;sup class="footnote" id="fnr1"&gt;&lt;a href="#fn1"&gt;1&lt;/a&gt;&lt;/sup&gt; can (sometimes inadverdantly) prevent the end-of-file condition from being reached in the reader.&lt;/p&gt;
&lt;p&gt;&lt;sup class="footnote" id="fnr1"&gt;&lt;a href="#fn1"&gt;1&lt;/a&gt;&lt;/sup&gt; &amp;#8211; and similar functions, like fork()&lt;/p&gt;
&lt;p&gt;&lt;cite&gt;License: &lt;a href="http://www.gnu.org/licenses/gpl-3.0.txt"&gt;GPLv3&lt;/a&gt; (or later, at the discretion of Eric Wong)&lt;/cite&gt;&lt;/p&gt;</description><author>normalperson@yhbt.net (Eric Wong)</author><pubDate>Wed, 19 Oct 2011 04:59:00 -0400</pubDate><link>http://blog.rubybestpractices.com/posts/ewong/013-IO-dup-and-dup-system-call.html</link><guid>http://blog.rubybestpractices.com/posts/ewong/013-IO-dup-and-dup-system-call.html</guid></item><item><title>USP: Unix time and the Ruby Time class</title><description>&lt;p&gt;The Unix epoch is defined as January 1, 1970, 00:00:00 &lt;span class="caps"&gt;UTC&lt;/span&gt; (Coordinated Universal Time&lt;sup class="footnote" id="fnr1"&gt;&lt;a href="#fn1"&gt;1&lt;/a&gt;&lt;/sup&gt;).  Unix systems return the time in seconds as a signed integer relative to the Unix epoch.  Negative numbers are interpreted as dates before the Unix epoch.&lt;/p&gt;
&lt;p&gt;Using seconds (and fractions of a second) to represent time allows application authors to rely on arithmetic rather than specialized functions for calculating time intervals.&lt;/p&gt;
&lt;p&gt;File systems expose timestamps for all files in Unix time with varying degrees of accuracy and granularity.  The Ruby File and File::Stat classes can support timestamps with sub-second granularity on some systems.&lt;/p&gt;
&lt;p&gt;Modern kernels do not know nor care about timezones.  Conversions from &lt;span class="caps"&gt;UTC&lt;/span&gt; to the local timezone (and vice versa) are done in user space&lt;sup class="footnote" id="fnr2"&gt;&lt;a href="#fn2"&gt;2&lt;/a&gt;&lt;/sup&gt;. Different processes running concurrently on the same machine do not necessarily share the same local timezone.&lt;/p&gt;
&lt;h3&gt;Ruby Time class&lt;/h3&gt;
&lt;p&gt;The Ruby Time class includes methods for reading the system time and allows converting from an Integer (seconds since the epoch) to a Ruby Time object.&lt;/p&gt;
&lt;p&gt;Ruby Time objects have a timezone attached to them, but remember this is a user space construct.&lt;/p&gt;
&lt;h3&gt;Time.now / gettimeofday(2) / clock_gettime(2)&lt;/h3&gt;
&lt;p&gt;gettimeofday(2) is the commonly available system call for reading the Unix time with (up to) microsecond resolution.  On some systems, clock_gettime(2) may be used for nanosecond resolution&lt;sup class="footnote" id="fnr3"&gt;&lt;a href="#fn3"&gt;3&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;Time.now will return the current time as a Time object taking into account the timezone of the current process (in user space).  Ruby 1.9 may use clock_gettime(2) internally if available, but fall back to&lt;br /&gt;
gettimeofday(2) to retrieve the system time.&lt;/p&gt;
&lt;h3&gt;Time#tv_sec / Time#tv_usec / Time#tv_nsec&lt;/h3&gt;
&lt;p&gt;These accessors allow access to the underlying values returned by gettimeofday(2) or clock_gettime(2) as Integers.  For systems without nanosecond resolution, Time#tv_nsec may just be the value of Time#tv_usec multiplied by 1000.&lt;/p&gt;
&lt;h3&gt;Time.at &amp;#8211; converts from Unix time to a Time object&lt;/h3&gt;
&lt;p&gt;If you have the number of seconds (and maybe microseconds) as integer seconds since the Unix epoch, you can convert that into a Ruby Time object using the Time.at class method:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
       Time.at(seconds[, microseconds ])
&lt;/pre&gt;
&lt;p&gt;This is is useful if you encounter a Unix timestamp anywhere but want to have a Ruby Time object.  The local timezone is attached to the created object.&lt;/p&gt;
&lt;p&gt;There is no underlying syscall needed for this, this conversion can be performed entirely in user space (although it may require memory allocation).&lt;/p&gt;
&lt;h3&gt;Process timezone&lt;/h3&gt;
&lt;p&gt;The &amp;#8220;TZ&amp;#8221; environment variable controls the timezone for a given process, and thus the timezone attached to a Ruby Time object.  If &amp;#8220;TZ&amp;#8221; is unset, the timezone of the process is implementation-defined.&lt;/p&gt;
&lt;h3&gt;Time#utc&lt;/h3&gt;
&lt;p&gt;If your process is not running under &lt;span class="caps"&gt;UTC&lt;/span&gt;, you may wish to convert Time objects to &lt;span class="caps"&gt;UTC&lt;/span&gt; with this method.&lt;/p&gt;
&lt;h3&gt;Setting system time&lt;/h3&gt;
&lt;p&gt;Ruby does not provide methods to change the system time.  Changing system time typically requires administrator (root) privileges and few applications (especially high-level ones) need to change the system time.  For machines with network access, system time is commonly synchronized via &lt;span class="caps"&gt;NTP&lt;/span&gt; and gradually adjusted via adjtime(3) and/or non-portable syscalls.&lt;/p&gt;
&lt;h3&gt;Monotonic clocks&lt;/h3&gt;
&lt;p&gt;Some systems support a monotonic clock which is not adjustable (even by the administrator).  A monotonic clock is useful for maintaining consistent timing and scheduling across system time changes.&lt;/p&gt;
&lt;p&gt;Ruby currently (as of 1.9.3) does not provide access to the monotonic clock.  However, Ruby implementations may use the monotonic clock internally for timing (via clock_gettime(2)) and recording time differences.&lt;/p&gt;
&lt;h3&gt;Avoiding system calls&lt;/h3&gt;
&lt;p&gt;You may notice the lack of gettimeofday(2) or clock_gettime(2) syscalls if you&amp;#8217;re tracing syscalls.  This is because C libraries can work with the kernel to optimize away the syscalls for gettimeofday(2) and clock_gettime(2).  These implementations may trade accuracy for speed, but may be disabled (by the administrator) if accuracy is more important (than speed).&lt;/p&gt;
&lt;p class="footnote" id="fn1"&gt;&lt;a href="#fnr1"&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt; One should know &lt;span class="caps"&gt;UTC&lt;/span&gt; is not exactly the same as Greenwich Mean Time (&lt;span class="caps"&gt;GMT&lt;/span&gt;)&lt;/p&gt;
&lt;p class="footnote" id="fn2"&gt;&lt;a href="#fnr2"&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt; Timezone information is usually on (regular) files, so it may require syscalls to read those files.&lt;/p&gt;
&lt;p class="footnote" id="fn3"&gt;&lt;a href="#fnr3"&gt;&lt;sup&gt;3&lt;/sup&gt;&lt;/a&gt; You&amp;#8217;re not guaranteed this level of accuracy is supported by your kernel nor your hardware.  Consult your operating system and hardware documentation for more information.&lt;/p&gt;
&lt;p&gt;&lt;cite&gt;License: &lt;a href="http://www.gnu.org/licenses/gpl-3.0.txt"&gt;GPLv3&lt;/a&gt; (or later, at the discretion of Eric Wong)&lt;/cite&gt;&lt;/p&gt;</description><author>normalperson@yhbt.net (Eric Wong)</author><pubDate>Sat, 24 Sep 2011 02:28:00 -0400</pubDate><link>http://blog.rubybestpractices.com/posts/ewong/012-Unix-time-and-the-Time-class.html</link><guid>http://blog.rubybestpractices.com/posts/ewong/012-Unix-time-and-the-Time-class.html</guid></item><item><title>USP: An introduction to the Unix pipe</title><description>&lt;p&gt;The Unix pipe is the first example of an anonymous file we will cover.&lt;/p&gt;
&lt;p&gt;Unlike regular files and directories, anonymous files do not exist on the filesystem and do not persist across reboots.  Only the process that creates the anonymous file (and its descendants) can access anonymous files.  Anonymous files only persist until the last process using it closes it.&lt;/p&gt;
&lt;p&gt;At its heart, the Unix pipe is just like a pipe in plumbing, a one-way buffer for transporting payload from one end to another.&lt;/p&gt;
&lt;p&gt;It is implemented as a circular ring buffer in the kernel:&lt;/p&gt;
&lt;pre&gt;
                     user space  | kernel space
       -----------------------------------------------
                                 |
         data in --&amp;gt; fd[writer] -&amp;gt;- file[writer] --&amp;gt;\
                                 |                   \
                                 |                [buffer]
                                 |                   /
        data out &amp;lt;-- fd[reader] -&amp;lt;- file[reader] &amp;lt;--/
                                 |
&lt;/pre&gt;
&lt;p&gt;The buffer is created by the pipe(2) system call and persists until both files are closed.  In Ruby, the IO.pipe method calls pipe(2) and returns an array of two Ruby IO objects, a reader and writer:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
       reader, writer = IO.pipe # kernel creates internal buffer
&lt;/pre&gt;
&lt;p&gt;Writing can be accomplished by making the write(2) syscall, the writer IO object should default to IO#sync=true at creation.&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
       writer.write("HELLO")
&lt;/pre&gt;
&lt;p&gt;Reading can be accomplished by making the read(2) syscall.&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
       reader.read(5)  # =&amp;gt; "HELLO"
&lt;/pre&gt;
&lt;p&gt;Finally, the kernel memory for the buffer is released after both file objects (through file descriptors and IO) are closed:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
       writer.close
       reader.close
       # Kernel frees the buffer
&lt;/pre&gt;
&lt;p&gt;As with regular files, pipes operate on byte streams and leaves higher-level functionality (like encoding) to user space.&lt;/p&gt;
&lt;p&gt;Pipes also have important atomicity requirements standardized by &lt;a href="http://pubs.opengroup.org/onlinepubs/9699919799/"&gt;&lt;span class="caps"&gt;POSIX&lt;/span&gt;&lt;/a&gt;. Given the importance of pipes in Unix programming, we will revisit and give pipes much more coverage in the future.&lt;/p&gt;
&lt;p&gt;&lt;cite&gt;License: &lt;a href="http://www.gnu.org/licenses/gpl-3.0.txt"&gt;GPLv3&lt;/a&gt; (or later, at the discretion of Eric Wong)&lt;/cite&gt;&lt;/p&gt;</description><author>normalperson@yhbt.net (Eric Wong)</author><pubDate>Fri, 23 Sep 2011 00:35:00 -0400</pubDate><link>http://blog.rubybestpractices.com/posts/ewong/010-An-introduction-to-the-Unix-pipe.html</link><guid>http://blog.rubybestpractices.com/posts/ewong/010-An-introduction-to-the-Unix-pipe.html</guid></item><item><title>USP: Directories on the filesystem</title><description>&lt;p&gt;Directories are containers for files, and directories are also files. Similarly, Ruby Hashes are containers for Objects, and Hashes are also Objects.&lt;/p&gt;
&lt;p&gt;The contents of the &amp;#8220;/home/johndoe/&amp;#8221; directory could be expressed as the following Ruby pseudocode:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
       root = {
         "home" =&amp;gt; {
           "johndoe" =&amp;gt; {
             ".bashrc" =&amp;gt; Inode[123],
             ".vimrc" =&amp;gt; Inode[456],
             ".mutt" =&amp;gt; {
               ".muttrc" =&amp;gt; Inode[789]
             }
           }
         }
       }
&lt;/pre&gt;
&lt;p&gt;As one may guess, it&amp;#8217;s impossible for two identical file names to appear in the same directory at the same time.&lt;/p&gt;
&lt;h3&gt;Directory Entries&lt;/h3&gt;
&lt;p&gt;As hashes are composed of key-value pairs, directories are composed of directory entries, or &amp;#8220;dirent&amp;#8221; structures which store file names and inode numbers.  Like &amp;#8220;struct stat&amp;#8221; information, the &amp;#8220;struct dirent&amp;#8221; exposed to user space contains only the standardized, common information for user space, not the actual, private information in the kernel or file system.&lt;/p&gt;
&lt;p&gt;Ruby does not expose the dirent structure in any way (the standard C library does), but one could express the dirent structure with the following Ruby Struct:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
       Dirent = Struct.new(:d_name, :d_ino)
       Dirent.new(".bashrc", 123)
&lt;/pre&gt;
&lt;h3&gt;Reading Dirents&lt;/h3&gt;
&lt;p&gt;The Ruby Dir class handles reading directories, but only exposes names to the user (not inode numbers).&lt;/p&gt;
&lt;p&gt;There are no portable syscalls for reading dirents from a directory, only standardized &lt;em&gt;library&lt;/em&gt; functions such as readdir(3) and readdir_r(3).  These library functions are wrappers for non-portable system calls.&lt;/p&gt;
&lt;p&gt;Furthermore, common functionality like partial name matching (globbing) is handled by user space.  As we learned before, proper Unix file systems have no notion of encodings/case-sensitivity in kernel space, thus inexact name matching rules need to be applied in user space.&lt;/p&gt;
&lt;p&gt;Sorting is also done in user space.  The standard C library functions never guarantee entries are returned in any particular order.  This behavior matches the behavior of Hashes in Ruby 1.8 and earlier. In fact, some file systems store or index name-to-inode mappings in a hash structure on disk.&lt;/p&gt;
&lt;p&gt;All dentries (except &amp;#8220;..&amp;#8221;) within one directory belong to the same device (and often the same physical device&lt;sup class="footnote" id="fnr1"&gt;&lt;a href="#fn1"&gt;1&lt;/a&gt;&lt;/sup&gt;), so only the inode number is stored in the dirent.&lt;/p&gt;
&lt;h3&gt;Creating and Removing Directories&lt;/h3&gt;
&lt;p&gt;For regular files, we&amp;#8217;ve covered the File.open, File.link, and File.unlink methods.  Creating directories requires the mkdir(2) syscall provided by the Ruby Dir.mkdir method, not the open(2) syscall.&lt;/p&gt;
&lt;p&gt;Once created, it /is/ possible to use open(2) (and thus File.open) to &amp;#8220;open&amp;#8221; a directory like a regular file and IO#stat it.&lt;/p&gt;
&lt;p&gt;The rmdir(2) (not unlink(2)) syscall is used to remove directories and that is provided to Ruby by Dir.rmdir.&lt;/p&gt;
&lt;p&gt;High-level wrappers like FileUtils.mkpath (or &amp;#8220;mkdir(1) -p&amp;#8221;) and FileUtils.rmtree (or &amp;#8220;rm(1) -r&amp;#8221;) need to invoke the appropriate syscall for every entry they wish to create or remove.&lt;/p&gt;
&lt;p&gt;On modern Unicies, it is not possible to create hard links for directories.  Allowing directory hard links would lead to infinite recursion loops when traversing directories.&lt;/p&gt;
&lt;p&gt;Thus the File::Stat#nlink field for directories shows the number of entries the directory contains.&lt;/p&gt;
&lt;h3&gt;&amp;#8220;.&amp;#8221; and &amp;#8220;..&amp;#8221; entries&lt;/h3&gt;
&lt;p&gt;Every directory contains a entry for itself &amp;#8220;.&amp;#8221; and to its parent &amp;#8220;..&amp;#8221;. The root &amp;#8220;/&amp;#8221; directory is special and is its own parent, so &amp;#8220;..&amp;#8221; points to itself.&lt;/p&gt;
&lt;h3&gt;rename(2)&lt;/h3&gt;
&lt;p&gt;The File.rename method wraps the rename(2) syscall to change the name of a file (of any type) within the same device.  rename(2) can occur within the same or different directories as long as the source and destination exist on the same device.&lt;/p&gt;
&lt;p&gt;For regular files:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
       File.rename("foo", "bar")
&lt;/pre&gt;
&lt;p&gt;is roughly equivalent to:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
       File.link("foo", "bar")
       File.unlink("foo")
&lt;/pre&gt;
&lt;p&gt;However, it is impossible (on a &lt;span class="caps"&gt;POSIX&lt;/span&gt;-compliant filesystem) for userspace to access both &amp;#8220;foo&amp;#8221; and &amp;#8220;bar&amp;#8221; at the same time when using File.rename.  Additionally, File.rename will work on directories whereas File.link and File.unlink do not work on directories.&lt;/p&gt;
&lt;p&gt;Commands like mv(1) will use rename(2) if both the source and destination exist on the same device.  This makes mv(1) very fast in cases where it works on the same device, but slow (and non-atomic) if the source and destination need to cross devices.&lt;/p&gt;
&lt;p class="footnote" id="fn1"&gt;&lt;a href="#fnr1"&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt; There exist some union filesystems which break this assumption, however they are uncommon and often restricted to read-only access.&lt;/p&gt;
&lt;p&gt;&lt;cite&gt;License: &lt;a href="http://www.gnu.org/licenses/gpl-3.0.txt"&gt;GPLv3&lt;/a&gt; (or later, at the discretion of Eric Wong)&lt;/cite&gt;&lt;/p&gt;</description><author>normalperson@yhbt.net (Eric Wong)</author><pubDate>Fri, 23 Sep 2011 00:21:00 -0400</pubDate><link>http://blog.rubybestpractices.com/posts/ewong/011-Directories-on-the-filesystem.html</link><guid>http://blog.rubybestpractices.com/posts/ewong/011-Directories-on-the-filesystem.html</guid></item><item><title>USP: Regular files and metadata</title><description>&lt;p&gt;Regular files on a persistent filesystem are pointers / links to internal metadata known as inodes.  The implementation details of inodes vary between various filesystems and is usually not the concern of user space.  User space developers should only need to know a few common traits about inodes&lt;/p&gt;
&lt;h3&gt;device number (File::Stat#dev)&lt;/h3&gt;
&lt;p&gt;The device number is a unique integer identifier for the device an inode belongs to.  Each file system partition is considered its own &amp;#8220;device&amp;#8221;, so a device number does not necessarily correspond to a physical device (e.g. hard disk drive)&lt;/p&gt;
&lt;p&gt;This device number is unique within a running Unix system, no two &amp;#8220;devices&amp;#8221; may have the same device number at the same point in time.&lt;/p&gt;
&lt;h3&gt;inode number (File::Stat#ino)&lt;/h3&gt;
&lt;p&gt;The inode number is unique integer identifier for an inode within a particular device.  Like PIDs, FDs, and device numbers, they are opaque pointers to complex objects in kernel space.&lt;/p&gt;
&lt;p&gt;The combination of device and inode number is required to uniquely identify any inode (and thus file) in the system.&lt;/p&gt;
&lt;h3&gt;File Names&lt;/h3&gt;
&lt;p&gt;In many cases, there is a 1:1 relationship between file names and inodes.  That is, each file name points to its own inode, much like how one variable points to one Ruby object:&lt;/p&gt;
&lt;p style="padding-left:1em;"&gt;&amp;#8220;.bashrc&amp;#8221; &amp;#8594; inode_number=123, device_number=456&lt;/p&gt;
&lt;p&gt;It is important to know the file name &amp;#8594; inode relationship is one way.  Inodes do not know which file name(s) it has pointing to it.  Similarly, Ruby objects do not know which variable name(s) are assigned to it.&lt;/p&gt;
&lt;p&gt;When working with File objects, one should know the File#path method return value in Ruby is determined in user space when File.open is called, &lt;em&gt;not&lt;/em&gt; when File#path is called:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
       file = File.open(".bashrc")
       file.path       # returns value of ".bashrc" determined above
&lt;/pre&gt;
&lt;h3&gt;Creating Inodes and Files&lt;/h3&gt;
&lt;p&gt;Making the open(2) system call with the O_CREAT flag will create a file.&lt;/p&gt;
&lt;p&gt;File.open can accept the equivalent IO::&lt;span class="caps"&gt;CREAT&lt;/span&gt; constant or with fopen(3)-style mode strings (&amp;#8220;w&amp;#8221;, &amp;#8220;a&amp;#8221;) to create an inode if the specified file name does not exist.&lt;/p&gt;
&lt;p&gt;The Unix touch(1) command and FileUtils.touch method both create files with open(2) in this way.  Historically there is also a creat(2) system call for creating and opening files, but open(2) is more flexible and preferred.  Ruby does not use nor expose creat(2) to the user.&lt;/p&gt;
&lt;h3&gt;Hard links&lt;/h3&gt;
&lt;p&gt;Since you should understand how two (or more) variables can point to the same object in Ruby, you should be able to understand how two (or more) file names can point to the same inode (and thus the same file) on one device.&lt;/p&gt;
&lt;p&gt;Like two variables pointing to the same Ruby object, two (or more) links pointing to the same inode are indistinguishable from each other:&lt;/p&gt;
&lt;pre&gt;
       "filename_1" ------+
                          |
       "filename_2" ------+----&amp;gt; inode_number=123, device_number=456
                          |
       "filename_3" ------+
                          |
                         ...
                          |
       "filename_X" ------+
&lt;/pre&gt;
&lt;p&gt;Hard links to existing files are created with the File.link method which makes the link(2) system call.  There is usually a system-dependent limit on the number of links to a particular inode, File.link will raise Errno::&lt;span class="caps"&gt;EMLINK&lt;/span&gt; if this limit is hit.&lt;/p&gt;
&lt;h3&gt;Number of Hard Links (File::Stat#nlink)&lt;/h3&gt;
&lt;p&gt;While inodes do not know which file name(s) point to it, inodes are aware of how many file names point to it.  Each time a hard link is created, the number of hard links to the referenced given inode is incremented.&lt;/p&gt;
&lt;p&gt;File names may be removed with the unlink(2) system call (via File.unlink in Ruby).  Unlinking a file will decrement the number of links an inode has.  It is possible for an inode to have zero links to it and remain valid (which we will surely discuss later).&lt;/p&gt;
&lt;h3&gt;File::Stat&lt;/h3&gt;
&lt;p&gt;File::Stat is the Ruby class to represent inode information to the user.  All of the fields mentioned above (dev, ino, nlink) are available from a File::Stat object.&lt;/p&gt;
&lt;p&gt;File.stat is a wrapper for the stat(2) system call and returns a File::Stat object for a given path.&lt;/p&gt;
&lt;p&gt;If you have a Ruby IO object (and thus file) open, you can use IO#stat to get the File::Stat object for the file descriptor belonging to the IO/File object.  IO#stat makes the fstat(2) system call instead of stat(2).&lt;/p&gt;
&lt;p&gt;File::Stat is the Ruby equivalent/wrapper of the &amp;#8220;struct stat&amp;#8221; structure seen by C programmers.&lt;/p&gt;
&lt;p&gt;We will discuss File.lstat when we discuss symbolic links.&lt;/p&gt;
&lt;p&gt;&lt;cite&gt;License: &lt;a href="http://www.gnu.org/licenses/gpl-3.0.txt"&gt;GPLv3&lt;/a&gt; (or later, at the discretion of Eric Wong)&lt;/cite&gt;&lt;/p&gt;</description><author>normalperson@yhbt.net (Eric Wong)</author><pubDate>Tue, 20 Sep 2011 04:13:00 -0400</pubDate><link>http://blog.rubybestpractices.com/posts/ewong/007-Regular-files-and-metadata.html</link><guid>http://blog.rubybestpractices.com/posts/ewong/007-Regular-files-and-metadata.html</guid></item><item><title>USP: basic IO methods</title><description>&lt;p&gt;(Consider C library functions (3) analogues while the system call (2)&lt;br /&gt;
 functions are inevitably called by Ruby)&lt;/p&gt;
&lt;h3&gt;Opening (and Closing) Files&lt;/h3&gt;
&lt;ul&gt;
	&lt;li&gt;File.open &amp;#8211; fopen(3) which wraps open(2) and provides a File object&lt;/li&gt;
	&lt;li&gt;IO#close &amp;#8211; fclose(3), close(2) Copies Ruby buffers to the kernel, invalidates the IO object and releases the file descriptor so it may be reused by the kernel.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These methods will be covered in more detail as we dig deeper.&lt;/p&gt;
&lt;h3&gt;Some File Operations for Reading and Writing&lt;/h3&gt;
&lt;ul&gt;
	&lt;li&gt;IO#read &amp;#8211; fread(3) &amp;#8211; read all specified bytes&lt;/li&gt;
	&lt;li&gt;IO#write &amp;#8211; fwrite(3) &amp;#8211; write all specified bytes&lt;/li&gt;
	&lt;li&gt;IO#sync, IO#sync= &amp;#8211; setvbuf(3) &amp;#8211; controls Ruby (write) buffering&lt;/li&gt;
	&lt;li&gt;IO#flush &amp;#8211; fflush(3) &amp;#8211; copies existing Ruby (write) buffers to kernel&lt;/li&gt;
	&lt;li&gt;IO#syswrite &amp;#8211; write(2) &amp;#8211; copies application buffers to kernel&lt;/li&gt;
	&lt;li&gt;IO#sysread &amp;#8211; read(2) &amp;#8211; copies kernel buffers to application&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;(there are more methods which we&amp;#8217;ll cover in time, of course)&lt;/p&gt;
&lt;p&gt;Setting IO#sync= to true will make IO#write copy application buffers directly into kernel buffers, bypassing Ruby buffers.  IO#sync does not influence read buffering.&lt;/p&gt;
&lt;p&gt;If IO#sync is false, IO#write may copy small application buffers into Ruby buffers to before internally doing IO#flush.&lt;/p&gt;
&lt;p&gt;The non-sys* methods will retry until the operation is complete (or raise on any errors).  The sys* variants do not retry if the kernel returns a partial read(2) or write(2) and will also raise on errors.&lt;/p&gt;
&lt;p&gt;Mixing sys* and non-sys* methods is not recommended and will result in errors or exceptions.&lt;/p&gt;
&lt;p&gt;If you need more detailed descriptions, check `ri&amp;#8217; or other Ruby doc for Ruby methods.  For C library functions and system calls, your Unix-like OS should provide manpages and you can search online, too. I have no intention of regurgitating &lt;span class="caps"&gt;API&lt;/span&gt; documentation.&lt;/p&gt;
&lt;p&gt;&lt;cite&gt;License: &lt;a href="http://www.gnu.org/licenses/gpl-3.0.txt"&gt;GPLv3&lt;/a&gt; (or later, at the discretion of Eric Wong)&lt;/cite&gt;&lt;/p&gt;</description><author>normalperson@yhbt.net (Eric Wong)</author><pubDate>Mon, 19 Sep 2011 21:28:00 -0400</pubDate><link>http://blog.rubybestpractices.com/posts/ewong/008-basic-IO-methods.html</link><guid>http://blog.rubybestpractices.com/posts/ewong/008-basic-IO-methods.html</guid></item><item><title>USP: The Ruby IO Class</title><description>&lt;p&gt;The IO class wraps file descriptors as Ruby objects and provides instance methods which wrap system calls.  Each IO object wraps one OS file descriptor&lt;sup class="footnote" id="fnr1"&gt;&lt;a href="#fn1"&gt;1&lt;/a&gt;&lt;/sup&gt;.  IO also provides userspace buffering to avoid system calls and utility methods to make a programmer&amp;#8217;s life easier.&lt;/p&gt;
&lt;p&gt;C programmers may find the Ruby IO class analogous to the (opaque) &amp;#8220;&lt;span class="caps"&gt;FILE&lt;/span&gt;&amp;#8221; struct in stdio.&lt;/p&gt;
&lt;p&gt;IO is often used via subclasses:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;File class is mostly intended for regular files&lt;/li&gt;
	&lt;li&gt;TCPSocket for &lt;span class="caps"&gt;TCP&lt;/span&gt; sockets&lt;/li&gt;
	&lt;li&gt;UNIXSocket for &lt;span class="caps"&gt;UNIX&lt;/span&gt; domain sockets&lt;/li&gt;
	&lt;li&gt;UDPSocket for &lt;span class="caps"&gt;UDP&lt;/span&gt; sockets&lt;/li&gt;
	&lt;li&gt;&amp;#8230;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of those classes are based on the IO class and wrap an integer file descriptor.&lt;/p&gt;
&lt;h3&gt;Layers of Buffering&lt;/h3&gt;
&lt;p&gt;There are at least four distinct layers of buffering within a machine.&lt;/p&gt;
&lt;pre&gt;
       Application buffers     - what your application sees
       Library buffers         - implemented by Ruby or libc
       ----------------- kernel-user space boundary -----------------
       Kernel software buffers
       Hardware buffers
&lt;/pre&gt;
&lt;p&gt;Buffers may be implemented for both reading and writing.&lt;/p&gt;
&lt;p&gt;The Ruby IO class can do the following:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;accept application buffers from the user (IO#write)&lt;/li&gt;
	&lt;li&gt;return application buffers to the user (IO#read)&lt;/li&gt;
	&lt;li&gt;manage library buffers internally&lt;/li&gt;
	&lt;li&gt;copy (and remove) library buffers to kernel buffers&lt;/li&gt;
	&lt;li&gt;(hopefully) force kernel and hardware buffers to storage/network&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We will cover how to use/influence/avoid them individually as we go further.  For now, just know they exist and what IO does.&lt;/p&gt;
&lt;h3&gt;Scope and Sharing of Buffers&lt;/h3&gt;
&lt;p&gt;A wider view of the above table would be:&lt;/p&gt;
&lt;pre&gt;
       process[0]  | process[1]  | process[2]  | ... process[N]
       ------------+-------------+-------------+---------------
       App buffers | App buffers | App buffers | ...
       Lib buffers | Lib buffers | Lib buffers | ...
       ------------- kernel-user space boundary ---------------
                       Kernel software buffers
                       Hardware buffers
&lt;/pre&gt;
&lt;p&gt;User space buffers are not shared between different processes in Ruby.&lt;/p&gt;
&lt;p&gt;Kernel buffers are shared, allowing read(2)-after-write(2) consistency between different processes.  This is one (of many) ways for cooperating processes to share data.&lt;/p&gt;
&lt;p&gt;A few applications&lt;sup class="footnote" id="fnr2"&gt;&lt;a href="#fn2"&gt;2&lt;/a&gt;&lt;/sup&gt; may manage process-shared buffers in user space, but (stock) Ruby does not have this.&lt;/p&gt;
&lt;p&gt;Library buffers (like most memory) in the Ruby IO class /are/ shared between different Threads and Fibers in Ruby.&lt;/p&gt;
&lt;p&gt;Sharing of application buffers between Threads/Fibers is possible but usually not a good idea.  It is of course, application-dependent.&lt;/p&gt;
&lt;p class="footnote" id="fn1"&gt;&lt;a href="#fnr1"&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt; Multiple IO objects may wrap a single file descriptor, but that is often a bad idea (to be explained later :)).&lt;/p&gt;
&lt;p class="footnote" id="fn2"&gt;&lt;a href="#fnr2"&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt; database servers like PostgreSQL come to mind&lt;/p&gt;
&lt;p&gt;&lt;cite&gt;License: &lt;a href="http://www.gnu.org/licenses/gpl-3.0.txt"&gt;GPLv3&lt;/a&gt; (or later, at the discretion of Eric Wong)&lt;/cite&gt;&lt;/p&gt;</description><author>normalperson@yhbt.net (Eric Wong)</author><pubDate>Sat, 17 Sep 2011 03:33:00 -0400</pubDate><link>http://blog.rubybestpractices.com/posts/ewong/009-The-Ruby-IO-Class.html</link><guid>http://blog.rubybestpractices.com/posts/ewong/009-The-Ruby-IO-Class.html</guid></item><item><title>USP: The Unix object model (as seen in procfs)</title><description>&lt;p&gt;Eric Wong wrote:&lt;/p&gt;
&lt;p&gt;&lt;cite&gt;If you&amp;#8217;re a Rubyist, you may already be familiar with object-oriented designs.  A running Unix/Unix-like kernel exposes two primary types of objects to userspace:&lt;/cite&gt;&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;&lt;cite&gt;Processes&lt;/cite&gt;&lt;/li&gt;
	&lt;li&gt;&lt;cite&gt;Open files&lt;/cite&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Now that we know what filesystems and virtual filesystems are, several systems have a procfs virtual filesystem mounted under /proc.  I don&amp;#8217;t believe it&amp;#8217;s standardized anywhere between different systems, but your system probably supports it.&lt;/p&gt;
&lt;p&gt;Among other things, procfs allows you to see the relationship between processes and their file descriptors on the filesystem.&lt;/p&gt;
&lt;p&gt;You can inspect which file descriptors a particular process is using by looking in the &amp;#8220;fd&amp;#8221; subdirectory belonging to the &lt;span class="caps"&gt;PID&lt;/span&gt; belonging to the process.  For example, my current mutt process has &lt;span class="caps"&gt;PID&lt;/span&gt;=19245 and file descriptors 0, 1, 2, and 4 open:&lt;/p&gt;
&lt;pre&gt;
       /proc/19245/fd
       /proc/19245/fd/0
       /proc/19245/fd/1
       /proc/19245/fd/2
       /proc/19245/fd/4
&lt;/pre&gt;
&lt;p&gt;Each &lt;span class="caps"&gt;PID&lt;/span&gt; has a directory in /proc/, and for each directory belonging to a particular &lt;span class="caps"&gt;PID&lt;/span&gt;, there is an &amp;#8220;fd&amp;#8221;&lt;/p&gt;
&lt;p&gt;Utilities like ps(1) (are likely to) use information found in procfs to generate its output.  Other information in procfs is less-consistent across different implementations, so consult your OS documentation.&lt;/p&gt;
&lt;p&gt;&lt;cite&gt;License: &lt;a href="http://www.gnu.org/licenses/gpl-3.0.txt"&gt;GPLv3&lt;/a&gt; (or later, at the discretion of Eric Wong)&lt;/cite&gt;&lt;/p&gt;</description><author>normalperson@yhbt.net (Eric Wong)</author><pubDate>Sat, 17 Sep 2011 03:32:00 -0400</pubDate><link>http://blog.rubybestpractices.com/posts/ewong/006-The-Unix-object-model.html</link><guid>http://blog.rubybestpractices.com/posts/ewong/006-The-Unix-object-model.html</guid></item><item><title>USP: Avoiding system calls</title><description>&lt;p&gt;Eric Wong wrote:&lt;/p&gt;
&lt;p&gt;&lt;cite&gt;As mentioned before, syscalls are the interface user space interacts with kernel space.  When a user space application makes a syscall, it is telling the kernel to execute code on its behalf.&lt;/cite&gt;&lt;/p&gt;
&lt;p&gt;The mode switch from user space to kernel space has more overhead and is slower than a normal library function call&lt;sup class="footnote" id="fnr1"&gt;&lt;a href="#fn1"&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;Thus user space can (and will often attempt to) aggregate several user space calls into fewer system calls to avoid this switching overhead.  This is a common concept found in user space code and Ruby itself is no exception.  This aggregation often does not happen transparently, so it should be understood and explained to avoid confusion.&lt;/p&gt;
&lt;h2&gt;I/O Buffering&lt;/h2&gt;
&lt;p&gt;As a Ruby programmer, you&amp;#8217;ll notice the IO class (and subclasses like File) will buffer data you write and you need to call IO#flush or set &amp;#8220;IO#sync = true&amp;#8221; to ensure other processes can read it.&lt;/p&gt;
&lt;p&gt;If you&amp;#8217;re a C programmer, you&amp;#8217;ll know the stdio library can do the same type of buffering in user space.   In fact, &lt;span class="caps"&gt;MRI&lt;/span&gt; 1.8 used the stdio library internally for its user space buffering needs.&lt;/p&gt;
&lt;p&gt;Kernel space may also implement its own buffering to avoid overhead when interacting with the storage and network layers.  This buffering can be influenced in some cases from Ruby.  We&amp;#8217;ll cover this later.&lt;/p&gt;
&lt;h2&gt;Memory Allocation&lt;/h2&gt;
&lt;p&gt;While Ruby programmers do not often worry about memory allocation, sometimes the following question comes up:&lt;/p&gt;
&lt;p style="padding-left:1em;"&gt;Why did my Ruby process stay so big even after I&amp;#8217;ve cleared all references to big objects?  I&amp;#8217;m /sure/ GC has run several times and freed my big objects and I&amp;#8217;m not leaking memory.&lt;/p&gt;
&lt;p&gt;A C programmer might ask the same question:&lt;/p&gt;
&lt;p style="padding-left:1em;"&gt;I free()-ed a lot of memory, why is my process still so big?&lt;/p&gt;
&lt;p&gt;Memory allocation to user space from the kernel is cheaper in large chunks, thus user space avoids interaction with the kernel by doing more work itself.&lt;/p&gt;
&lt;p&gt;User space libraries/runtimes implement a memory allocator (e.g.: malloc(3) in libc) which takes large chunks of kernel memory&lt;sup class="footnote" id="fnr2"&gt;&lt;a href="#fn2"&gt;2&lt;/a&gt;&lt;/sup&gt; and divides them up into smaller pieces for user space applications to use.&lt;/p&gt;
&lt;p&gt;Thus, several user space memory allocations may occur before user space needs to ask the kernel for more memory.  Thus if you got a large chunk of memory from the kernel and are only using a small part of that, that large chunk of memory remains allocated.&lt;/p&gt;
&lt;p&gt;Releasing memory back to the kernel also has a cost.  User space memory allocators may hold onto that memory (privately) in the hope it can be reused within the same process and not give it back to the kernel for use in other processes.&lt;/p&gt;
&lt;p class="footnote" id="fn1"&gt;&lt;a href="#fnr1"&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt; Why this is expensive outside the scope of this list so explaining this is left as an exercise for the reader :)&lt;/p&gt;
&lt;p class="footnote" id="fn2"&gt;&lt;a href="#fnr2"&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt; Via brk(2), sbrk(2), mmap(2) or various non-portable methods.&lt;/p&gt;
&lt;p&gt;&lt;cite&gt;License: &lt;a href="http://www.gnu.org/licenses/gpl-3.0.txt"&gt;GPLv3&lt;/a&gt; (or later, at the discretion of Eric Wong)&lt;/cite&gt;&lt;/p&gt;</description><author>normalperson@yhbt.net (Eric Wong)</author><pubDate>Thu, 15 Sep 2011 00:34:00 -0400</pubDate><link>http://blog.rubybestpractices.com/posts/ewong/005-Avoiding-system-calls.html</link><guid>http://blog.rubybestpractices.com/posts/ewong/005-Avoiding-system-calls.html</guid></item><item><title>USP: System calls in Unix</title><description>&lt;p&gt;As mentioned before, syscalls are the interface user space interacts with kernel space.  When a user space application makes a syscall, it is telling the kernel to execute code on its behalf.&lt;/p&gt;
&lt;p&gt;Ruby itself provides global &amp;#8220;syscall&amp;#8221; method on many platforms.  It is useful for learning and experimentation, but not recommended for general use as it is fragile and non-portable.   There is usually no need to use this method as many useful syscalls are already provided + wrapped by Ruby methods&lt;/p&gt;
&lt;p&gt;For a user space application to make a system call: architecture and OS-dependent code must be invoked.  At the lowest (userspace) levels this is implemented in non-portable assembly code.&lt;/p&gt;
&lt;p&gt;Fortunately, most system calls are already provided as wrappers by the system C library (libc) so they appear to user space as portable C functions.  Ruby itself wraps these C functions as Ruby methods.  Even non-C Ruby implementations are likely to call these C functions in libc (rather than implement the non-portable assembly themselves).&lt;/p&gt;
&lt;p&gt;Thus:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;IO.pipe in Ruby is a wrapper for the pipe(3) C function,&lt;/li&gt;
	&lt;li&gt;which in turn wraps the pipe(2) system call.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You may not find the pipe(3) manpage because pipe(3) is a very thin wrapper for the pipe(2) syscall and the pipe(2) manpage is equivalent.&lt;/p&gt;
&lt;p&gt;&lt;cite&gt;License: &lt;a href="http://www.gnu.org/licenses/gpl-3.0.txt"&gt;GPLv3&lt;/a&gt; (or later, at the discretion of Eric Wong)&lt;/cite&gt;&lt;/p&gt;</description><author>normalperson@yhbt.net (Eric Wong)</author><pubDate>Thu, 15 Sep 2011 00:34:00 -0400</pubDate><link>http://blog.rubybestpractices.com/posts/ewong/004-System-calls-in-Unix.html</link><guid>http://blog.rubybestpractices.com/posts/ewong/004-System-calls-in-Unix.html</guid></item><item><title>USP: Traditional Unix filesystem behavior</title><description>&lt;p&gt;Eric Wong wrote:&lt;/p&gt;
&lt;p&gt;&lt;cite&gt;Traditional filesystems are backed by stable storage (hard drives, &lt;span class="caps"&gt;SSD&lt;/span&gt;) and persists across reboots and shutdowns.  Some of these are designed for Unix and considered &lt;span class="caps"&gt;POSIX&lt;/span&gt;-compliant, while others were designed for other operating systems and incompatible with &lt;span class="caps"&gt;POSIX&lt;/span&gt; to various degrees.&lt;/cite&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class="caps"&gt;POSIX&lt;/span&gt;-compliant filesystems are the standard, other (including pseudo) filesystems attempt to expose a user-interface similar to those in &lt;span class="caps"&gt;POSIX&lt;/span&gt;-compliant filesystem.  Unfortunately this means there are sometimes leaky, incompatible, and even dangerous abstractions may be present.&lt;/p&gt;
&lt;p&gt;Unix filesystems are byte-oriented.  They have no notion of encodings, and thus cannot be case-insensitive.  They do not normalize path names or data in any way.  The lack of conversion and normalization makes path lookup operations fast.&lt;/p&gt;
&lt;p&gt;In a path name, only the \0&amp;quot; byte is disallowed.  The &amp;#8220;/&amp;#8221; byte is used to delimit directories so it may not exist in a path component itself.  Otherwise, path names may contain any other byte value (even gibberish).&lt;/p&gt;
&lt;p&gt;Regular files will store any binary data stream without altering it in the kernel.  Filesystem operations have no notion of &amp;#8220;lines&amp;#8221; and won&amp;#8217;t convert &lt;span class="caps"&gt;CRLF&lt;/span&gt; line endings to LF or vice-versa.&lt;/p&gt;
&lt;p&gt;There are many filesystem operations defined to be atomic in &lt;span class="caps"&gt;POSIX&lt;/span&gt;.  These atomic filesystem operations are ideal for helping multiple processes interact with each other safely.  Unfortunately, they also make &lt;span class="caps"&gt;POSIX&lt;/span&gt;-compliance difficult for implementations of network/distributed filesystems.&lt;/p&gt;
&lt;p&gt;We will cover atomic operations in detail as we progress, including caveats for working with non-&lt;span class="caps"&gt;POSIX&lt;/span&gt; filesystems.&lt;/p&gt;
&lt;p&gt;&lt;cite&gt;License: &lt;a href="http://www.gnu.org/licenses/gpl-3.0.txt"&gt;GPLv3&lt;/a&gt; (or later, at the discretion of Eric Wong)&lt;/cite&gt;&lt;/p&gt;</description><author>normalperson@yhbt.net (Eric Wong)</author><pubDate>Wed, 14 Sep 2011 23:55:00 -0400</pubDate><link>http://blog.rubybestpractices.com/posts/ewong/003-Traditional-Unix-filesystem-behavior.html</link><guid>http://blog.rubybestpractices.com/posts/ewong/003-Traditional-Unix-filesystem-behavior.html</guid></item><item><title>USP: An overview of the Unix filesystem</title><description>&lt;p&gt;Unix features a hierarchical filesystem visible to all running processes.  It is the primary shared namespace within a Unix system.&lt;/p&gt;
&lt;p&gt;As you may know, the top of this namespace starts at &amp;#8220;/&amp;#8221; (or the root) and subdirectories may be created under it, each path component separated by &amp;#8220;/&amp;#8221;.&lt;/p&gt;
&lt;p&gt;Filesystems may contain other filesystems.  The root filesystem on a modern Unix system almost always contains other filesystems.&lt;/p&gt;
&lt;p&gt;Filesystems may have several types of files: directories, symlinks, &lt;span class="caps"&gt;UNIX&lt;/span&gt; domain sockets, FIFOs, character devices, block devices and of course &amp;#8220;regular&amp;#8221; files.&lt;/p&gt;
&lt;p&gt;Traditional filesystems are backed by stable storage (hard drives, &lt;span class="caps"&gt;SSD&lt;/span&gt;) and persists across reboots and shutdowns.  Some of these are designed for Unix and considered &lt;span class="caps"&gt;POSIX&lt;/span&gt;-compliant, while others were designed for other operating systems and incompatible with &lt;span class="caps"&gt;POSIX&lt;/span&gt; to various degrees.&lt;/p&gt;
&lt;p&gt;Various pseudo-filesystems exist, but they are mostly non-standardized.  Among pseudo-filesystems, there are memory-only filesystems, network filesystems, proc (process information) filesystems, device filesystems, and filesystems for tuning / inspecting kernel and hardware.&lt;/p&gt;
&lt;p&gt;Pseudo-filesystems allow Unix-based operating systems to avoid implementing system calls only useful within a limited scope..&lt;/p&gt;
&lt;p&gt;The &amp;#8220;everything-is-a-file&amp;#8221; design and use of filesystems (even for non-storage tasks) allows a few system calls to be useful for multiple purposes.  This consistency improves the user experience by reducing the amount a systems programmer needs to know and also improving discoverability of the interfaces.&lt;/p&gt;
&lt;p&gt;As the amount of system calls is relatively small, learning Unix systems programming should be easier than in other operating systems.&lt;/p&gt;
&lt;p&gt;Plan 9 (the intended successor to Unix) takes &amp;#8220;everything-is-a-file&amp;#8221; more literally to further minimize the need for specialized system calls.  This Plan 9 idea (among others) is being co-opted into existing userspaces and operating systems.&lt;/p&gt;
&lt;p&gt;&lt;cite&gt;License: &lt;a href="http://www.gnu.org/licenses/gpl-3.0.txt"&gt;GPLv3&lt;/a&gt; (or later, at the discretion of Eric Wong)&lt;/cite&gt;&lt;/p&gt;</description><author>normalperson@yhbt.net (Eric Wong)</author><pubDate>Wed, 14 Sep 2011 23:30:00 -0400</pubDate><link>http://blog.rubybestpractices.com/posts/ewong/002-An-overview-of-the-Unix-filesystem.html</link><guid>http://blog.rubybestpractices.com/posts/ewong/002-An-overview-of-the-Unix-filesystem.html</guid></item><item><title>USP: The Unix object model (as seen from user space)</title><description>&lt;p&gt;If you&amp;#8217;re a Rubyist, you may already be familiar with object-oriented designs.  A running Unix/Unix-like kernel exposes two primary types of objects to userspace:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;Processes&lt;/li&gt;
	&lt;li&gt;Open files&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Processes&lt;/h2&gt;
&lt;p&gt;Processes are instances of running applications.  Ruby programs typically run as their own process&lt;sup class="footnote" id="fnr1"&gt;&lt;a href="#fn1"&gt;1&lt;/a&gt;&lt;/sup&gt; in userspace.  Kernels expose a Process IDentifier (&lt;span class="caps"&gt;PID&lt;/span&gt;) as positive integers to userspace programs to uniquely identify processes.&lt;/p&gt;
&lt;p&gt;Each &lt;span class="caps"&gt;PID&lt;/span&gt; represents one (private) process object in the OS kernel.  The &lt;span class="caps"&gt;PID&lt;/span&gt; is only a reference or pointer to that object.  Two running processes cannot have the same &lt;span class="caps"&gt;PID&lt;/span&gt;, and two PIDs cannot refer to the same process, but PIDs can be recycled and reused over time.&lt;/p&gt;
&lt;p&gt;PIDs are global in scope to each running Unix system.&lt;/p&gt;
&lt;p&gt;Processes are created from its parent using the fork(2) system call (which is wrapped by the Kernel#fork method in Ruby).&lt;/p&gt;
&lt;p&gt;We will cover processes more in later chapters / posts.&lt;/p&gt;
&lt;p class="footnote" id="fn1"&gt;&lt;a href="#fnr1"&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt; although experimental Multi-VM implementations exist that allow multiple Ruby VMs within a single process&lt;/p&gt;
&lt;h2&gt;Open Files&lt;/h2&gt;
&lt;p&gt;Running processes may create, open, and release objects known as &amp;#8220;files&amp;#8221; in kernel space using APIs provided in user space.  Much of Unix systems programming revolves around manipulating &amp;#8220;file&amp;#8221; objects of various types.&lt;/p&gt;
&lt;p&gt;The kernel exposes non-negative integers known as &amp;#8220;file descriptors&amp;#8221; to userspace.  These are similar to PIDs as they are integers which point to objects within the kernel.&lt;/p&gt;
&lt;p&gt;You may have heard the term: &amp;#8220;everything is a file&amp;#8221; in Unix literature.&lt;/p&gt;
&lt;p&gt;Indeed, each integer file descriptor may refer to one of several types of objects within a running kernel.  All of these objects can be called &amp;#8220;files&amp;#8221; even if they&amp;#8217;re not stored on hard disks or visible on the filesystem.&lt;/p&gt;
&lt;p&gt;File descriptors may be reused and recycled within the lifetime a process.  They are more frequently recycled than PIDs.&lt;/p&gt;
&lt;p&gt;Each process has its own file descriptor table (inherited from its parent).&lt;/p&gt;
&lt;p&gt;Unlike PIDs, several file descriptors may refer to the same file object inside the kernel.&lt;/p&gt;
&lt;p&gt;File descriptors have properties of their own that are not tied to the underlying file object in the kernel.&lt;/p&gt;
&lt;p&gt;As open files are the primary interface for processes to interact with the kernel, I expect the majority of my future posts to cover various aspects of file manipulation in-depth.&lt;/p&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;Processes are containers for open files (among other things).  Open files are objects in the Unix kernel that can be accessed from within processes.&lt;/p&gt;
&lt;p&gt;&lt;cite&gt;License: &lt;a href="http://www.gnu.org/licenses/gpl-3.0.txt"&gt;GPLv3&lt;/a&gt; (or later, at the discretion of Eric Wong)&lt;/cite&gt;&lt;/p&gt;</description><author>normalperson@yhbt.net (Eric Wong)</author><pubDate>Tue, 13 Sep 2011 04:24:00 -0400</pubDate><link>http://blog.rubybestpractices.com/posts/ewong/001-Object-Model.html</link><guid>http://blog.rubybestpractices.com/posts/ewong/001-Object-Model.html</guid></item><item><title>USP: Prerequisite Knowledge</title><description>&lt;h2&gt;Introduction (by RKlemme)&lt;/h2&gt;
&lt;p&gt;This series started out with &lt;a href="http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/387469"&gt;this posting of Eric&lt;/a&gt; to ruby-talk:&lt;/p&gt;
&lt;p&gt;&lt;cite&gt;I would like to do a series of mailing list posts on the subject of Unix systems programming in Ruby.  I only intend to cover standardized, &lt;span class="caps"&gt;POSIX&lt;/span&gt;-compliant features of the standard Ruby distribution.  No extensions or Linux-only parts.&lt;/cite&gt;&lt;/p&gt;
&lt;p&gt;I volunteered to edit his postings and mirror them on the &amp;#8220;Practicing Ruby&amp;#8221; blog (formerly &amp;#8220;Ruby Best Practices&amp;#8221;).  I will try to mirror articles as quickly as possible but the blog will certainly be lagging behind a bit.&lt;/p&gt;
&lt;p&gt;You may discuss articles here on the blog or on the mailing list where there are originally published: &lt;a href="mailto:usp.ruby@librelist.org"&gt;usp.ruby@librelist.org&lt;/a&gt; (&lt;a href="mailto:usp.ruby-subscribe@librelist.com"&gt;subscribe&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;Now let&amp;#8217;s start with the original text.&lt;/p&gt;
&lt;h2&gt;What you should know&lt;/h2&gt;
&lt;ul&gt;
	&lt;li&gt;You should know basic Ruby syntax.&lt;/li&gt;
	&lt;li&gt;Bourne shell knowledge will be useful, but not required.&lt;/li&gt;
	&lt;li&gt;You do not need to know C, though I&amp;#8217;ll refer to and map Ruby methods to corresponding or analogous C functions.&lt;/li&gt;
	&lt;li&gt;You must know that that two (or more) variables (in Ruby) can refer to the same underlying object.  This concept is present in Unix, so it is &lt;em&gt;very&lt;/em&gt; important one understand this:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre name="code" class="ruby"&gt;
       a = "this is a string"
       b = a      # 'b' refers to the same String object as 'a'
       a &amp;lt;&amp;lt; "!"   # modifies the String object 'a' points to

       "this is a string!" == a

       # You should understand why the following statements are true:
       "this is a string!" == b
       "this is a string" != b
&lt;/pre&gt;
&lt;h2&gt;Notations/conventions&lt;/h2&gt;
&lt;ul&gt;
	&lt;li&gt;Ruby method documentation references (should be the same as Ruby documentation)
	&lt;ul&gt;
		&lt;li&gt;IO.pipe &amp;#8212; class/singleton method&lt;/li&gt;
		&lt;li&gt;IO#stat &amp;#8212; instance method&lt;/li&gt;
	&lt;/ul&gt;&lt;/li&gt;
	&lt;li&gt;C function documentation references
	&lt;ul&gt;
		&lt;li&gt;pipe(2) &amp;#8212; &amp;#8220;#{function_name}(#{section})&amp;#8221;&lt;br /&gt;
               The C function manpage can be accessed as:&lt;br /&gt;
                    man #{section} #{function_name}&lt;br /&gt;
               so you can open documentation for pipe(2) using the command: man 2 pipe&lt;/li&gt;
	&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That&amp;#8217;s all I can think of for now&amp;#8230;&lt;/p&gt;
&lt;p&gt;&lt;cite&gt;License: &lt;a href="http://www.gnu.org/licenses/gpl-3.0.txt"&gt;GPLv3&lt;/a&gt; (or later, at the discretion of Eric Wong)&lt;/cite&gt;&lt;/p&gt;</description><author>normalperson@yhbt.net (Eric Wong)</author><pubDate>Tue, 13 Sep 2011 01:29:00 -0400</pubDate><link>http://blog.rubybestpractices.com/posts/ewong/000-Prerequisite-Knowledge.html</link><guid>http://blog.rubybestpractices.com/posts/ewong/000-Prerequisite-Knowledge.html</guid></item></channel></rss>
