diff --git a/System/Linux/Proc/Errors.hs b/System/Linux/Proc/Errors.hs
new file mode 100644
--- /dev/null
+++ b/System/Linux/Proc/Errors.hs
@@ -0,0 +1,28 @@
+{-# LANGUAGE LambdaCase #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+module System.Linux.Proc.Errors
+  ( ProcError (..)
+  , renderProcError
+  ) where
+
+import           Data.Text (Text)
+import qualified Data.Text as T
+
+
+data ProcError
+  = ProcReadError !FilePath !Text
+  | ProcParseError !FilePath !Text
+  | ProcMemInfoKeyError !Text
+  deriving (Eq, Show)
+
+renderProcError :: ProcError -> Text
+renderProcError = \case
+  ProcReadError fp msg -> T.concat
+    [ "Error reading '", T.pack fp, "': ", msg ]
+  ProcParseError fp msg -> T.concat
+    [ "Parser error on file '", T.pack fp, ": ", msg ]
+  ProcMemInfoKeyError key -> T.concat
+    [ "MemInfo: Key not found: '", key, "'" ]
+
+
diff --git a/System/Linux/Proc/File.hs b/System/Linux/Proc/File.hs
deleted file mode 100644
--- a/System/Linux/Proc/File.hs
+++ /dev/null
@@ -1,29 +0,0 @@
-{-# LANGUAGE OverloadedStrings #-}
-
-module System.Linux.Proc.File
-  ( readProcFile
-  ) where
-
-import           Control.Error (ExceptT, handleExceptT)
-
-import           Data.ByteString (ByteString)
-import qualified Data.ByteString.Char8 as BS
-
-import           Data.Text (Text)
-import qualified Data.Text as T
-
-import           System.IO (IOMode (..), withFile)
-
-import           System.Linux.Proc.Errors
-
-
-readProcFile :: FilePath -> ExceptT ProcError IO ByteString
-readProcFile fpath =
-  handleExceptT (ProcReadError fpath . ioErrorToText) $
-    -- BS.readFile won't work here because it tries to get the file
-    -- length before reading the file and files in the /proc filesystem
-    -- are reported as having zero length.
-    withFile fpath ReadMode BS.hGetContents
-
-ioErrorToText :: IOError -> Text
-ioErrorToText = T.pack . show
diff --git a/System/Linux/Proc/IO.hs b/System/Linux/Proc/IO.hs
new file mode 100644
--- /dev/null
+++ b/System/Linux/Proc/IO.hs
@@ -0,0 +1,35 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+module System.Linux.Proc.IO
+  ( listProcDirectory
+  , readProcFile
+  ) where
+
+import           Control.Error (ExceptT, handleExceptT)
+
+import           Data.ByteString (ByteString)
+import qualified Data.ByteString.Char8 as BS
+
+import           Data.Text (Text)
+import qualified Data.Text as T
+
+import           System.IO (IOMode (..), withFile)
+
+import           System.Directory (listDirectory)
+import           System.Linux.Proc.Errors
+
+
+readProcFile :: FilePath -> ExceptT ProcError IO ByteString
+readProcFile fpath =
+  handleExceptT (ProcReadError fpath . ioErrorToText) $
+    -- BS.readFile won't work here because it tries to get the file
+    -- length before reading the file and files in the /proc filesystem
+    -- are reported as having zero length.
+    withFile fpath ReadMode BS.hGetContents
+
+listProcDirectory :: FilePath -> ExceptT ProcError IO [FilePath]
+listProcDirectory fpath =
+  handleExceptT (ProcReadError fpath . ioErrorToText) $ listDirectory fpath
+
+ioErrorToText :: IOError -> Text
+ioErrorToText = T.pack . show
diff --git a/System/Linux/Proc/MemInfo.hs b/System/Linux/Proc/MemInfo.hs
--- a/System/Linux/Proc/MemInfo.hs
+++ b/System/Linux/Proc/MemInfo.hs
@@ -3,10 +3,11 @@
 module System.Linux.Proc.MemInfo
   ( MemInfo (..)
   , readProcMemInfo
+  , readProcMemInfoKey
   , readProcMemUsage
   ) where
 
-import           Control.Error (fromMaybe, runExceptT, throwE)
+import           Control.Error (ExceptT (..), fromMaybe, runExceptT, throwE)
 
 import           Data.Attoparsec.ByteString.Char8 (Parser)
 import qualified Data.Attoparsec.ByteString.Char8 as A
@@ -15,10 +16,11 @@
 
 import qualified Data.List as DL
 import qualified Data.Map.Strict as DM
+import           Data.Maybe (mapMaybe)
 import qualified Data.Text as T
 import           Data.Word (Word64)
 
-import           System.Linux.Proc.File
+import           System.Linux.Proc.IO
 import           System.Linux.Proc.Errors
 
 -- | A struct to contain information parsed from the `/proc/meminfo` file
@@ -69,15 +71,39 @@
     convert :: (Word64, Word64) -> Double
     convert (avail, total) = fromIntegral avail / fromIntegral total
 
-    fromEither :: a -> Either e a -> a
-    fromEither a (Left _) = a
-    fromEither _ (Right a) = a
+-- | Read the value for the given key from `/proc/meminfo`.
+-- Although this is in `IO` all exceptions and errors should be caught and
+-- returned as a `ProcError`.
+readProcMemInfoKey :: ByteString -> IO (Either ProcError Word64)
+readProcMemInfoKey target =
+  runExceptT $ do
+    xs <- BS.lines <$> readProcFile fpMemInfo
+    hoistEither . headEither keyError $ mapMaybe findValue xs
+  where
+    findValue :: ByteString -> Maybe Word64
+    findValue bs =
+      let (key, rest) = BS.break (== ':') bs in
+      if key /= target 
+        then Nothing
+        else either (const Nothing) Just $ A.parseOnly pValue rest
+    keyError :: ProcError
+    keyError = ProcMemInfoKeyError $ T.pack (BS.unpack target)
 
 -- -----------------------------------------------------------------------------
 -- Internals.
 
 fpMemInfo :: FilePath
 fpMemInfo = "/proc/meminfo"
+
+fromEither :: a -> Either e a -> a
+fromEither a = either (const a) id
+
+headEither :: e -> [a] -> Either e a
+headEither e [] = Left e
+headEither _ (x:_) = Right x
+
+hoistEither :: Monad m => Either e a -> ExceptT e m a
+hoistEither = ExceptT . pure
 
 construct :: [(ByteString, Word64)] -> MemInfo
 construct xs =
diff --git a/System/Linux/Proc/Process.hs b/System/Linux/Proc/Process.hs
new file mode 100644
--- /dev/null
+++ b/System/Linux/Proc/Process.hs
@@ -0,0 +1,29 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+module System.Linux.Proc.Process
+  ( ProcessId (..)
+  , getProcProcessIds
+  ) where
+
+import           Control.Error (runExceptT)
+
+import           Data.Maybe (mapMaybe)
+
+import           System.Linux.Proc.IO
+import           System.Linux.Proc.Errors
+
+newtype ProcessId
+  = ProcessId { unProcessId :: Int }
+  deriving (Eq, Show)
+
+-- | Get the current list of `ProcessId`s.
+getProcProcessIds :: IO (Either ProcError [ProcessId])
+getProcProcessIds =
+  runExceptT $
+    mapMaybe maybeProcessId <$> listProcDirectory "/proc"
+  where
+    maybeProcessId :: String -> Maybe ProcessId
+    maybeProcessId str =
+      case reads str of
+        [(i, "")] -> Just $ ProcessId i
+        _ -> Nothing
diff --git a/system-linux-proc.cabal b/system-linux-proc.cabal
--- a/system-linux-proc.cabal
+++ b/system-linux-proc.cabal
@@ -2,7 +2,7 @@
 -- documentation, see http://haskell.org/cabal/users-guide/
 
 name:                system-linux-proc
-version:             0.1.0.0
+version:             0.1.0.1
 synopsis:            A library for accessing the /proc filesystem in Linux
 -- description:
 homepage:            https://github.com/erikd/system-linux-proc
@@ -22,13 +22,16 @@
   ghc-options:        -Wall -fwarn-tabs
   hs-source-dirs:    .
 
-  exposed-modules:     System.Linux.Proc.MemInfo
-                     , System.Linux.Proc.File
+  exposed-modules:     System.Linux.Proc.Errors
+                     , System.Linux.Proc.IO
+                     , System.Linux.Proc.MemInfo
+                     , System.Linux.Proc.Process
 
   build-depends:       base                          >= 4.8         && < 5.0
                      , attoparsec                    == 0.13.*
                      , bytestring                    == 0.10.*
                      , containers                    == 0.5.*
+                     , directory                     == 1.3.*
                      , errors                        == 2.2.*
                      , text                          == 1.2.*
 
