Linux 命令:mknod
mknod 是 Linux 中手动创建特殊设备文件 的专用命令,核心作用是在 /dev 等目录下创建字符设备(char)、块设备(block)和命名管道(FIFO)文件,为内核设备驱动、进程间通信提供文件系统级的访问接口。Linux 中所有设备均以文件形式存在,大部分设备文件由系统自动创建,而 mknod 用于手动创建自定义/特殊设备文件,是内核开发、设备驱动调试、系统运维的基础工具。
资料合集:https://pan.quark.cn/s/6fe3007c3e95、https://pan.quark.cn/s/561de99256a5、https://pan.quark.cn/s/985f55b13d94、https://pan.quark.cn/s/d0fb20abd19a
核心背景
Linux 遵循一切皆文件 的设计理念,硬件设备(如硬盘、串口、显卡)、内核虚拟设备均通过设备文件 在文件系统中暴露接口,用户空间程序通过读写设备文件与内核设备驱动交互,无需直接操作硬件。
设备文件分为两类核心类型,且均有唯一的主设备号(major)和次设备号(minor):
- 字符设备:按字节流顺序访问,无缓存,如串口(tty)、键盘、鼠标、/dev/null,主设备号标识设备驱动,次设备号标识同驱动下的不同设备;
- 块设备:按固定大小块访问,有缓存,如硬盘(sd*)、U盘、分区,主/次设备号作用与字符设备一致;
- 命名管道(FIFO):特殊的进程间通信(IPC)文件,无主/次设备号,用于同一主机上的进程间数据传输。
系统默认通过 udev 机制自动创建设备文件,但在内核调试、自定义设备开发、系统初始化异常等场景下,需通过 mknod 手动创建设备文件,这是该命令的核心使用场景。
核心特点
- 专创特殊文件:仅用于创建字符设备、块设备、命名管道,无法创建普通文件/目录;
- 需指定设备标识:创建设备文件时必须指定主/次设备号,创建命名管道无需指定;
- 依赖内核驱动:创建的设备文件仅当内核存在对应主设备号的驱动时,才能实现实际设备访问;
- 权限可控:创建的文件支持通过 chmod/chown 修改传统权限,结合 ACL 实现精细化访问控制;
- 仅root可执行:创建设备文件需要root 权限(CAP_MKNOD 能力),普通用户无执行权限,保证系统设备安全;
- 轻量无依赖:直接与内核交互,无额外依赖,执行后立即在文件系统中生成对应特殊文件。
基本语法
mknod 语法围绕文件类型、设备号 设计,核心分为创建设备文件 和创建命名管道 两类,创建设备文件时必须指定主/次设备号,格式为主设备号.次设备号或主设备号 次设备号:
bash
# 核心语法:创建字符/块设备文件(需root权限)
mknod [选项] 设备文件名 [b|c|u] 主设备号 次设备号
# 语法:创建命名管道(FIFO)文件
mknod [选项] 管道文件名 p
# 简写格式:主/次设备号可用点分隔(与空格等价)
mknod 设备文件名 c 1 3 === mknod 设备文件名 c 1.3
关键类型标识说明
| 标识 | 文件类型 | 核心特性 | 示例 |
|---|---|---|---|
b |
块设备文件 | 块访问、有缓存,需主/次设备号 | 硬盘:mknod /dev/sdb b 8 16 |
c |
字符设备文件 | 字节流访问、无缓存,需主/次设备号 | 空设备:mknod /dev/null c 1 3 |
u |
字符设备文件(无缓冲) | 与c一致,部分系统为兼容标识,优先用c | 同c类型,无实际差异 |
p |
命名管道(FIFO) | 进程间通信,无主/次设备号,无设备驱动关联 | 管道:mknod /tmp/fifo.p p |
主/次设备号说明
- 主设备号(0-4095):标识内核中的设备驱动程序,相同主设备号对应同一驱动;
- 次设备号(0-255/65535):标识同一驱动下的不同物理/虚拟设备,如硬盘分区、多个串口;
- 号段分配:内核有固定的设备号分配规则(可通过
cat /proc/devices查看已注册的主设备号),自定义设备建议使用未分配的号段。
常用选项
mknod 设计极简,仅提供少量基础选项,围绕文件权限、创建路径设计,无冗余功能,日常使用掌握3个核心选项即可覆盖所有场景:
| 选项 | 核心作用 | 实用场景 |
|---|---|---|
-m |
指定创建文件的初始权限 | 无需创建后再执行chmod,直接设置权限,如-m 666表示所有用户读写 |
-Z |
设置文件的SELinux安全上下文 | 开启SELinux的系统中,直接指定上下文,避免后续执行chcon |
--help |
显示帮助信息 | 快速查看语法、类型标识说明,无需查阅手册 |
权限说明
- 设备文件权限:传统rwx权限,
r为读设备、w为写设备、x一般无意义(部分设备用于执行/ioctl); - 命名管道权限:
r为读管道、w为写管道,无x权限; - 默认权限:未指定
-m时,默认权限为0600(仅root读写),需根据需求修改。
经典实操示例
mknod 的使用场景分为创建设备文件 和创建命名管道 两大类,所有操作均需root权限(sudo/切换root),示例贴合内核调试、系统运维、进程间通信的真实场景,可直接复用。
前置准备
- 切换为root用户或使用sudo,获取执行权限;
- 查看系统已注册的设备号:
cat /proc/devices(查看字符设备用cat /proc/char_devices,块设备用cat /proc/block_devices); - 验证特殊文件类型:用
ls -l查看,设备文件首字符为b/c,命名管道首字符为p。
bash
# 切换root
su - root
# 查看已注册的字符/块设备主设备号
cat /proc/devices
# 示例输出:字符设备1为mem,3为tty,11为sound;块设备8为sd(硬盘)
场景1:创建经典字符设备------/dev/null(空设备)
/dev/null 是Linux核心的字符设备,用于丢弃所有写入的数据,读取则返回空,手动创建可验证mknod基础用法,主设备号1、次设备号3为内核固定分配:
bash
# 创建字符设备/dev/mynull,主1次3,初始权限666(所有用户读写)
mknod -m 666 /dev/mynull c 1 3
# 验证文件类型和权限(ls -l首字符为c,权限-rw-rw-rw-)
ls -l /dev/mynull
# 输出示例:crw-rw-rw- 1 root root 1, 3 月 日 时:分 /dev/mynull
# 测试设备功能(写入数据无输出,读取无内容)
echo "test" > /dev/mynull
cat /dev/mynull
场景2:创建块设备文件------硬盘分区设备
为硬盘分区创建手动设备文件,需先确认分区的主/次设备号(硬盘主设备号固定为8,次设备号按分区规则分配:sda1为1,sda2为2,sdb1为17,依此类推):
bash
# 创建块设备/dev/my_sdb1,对应U盘分区sdb1,主8次17,权限644
mknod -m 644 /dev/my_sdb1 b 8 17
# 验证文件类型(首字符为b)
ls -l /dev/my_sdb1
# 输出示例:brw-r--r-- 1 root root 8, 17 月 日 时:分 /dev/my_sdb1
# 测试访问(查看分区文件系统)
blkid /dev/my_sdb1
场景3:创建命名管道(FIFO)------进程间通信
创建命名管道实现两个进程间的单向数据传输,无需主/次设备号,标识为p,管道遵循先进先出原则,读进程会阻塞至有写进程写入数据:
bash
# 创建命名管道/tmp/ipc_fifo,初始权限666
mknod -m 666 /tmp/ipc_fifo p
# 验证文件类型(首字符为p)
ls -l /tmp/ipc_fifo
# 输出示例:prw-rw-rw- 1 root root 0 月 日 时:分 /tmp/ipc_fifo
# 测试进程间通信(打开两个终端)
# 终端1:读管道(阻塞,直到终端2写入数据)
cat /tmp/ipc_fifo
# 终端2:写管道(写入后终端1立即输出内容)
echo "Hello Linux IPC" > /tmp/ipc_fifo
场景4:创建自定义字符设备------内核调试
内核开发中,为自定义字符设备驱动创建设备文件,假设自定义驱动注册的主设备号为240(未分配号段),次设备号0为第一个自定义设备:
bash
# 创建自定义字符设备/dev/mydev,主240次0,权限600(仅root访问)
mknod -m 600 /dev/mydev c 240 0
# 验证设备文件
ls -l /dev/mydev
# 输出示例:crw------- 1 root root 240, 0 月 日 时:分 /dev/mydev
# 加载自定义驱动后,即可通过该文件与驱动交互
insmod mydev.ko
cat /dev/mydev # 读设备数据
echo "cmd" > /dev/mydev # 写设备指令
场景5:删除已创建的特殊文件
mknod 仅负责创建特殊文件,删除直接使用rm命令,与删除普通文件一致,删除后文件系统接口消失,不影响内核驱动:
bash
# 删除手动创建的字符设备
rm -f /dev/mynull
# 删除命名管道
rm -f /tmp/ipc_fifo
# 删除自定义块设备
rm -f /dev/my_sdb1
高频组合用法
mknod 常与ls -l(验证文件类型)、cat /proc/devices(查看设备号)、chmod/chown(修改权限)、insmod/rmmod(内核驱动操作)搭配,形成设备文件创建-驱动加载-权限配置-设备访问的完整流程,是内核开发、设备调试的标准操作组合。
组合1:自定义字符设备「驱动加载-设备创建-访问测试」
bash
# 步骤1:查看未分配的主设备号(确认240未被使用)
cat /proc/devices
# 步骤2:加载自定义内核驱动
insmod mychar_dev.ko
# 步骤3:创建设备文件,主240次0,权限660(root和dev组可访问)
mknod -m 660 /dev/mychar c 240 0
chown root:dev /dev/mychar
# 步骤4:测试设备访问(读驱动返回的测试数据)
cat /dev/mychar
# 步骤5:卸载驱动并删除设备文件
rmmod mychar_dev
rm -f /dev/mychar
组合2:命名管道「创建-多进程通信-清理」
bash
# 步骤1:创建命名管道,权限600(仅当前用户)
sudo mknod -m 600 /tmp/fifo p
sudo chown $USER:$USER /tmp/fifo
# 步骤2:终端1:启动读进程(持续读取管道数据)
while true; do cat /tmp/fifo; done
# 步骤3:终端2:启动写进程(向管道写入日志)
tail -f /var/log/messages > /tmp/fifo
# 步骤4:结束通信,清理管道
rm -f /tmp/fifo
组合3:系统设备恢复------手动重建/dev/tty(串口设备)
系统udev异常导致/dev/tty1(虚拟控制台)丢失时,手动重建,主设备号4、次设备号1为内核固定分配:
bash
# 步骤1:查看串口设备主设备号
grep tty /proc/devices
# 步骤2:重建tty1,主4次1,权限620(root和tty组)
mknod -m 620 /dev/tty1 c 4 1
chown root:tty /dev/tty1
# 步骤3:验证设备可用
ls /dev/tty1
关键注意事项
- 必须root权限:执行mknod需要root或CAP_MKNOD能力,普通用户执行会提示「权限拒绝」,可通过sudo提升权限;
- 设备号需匹配内核:创建的设备文件主设备号必须与内核中已注册的驱动一致,否则读写文件会提示「没有那个设备或地址」;
- 勿修改系统默认设备:系统自动创建的/dev下设备文件(如sd*、tty*、null)请勿手动删除/重建,否则会导致设备无法使用,异常时通过
udevadm trigger重建; - 命名管道与匿名管道的区别:mknod创建的是命名管道(FIFO) ,有文件系统路径,可跨任意进程使用;匿名管道由
|创建,无路径,仅能用于父子进程间通信; - 设备文件无实际数据:设备文件仅为访问接口,无实际文件内容,文件大小始终为0,读写操作均映射为内核驱动的函数调用;
- 权限配置需谨慎:设备文件权限过宽(如666)会导致普通用户随意访问/操作设备,造成系统安全风险,建议按「最小权限原则」配置(如仅root访问为600);
- 自定义设备号避用已分配段:查看
/proc/devices确认未分配的主设备号,自定义设备建议使用240-255(内核预留的自定义号段),避免与系统设备冲突。
与mkfifo的区别
mkfifo 是专门创建命名管道 的命令,与mknod 文件名 p功能完全一致,二者是等价实现,核心区别仅为专用性,可根据使用习惯选择:
| 命令 | 支持创建的文件类型 | 核心用途 | 等价用法 |
|---|---|---|---|
| mknod | 字符设备、块设备、命名管道 | 通用特殊文件创建,侧重设备文件 | mknod fifo.p p = mkfifo fifo.p |
| mkfifo | 仅命名管道 | 专用命名管道创建,侧重进程间通信 | 无其他功能,仅等价于mknod的p类型 |
使用建议:创建设备文件用mknod,创建命名管道用mkfifo,更符合命令语义,便于代码/脚本的可读性。
总结
mknod 是 Linux 中手动创建特殊设备文件的核心工具,核心价值是为内核设备驱动、进程间通信提供文件系统级的访问接口,实现用户空间与内核空间的交互,是内核开发、设备驱动调试、系统异常恢复的基础工具,核心要点可总结为:
- 核心功能:创建字符设备(c)、块设备(b)、命名管道(p),其中设备文件需指定主/次设备号,命名管道无需;
- 核心前提:必须root权限,设备文件主设备号需与内核驱动匹配,否则无法实际使用;
- 常用选项:
-m指定初始权限,是最核心的实用选项,避免后续执行chmod; - 类型识别:通过
ls -l首字符区分类型(b=块、c=字符、p=管道),所有特殊文件大小均为0; - 配套工具:与
cat /proc/devices(查设备号)、insmod(加载驱动)、chmod/chown(配权限)搭配使用; - 避坑关键:勿修改系统默认设备文件,按最小权限原则配置设备权限,自定义设备号使用内核预留段。