linux设备驱动模型--open系统调用(创建文件)

前面 
  
   
 

linux设备驱动模型一字符设备open系统调用流程这里讲了linux open系统调用的流程,里面主要是打开一个已经存在的文件,但是当文件不存在时,如果指定了O_CREATE标志,并且可以创建文件的话,就会新创建一个文件,这里接着了解下文件的创建过程,这里的内核版本是3.0的,跟前面 这个不同,不过流程其实还是一样的

接着open系统调用到了do_last,进行一些初始化及判断后,调用vfs_create

		error = security_path_mknod(&nd->path, dentry, mode, 0);
		if (error)
			goto exit_mutex_unlock;
		
		error = vfs_create(dir->d_inode, dentry, mode, nd);
		if (error)
			goto exit_mutex_unlock;
		mutex_unlock(&dir->d_inode->i_mutex);
		dput(nd->path.dentry);
		nd->path.dentry = dentry;
		goto common;

vfs_create函数比较简单,

int vfs_create(struct inode *dir, struct dentry *dentry, int mode,
		struct nameidata *nd)
{
	int error = may_create(dir, dentry);
	printk("leaves Enter %s \n", __FUNCTION__);
	printk("leaves dentry %s \n", dentry->d_name.name);
	if (error)
		return error;

	if (!dir->i_op->create)
		return -EACCES;	/* shouldn't it be ENOSYS? */
	mode &= S_IALLUGO;
	mode |= S_IFREG;
	error = security_inode_create(dir, dentry, mode);
	if (error)
		return error;
	error = dir->i_op->create(dir, dentry, mode, nd);
	if (!error)
		fsnotify_create(dir, dentry);
	printk("leaves Exit %s \n", __FUNCTION__);
	return error;
}
基本上就是直接调用父节点的inode_operations的create方法,这里以在/dev目录下面创建文件为例,我们知道,/dev目录的文件系统为tmpfs

在系统启动的时候,一般有mount("tmpfs", "/dev", "tmpfs", 0, "mode=0755");

而在创建/dev目录的时候,就会将其i_op设置为shmem_dir_inode_operations,所以这时对应调用shmem_create这个方法。
static int shmem_create(struct inode *dir, struct dentry *dentry, int mode,
		struct nameidata *nd)
{
	return shmem_mknod(dir, dentry, mode | S_IFREG, 0);
}
这个函数只是一个简单的封装

/*
 * File creation. Allocate an inode, and we're done..
 */
static int
shmem_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
{
	struct inode *inode;
	int error = -ENOSPC;

	inode = shmem_get_inode(dir->i_sb, dir, mode, dev, VM_NORESERVE);//获取一个inode节点
	if (inode) {
		error = security_inode_init_security(inode, dir,
						     &dentry->d_name, NULL,
						     NULL, NULL);
		if (error) {
			if (error != -EOPNOTSUPP) {
				iput(inode);
				return error;
			}
		}
#ifdef CONFIG_TMPFS_POSIX_ACL
		error = generic_acl_init(inode, dir);
		if (error) {
			iput(inode);
			return error;
		}
#else
		error = 0;
#endif
		dir->i_size += BOGO_DIRENT_SIZE;
		dir->i_ctime = dir->i_mtime = CURRENT_TIME;
		d_instantiate(dentry, inode);//为一个目录项填充索引节点信息
		dget(dentry); /* Extra count - pin the dentry in core */
	}
	return error;
}

这里调用shmem_get_inode  new一个i节点

static struct inode *shmem_get_inode(struct super_block *sb, const struct inode *dir,
				     int mode, dev_t dev, unsigned long flags)
{
	struct inode *inode;
	struct shmem_inode_info *info;
	struct shmem_sb_info *sbinfo = SHMEM_SB(sb);

	if (shmem_reserve_inode(sb))
		return NULL;

	inode = new_inode(sb);//新建一个i节点
	if (inode) {
		inode->i_ino = get_next_ino();
		inode_init_owner(inode, dir, mode);
		inode->i_blocks = 0;
		inode->i_mapping->backing_dev_info = &shmem_backing_dev_info;
		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
		inode->i_generation = get_seconds();
		info = SHMEM_I(inode);
		memset(info, 0, (char *)inode - (char *)info);
		spin_lock_init(&info->lock);
		info->flags = flags & VM_NORESERVE;
		INIT_LIST_HEAD(&info->swaplist);
		INIT_LIST_HEAD(&info->xattr_list);
		cache_no_acl(inode);

		switch (mode & S_IFMT) {//设置i节点的i节点操作和文件操作
		default:
			inode->i_op = &shmem_special_inode_operations;
			init_special_inode(inode, mode, dev);
			break;
		case S_IFREG:
			inode->i_mapping->a_ops = &shmem_aops;
			inode->i_op = &shmem_inode_operations;
			inode->i_fop = &shmem_file_operations;
			mpol_shared_policy_init(&info->policy,
						 shmem_get_sbmpol(sbinfo));
			break;
		case S_IFDIR:
			inc_nlink(inode);
			/* Some things misbehave if size == 0 on a directory */
			inode->i_size = 2 * BOGO_DIRENT_SIZE;
			inode->i_op = &shmem_dir_inode_operations;
			inode->i_fop = &simple_dir_operations;
			break;
		case S_IFLNK:
			/*
			 * Must not load anything in the rbtree,
			 * mpol_free_shared_policy will not be called.
			 */
			mpol_shared_policy_init(&info->policy, NULL);
			break;
		}
	} else
		shmem_free_inode(sb);
	return inode;
}

个人理解,创建一个文件和文件夹对linux来说没什么区别,都是新建一个i节点和一个目录项对象。


你可能感兴趣的:(linux设备驱动模型--open系统调用(创建文件))