ping 127.0.0.1 > /dev/null

使用linux的人对于/dev/null这个设备并不会陌生,通常用于将程序的输出信息扔掉,如果不指定>/dev/null,将会输出到当前控制台,那么它是如何实现的呢?

这里我们不讲Libc里面管道等等知识,直接定位到 linux内核。

/dev/null是一个字符型设备,它的驱动代码位于 drivers/char/mem.c中

了解驱动编程的人看下面的结构体都知道,file_operations 对应的是libc中read write llseek等函数在驱动中的实现。

static const struct file_operations null_fops = {
	.llseek		= null_lseek,
	.read		= read_null,
	.write		= write_null,
	.read_iter	= read_iter_null,
	.write_iter	= write_iter_null,
	.splice_write	= splice_write_null,
};


static const struct memdev {
	const char *name;
	umode_t mode;
	const struct file_operations *fops;
	fmode_t fmode;
} devlist[] = {
#ifdef CONFIG_DEVMEM
	 [1] = { "mem", 0, &mem_fops, FMODE_UNSIGNED_OFFSET },
#endif
#ifdef CONFIG_DEVKMEM
	 [2] = { "kmem", 0, &kmem_fops, FMODE_UNSIGNED_OFFSET },
#endif
	 [3] = { "null", 0666, &null_fops, 0 },
#ifdef CONFIG_DEVPORT
	 [4] = { "port", 0, &port_fops, 0 },
#endif
	 [5] = { "zero", 0666, &zero_fops, 0 },
	 [7] = { "full", 0666, &full_fops, 0 },
	 [8] = { "random", 0666, &random_fops, 0 },
	 [9] = { "urandom", 0666, &urandom_fops, 0 },
#ifdef CONFIG_PRINTK
	[11] = { "kmsg", 0644, &kmsg_fops, 0 },
#endif
};

外部进行读取的时候,会调用read_null函数,此处直接返回读取的长度是0,什么也没读到。

外部write写入时, 会调用到write_null 此处直接返回count,外部传递过来的buf直接无视。

也就相当于是把写入的数据扔掉了。

static ssize_t read_null(struct file *file, char __user *buf,
			 size_t count, loff_t *ppos)
{
	return 0;
}

static ssize_t write_null(struct file *file, const char __user *buf,
			  size_t count, loff_t *ppos)
{
	return count;
}

代码链接:

mem.c - drivers/char/mem.c - Linux source code (v4.4) - Bootlin

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐