diff --git a/scheme/debug.rs b/scheme/debug.rs
index 8f63bf654f6f832206032332014f2a14f09db3fa..0dc67267ac9a17831497c37e8b40085b914440b1 100644
--- a/scheme/debug.rs
+++ b/scheme/debug.rs
@@ -1,6 +1,6 @@
 use collections::VecDeque;
 use core::str;
-use spin::{Mutex, MutexGuard, Once};
+use spin::{Mutex, Once};
 
 use context;
 use syscall::Result;
diff --git a/scheme/irq.rs b/scheme/irq.rs
new file mode 100644
index 0000000000000000000000000000000000000000..9d7d42dae7353c3fbef37c8add16139941ff6c2c
--- /dev/null
+++ b/scheme/irq.rs
@@ -0,0 +1,57 @@
+use core::{mem, str};
+
+use arch::interrupt::irq::COUNTS;
+use context;
+use syscall::{Error, Result};
+use super::Scheme;
+
+pub struct IrqScheme;
+
+impl Scheme for IrqScheme {
+    fn open(&mut self, path: &[u8], _flags: usize) -> Result<usize> {
+        let path_str = str::from_utf8(path).or(Err(Error::NoEntry))?;
+        let id = path_str.parse::<usize>().or(Err(Error::NoEntry))?;
+        if id < COUNTS.lock().len() {
+            Ok(id)
+        } else {
+            Err(Error::NoEntry)
+        }
+    }
+
+    fn dup(&mut self, file: usize) -> Result<usize> {
+        Ok(file)
+    }
+
+    fn read(&mut self, file: usize, buffer: &mut [u8]) -> Result<usize> {
+        // Ensures that the length of the buffer is larger than the size of a usize
+        if buffer.len() >= mem::size_of::<usize>() {
+            let current = COUNTS.lock()[file];
+            loop {
+                let next = COUNTS.lock()[file];
+                if next != current {
+                    // Safe if the length of the buffer is larger than the size of a usize
+                    assert!(buffer.len() >= mem::size_of::<usize>());
+                    unsafe { *(buffer.as_mut_ptr() as *mut usize) = next };
+                    return Ok(mem::size_of::<usize>());
+                } else {
+                    // Safe if all locks have been dropped
+                    unsafe { context::switch(); }
+                }
+            }
+        } else {
+            Err(Error::InvalidValue)
+        }
+    }
+
+    fn write(&mut self, _file: usize, _buffer: &[u8]) -> Result<usize> {
+        Err(Error::NotPermitted)
+    }
+
+    fn fsync(&mut self, file: usize) -> Result<()> {
+        Ok(())
+    }
+
+    fn close(&mut self, file: usize) -> Result<()> {
+        Ok(())
+    }
+}
diff --git a/scheme/mod.rs b/scheme/mod.rs
index af9f0a9a71e8c04fc25c3e078f1760aff71c71a0..6ca5c1357999b2e19baceb954448883f0445255b 100644
--- a/scheme/mod.rs
+++ b/scheme/mod.rs
@@ -18,6 +18,7 @@ use syscall::{Error, Result};
 use self::debug::DebugScheme;
 use self::env::EnvScheme;
 use self::initfs::InitFsScheme;
+use self::irq::IrqScheme;
 
 /// Debug scheme
 pub mod debug;
@@ -28,6 +29,9 @@ pub mod env;
 /// InitFS scheme
 pub mod initfs;
 
+/// IRQ handling
+pub mod irq;
+
 /// Limit on number of schemes
 pub const SCHEME_MAX_SCHEMES: usize = 65536;
 
@@ -98,6 +102,7 @@ fn init_schemes() -> RwLock<SchemeList> {
     list.insert(Box::new(*b"debug"), Arc::new(Mutex::new(Box::new(DebugScheme)))).expect("failed to insert debug: scheme");
     list.insert(Box::new(*b"env"), Arc::new(Mutex::new(Box::new(EnvScheme::new())))).expect("failed to insert env: scheme");
     list.insert(Box::new(*b"initfs"), Arc::new(Mutex::new(Box::new(InitFsScheme::new())))).expect("failed to insert initfs: scheme");
+    list.insert(Box::new(*b"irq"), Arc::new(Mutex::new(Box::new(IrqScheme)))).expect("failed to insert irq: scheme");
     RwLock::new(list)
 }