diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1f76bfaa24..fab232a635 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,6 +15,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
   identity for filesystem checks per-thread.
   (#[1163](https://github.com/nix-rust/nix/pull/1163))
 - Derived `Ord`, `PartialOrd` for `unistd::Pid` (#[1189](https://github.com/nix-rust/nix/pull/1189))
+- Added `select::FdSet::fds` method to iterate over file descriptors in a set.
+  ([#1207](https://github.com/nix-rust/nix/pull/1207))
 
 ### Changed
 - Changed `fallocate` return type from `c_int` to `()` (#[1201](https://github.com/nix-rust/nix/pull/1201))
diff --git a/src/sys/select.rs b/src/sys/select.rs
index 32569acc70..a46985bc4c 100644
--- a/src/sys/select.rs
+++ b/src/sys/select.rs
@@ -1,4 +1,6 @@
+use std::iter::FusedIterator;
 use std::mem;
+use std::ops::Range;
 use std::os::unix::io::RawFd;
 use std::ptr::{null, null_mut};
 use libc::{self, c_int};
@@ -59,14 +61,33 @@ impl FdSet {
     ///
     /// [`select`]: fn.select.html
     pub fn highest(&mut self) -> Option<RawFd> {
-        for i in (0..FD_SETSIZE).rev() {
-            let i = i as RawFd;
-            if unsafe { libc::FD_ISSET(i, self as *mut _ as *mut libc::fd_set) } {
-                return Some(i)
-            }
-        }
+        self.fds(None).next_back()
+    }
 
-        None
+    /// Returns an iterator over the file descriptors in the set.
+    /// 
+    /// For performance, it takes an optional higher bound: the iterator will
+    /// not return any elements of the set greater than the given file
+    /// descriptor.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # extern crate nix;
+    /// # use nix::sys::select::FdSet;
+    /// # use std::os::unix::io::RawFd;
+    /// let mut set = FdSet::new();
+    /// set.insert(4);
+    /// set.insert(9);
+    /// let fds: Vec<RawFd> = set.fds(None).collect();
+    /// assert_eq!(fds, vec![4, 9]);
+    /// ```
+    #[inline]
+    pub fn fds(&mut self, highest: Option<RawFd>) -> Fds {
+        Fds {
+            set: self,
+            range: 0..highest.map(|h| h as usize + 1).unwrap_or(FD_SETSIZE),
+        }
     }
 }
 
@@ -76,6 +97,46 @@ impl Default for FdSet {
     }
 }
 
+/// Iterator over `FdSet`.
+#[derive(Debug)]
+pub struct Fds<'a> {
+    set: &'a mut FdSet,
+    range: Range<usize>,
+}
+
+impl<'a> Iterator for Fds<'a> {
+    type Item = RawFd;
+
+    fn next(&mut self) -> Option<RawFd> {
+        while let Some(i) = self.range.next() {
+            if self.set.contains(i as RawFd) {
+                return Some(i as RawFd);
+            }
+        }
+        None
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        let (_, upper) = self.range.size_hint();
+        (0, upper)
+    }
+}
+
+impl<'a> DoubleEndedIterator for Fds<'a> {
+    #[inline]
+    fn next_back(&mut self) -> Option<RawFd> {
+        while let Some(i) = self.range.next_back() {
+            if self.set.contains(i as RawFd) {
+                return Some(i as RawFd);
+            }
+        }
+        None
+    }
+}
+
+impl<'a> FusedIterator for Fds<'a> {}
+
 /// Monitors file descriptors for readiness
 ///
 /// Returns the total number of ready file descriptors in all sets. The sets are changed so that all
@@ -100,9 +161,9 @@ impl Default for FdSet {
 ///
 /// [`FdSet::highest`]: struct.FdSet.html#method.highest
 pub fn select<'a, N, R, W, E, T>(nfds: N,
-                                 readfds: R,
-                                 writefds: W,
-                                 errorfds: E,
+    readfds: R,
+    writefds: W,
+    errorfds: E,
                                  timeout: T) -> Result<c_int>
 where
     N: Into<Option<c_int>>,
@@ -129,7 +190,7 @@ where
     let writefds = writefds.map(|set| set as *mut _ as *mut libc::fd_set).unwrap_or(null_mut());
     let errorfds = errorfds.map(|set| set as *mut _ as *mut libc::fd_set).unwrap_or(null_mut());
     let timeout = timeout.map(|tv| tv as *mut _ as *mut libc::timeval)
-                         .unwrap_or(null_mut());
+        .unwrap_or(null_mut());
 
     let res = unsafe {
         libc::select(nfds, readfds, writefds, errorfds, timeout)
@@ -168,10 +229,10 @@ where
 ///
 /// [`FdSet::highest`]: struct.FdSet.html#method.highest
 pub fn pselect<'a, N, R, W, E, T, S>(nfds: N,
-                                     readfds: R,
-                                     writefds: W,
-                                     errorfds: E,
-                                     timeout: T,
+    readfds: R,
+    writefds: W,
+    errorfds: E,
+    timeout: T,
                                      sigmask: S) -> Result<c_int>
 where
     N: Into<Option<c_int>>,
@@ -279,6 +340,20 @@ mod tests {
         assert_eq!(set.highest(), Some(7));
     }
 
+    #[test]
+    fn fdset_fds() {
+        let mut set = FdSet::new();
+        assert_eq!(set.fds(None).collect::<Vec<_>>(), vec![]);
+        set.insert(0);
+        assert_eq!(set.fds(None).collect::<Vec<_>>(), vec![0]);
+        set.insert(90);
+        assert_eq!(set.fds(None).collect::<Vec<_>>(), vec![0, 90]);
+
+        // highest limit
+        assert_eq!(set.fds(Some(89)).collect::<Vec<_>>(), vec![0]);
+        assert_eq!(set.fds(Some(90)).collect::<Vec<_>>(), vec![0, 90]);
+    }
+
     #[test]
     fn test_select() {
         let (r1, w1) = pipe().unwrap();
@@ -311,9 +386,9 @@ mod tests {
 
         let mut timeout = TimeVal::seconds(10);
         assert_eq!(1, select(Some(fd_set.highest().unwrap() + 1),
-                             &mut fd_set,
-                             None,
-                             None,
+                &mut fd_set,
+                None,
+                None,
                              &mut timeout).unwrap());
         assert!(fd_set.contains(r1));
         assert!(!fd_set.contains(r2));
@@ -331,9 +406,9 @@ mod tests {
 
         let mut timeout = TimeVal::seconds(10);
         assert_eq!(1, select(::std::cmp::max(r1, r2) + 1,
-                             &mut fd_set,
-                             None,
-                             None,
+                &mut fd_set,
+                None,
+                None,
                              &mut timeout).unwrap());
         assert!(fd_set.contains(r1));
         assert!(!fd_set.contains(r2));