Linux系统的/dev/zero文件是什么,怎么实现的
-
1 /dev/zero概述
在类UNIX 操作系统中, /dev/zero 是一个特殊的文件,当你读它的时候,它会提供无限的空字符(NULL, ASCII NUL, 0x00)。其中的一个典型用法是用它提供的字符流来覆盖信息,另一个常见用法是产生一个特定大小的空白文件。BSD就是通过mmap把/dev/zero映射到虚地址空间实现共享内存的。可以使用mmap将/dev/zero映射到一个虚拟的内存空间,这个操作的效果等同于使用一段匿名的内存(没有和任何文件相关)。
操作系统给用户新分配的内容(通过mmap或者brk)都是清零过的,但是这些虚拟地址通常都是按需分配物理页面。这里的“按需”的需求可能是读取,也可能是写入。如果只是读取,只要保证读取内容是零即可,在MMU的基础上,可以让“所有”虚拟地址都映射到内容为0的物理页面中。这样如果申请的内存大部分情况下都只是读取操作,那么并不会增加系统物理内存消耗量。
dd if=/dev/zero of=sun.txt bs=1M count=1 该命令创建了一个 1M 大小的文件 sun.txt,并将文件清零,其中参数解释: if 代表输入文件。如果不指定 if,默认就会从 stdin 中读取输入。 of 代表输出文件。如果不指定 of,默认就会将 stdout 作为默认输出。 bs 代表字节为单位的块大小。 count 代表被复制的块数。 /dev/zero 是一个字符设备,会不断返回 0 值字节(\0)。
linux万物皆是文件:
Linux内核对世界的定义,是把CPU认为是自我,除此以外所有的东西,都是外部。
内核与自我的交互,通过直接的机器指令实现,例如陷入中断(int)等。
内核与外部的交互,是通过把所有的外部事物抽象成统一的文件对象来实现的。内存是个文件(/dev/mem),硬盘是个文件(/dev/sda1),硬盘上的一个数据块是个文件(/home/xxx.dat,此处很神奇,需要细细品),鼠标是个文件(/dev/psaux),网卡、光盘等等都是文件。凡是支持读数据和写数据的东西,都是文件,万物皆文件。所有的文件组成了内核的虚拟文件系统(VFS),这个系统中记录内核可以读和写的所有文件。
文件这个概念这么好用,于是内核开始疯狂的使用文件概念来实现特定功能。需要个读出来都是空数据、写入数据没有任何side-effect的文件,就命名为/dev/null;需要个读出来都是0字符的文件,就是/dev/zero;等等。
2 /dev/zero的实现
2.1 shmem_zero_setup
/** * shmem_zero_setup - setup a shared anonymous mapping * @vma: the vma to be mmapped is prepared by do_mmap_pgoff */ int shmem_zero_setup(struct vm_area_struct *vma) { struct file *file; loff_t size = vma->vm_end - vma->vm_start; /* * Cloning a new file under mmap_sem leads to a lock ordering conflict * between XFS directory reading and selinux: since this file is only * accessible to the user through its mapping, use S_PRIVATE flag to * bypass file security, in the same way as shmem_kernel_file_setup(). */ file = __shmem_file_setup("dev/zero", size, vma->vm_flags, S_PRIVATE); vma->vm_file = file; vma->vm_ops = &shmem_vm_ops; return 0; }
2.2 shmem_kernel_file_setup
struct file *shmem_kernel_file_setup(const char *name, loff_t size, unsigned long flags) { return __shmem_file_setup(shm_mnt, name, size, flags, S_PRIVATE); } static struct file *__shmem_file_setup(struct vfsmount *mnt, const char *name, loff_t size, unsigned long flags, unsigned int i_flags) { struct file *res; struct inode *inode; struct path path; struct super_block *sb; struct qstr this; shmem_acct_size(flags, size); this.name = name; this.len = strlen(name); this.hash = 0; /* will go */ sb = mnt->mnt_sb; path.mnt = mntget(mnt); path.dentry = d_alloc_pseudo(sb, &this);//虚拟dentry d_set_d_op(path.dentry, &anon_ops); inode = shmem_get_inode(sb, NULL, S_IFREG | S_IRWXUGO, 0, flags);//获取file inode->i_flags |= i_flags; d_instantiate(path.dentry, inode); inode->i_size = size; clear_nlink(inode); /* It is unlinked */ ramfs_nommu_expand_for_mapping(inode, size); res = alloc_file(&path, FMODE_WRITE | FMODE_READ, &shmem_file_operations); return res; }
2.3 alloc_file
struct file *alloc_file(const struct path *path, fmode_t mode, const struct file_operations *fop) { struct file *file; file = get_empty_filp(); file->f_path = *path; file->f_inode = path->dentry->d_inode; file->f_mapping = path->dentry->d_inode->i_mapping; file->f_wb_err = filemap_sample_wb_err(file->f_mapping); if ((mode & FMODE_READ) && likely(fop->read || fop->read_iter)) mode |= FMODE_CAN_READ; if ((mode & FMODE_WRITE) && likely(fop->write || fop->write_iter)) mode |= FMODE_CAN_WRITE; file->f_mode = mode; file->f_op = fop; if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) i_readcount_inc(path->dentry->d_inode); return file; } struct file *get_empty_filp(void) { const struct cred *cred = current_cred(); struct file *f; //f 清零 f = kmem_cache_zalloc(filp_cachep, GFP_KERNEL); percpu_counter_inc(&nr_files); f->f_cred = get_cred(cred); error = security_file_alloc(f); atomic_long_set(&f->f_count, 1); rwlock_init(&f->f_owner.lock); spin_lock_init(&f->f_lock); mutex_init(&f->f_pos_lock); eventpoll_init_file(f); return f; }
3 mmap共享匿名映射
mmap 的共享匿名映射其实本质上还是共享文件映射,只不过这个文件比较特殊,创建于 dev/zero 目录下的 tmpfs 文件系统中。
unsigned long mmap_region(struct file *file, unsigned long addr, unsigned long len, vm_flags_t vm_flags, unsigned long pgoff, struct list_head *uf) { if (file) { ... } else if (vm_flags & VM_SHARED) { error = shmem_zero_setup(vma); } }
推荐阅读
- 上一篇: 360浏览器怎么关闭右下角“新闻早知道”弹窗
- 下一篇: Excel单元格背景色打印不出来怎么解决
文章标签:
版权声明: 本文除特别说明外均由 麒麟在线 原创
本文链接: https://www.70ol.com/jishu/298.html,尊重共享,欢迎转载,请自觉添加本文链接,谢谢!
分享本文: 请填写您的分享代码。
呃 本文暂时没人评论 来添加一个吧
发表评论