diff --git a/Makefile b/Makefile
index 7f91bac..26c831f 100644
--- a/Makefile
+++ b/Makefile
@@ -47,6 +47,7 @@ SRC = \
 	mc.c       \
 	mkdir.c    \
 	mkfifo.c   \
+	mknod.c    \
 	mv.c       \
 	nice.c     \
 	nl.c       \
diff --git a/mknod.1 b/mknod.1
new file mode 100644
index 0000000..db71f2d
--- /dev/null
+++ b/mknod.1
@@ -0,0 +1,40 @@
+.TH MKNOD 1 sbase\-VERSION
+.SH NAME
+mknod \- create a special device file
+
+.SH SYNOPSIS
+.B mknod
+.RB [ \-m
+.IR mode ]
+.I name
+.I type
+.I major
+.I minor
+
+.SH DESCRIPTION
+.B mknod
+Creates a special device file named
+.I name
+with major number
+.IR major ,
+and minor number
+.IR minor .
+
+.IR type
+specifies what kind of special file will be created, 
+and must be one of:
+.TP
+.BR u \ or\  c
+A character device.
+.TP
+.BR b
+A block device.
+
+.SH OPTIONS
+.TP
+.B \-m "mode"
+Set the mode of the new file based on the octal value of 
+.IR mode .
+
+.SH SEE ALSO
+.IR mknod (2)
diff --git a/mknod.c b/mknod.c
new file mode 100644
index 0000000..beb2ab7
--- /dev/null
+++ b/mknod.c
@@ -0,0 +1,46 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+#include "util.h"
+
+static void
+usage(void)
+{
+	eprintf("usage: mknod [-m mode] name type major minor\n");
+}
+
+int
+main(int argc, char **argv)
+{
+	mode_t type, mode = 0644;
+	mode_t types['u'+1];
+	dev_t dev;
+
+	types['u'] = types['c'] = S_IFCHR;
+	types['b'] = S_IFBLK;
+
+	ARGBEGIN {
+	case 'm':
+		mode = estrtol(EARGF(usage()), 8);
+		break;
+	default:
+		usage();
+	} ARGEND;
+
+	if(argc != 4)
+		usage();
+
+	if(strlen(argv[1]) != 1 || !strchr("ucb", argv[1][0]))
+		eprintf("mknod: '%s': invalid type\n", argv[1]);
+	type = types[(unsigned)argv[1][0]];
+
+	dev = makedev(estrtol(argv[2], 0), estrtol(argv[3], 0));
+
+	if(mknod(argv[0], type|mode, dev) == -1)
+		eprintf("mknod: '%s':", argv[0]);
+	return 0;
+}
