sysfs文件系统之建立文件

xiaoxiao2021-02-28  101

------------------------------------------------ #纯属个人理解,如有问题敬请谅解! #kernel version: 2.6.26 #Author: andy wang ------------------------------------------------- 在linux内核fs/sysfs目录下面dir.c是建立目录的文件, file.c定义了建立属性文件相关函数,创建二进制文件的函数定义在bin.c 中. sysfs创建目录文件 sysfs建立目录的软件流程sysfs_create_dir()->create_dir()->sysfs_new_dirent()->sysfs_add_one(); 在sysfs中每个目录都对应一个kobj结构 , 每个文件(包括目录文件)都对应一个sysfs_dirent对象 ,在建立目录和文件后, 内存中会形成一颗以sysfs_root为根的目录树结构. 下面是create_dir()的代码: 610 static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd, const char *name, struct sysfs_dirent **p_sd) 612 { 613 umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO; 614 struct sysfs_addrm_cxt acxt; 615 struct sysfs_dirent *sd; 616 int rc; 618 /* allocate */ 619 sd = sysfs_new_dirent(name, mode, SYSFS_DIR); 620 if (!sd) 621 return -ENOMEM; 622 sd->s_dir.kobj = kobj; 623 624 /* link in */ 625 sysfs_addrm_start(&acxt, parent_sd); 626 rc = sysfs_add_one(&acxt, sd); 627 sysfs_addrm_finish(&acxt); 628 629 if (rc == 0) 630 *p_sd = sd; 631 else 632 sysfs_put(sd); 633 634 return rc; 635 } 第613行指定文件的mode为目录文件可读写, 接下来第619行sysfs_new_dirent()为文件分配对应的sysfs_dirent对象 ,, sd->s_dir.kobj = kobj找到它的kobj对象,也可以进一步说明这是一个目录文件. 第625-627行API的目的是将建立的sysfs_dirent对象加到以sysfs_root对象为根的目录树中 ,在以后动态建立文件时会根据名字查找到它 最后就是返回sysfs_dirent对象, 将kobj->sd指向它. 好了,这个目录的信息就已经记录在内存中了. sysfs创建属性文件 sysfs建立属性文件的流程: sysfs_create_file()->sysfs_add_file()->sysfs_add_file_mode(); 下面重点看看sysfs_add_file_mode()函数的实现: 480 int sysfs_add_file_mode(struct sysfs_dirent *dir_sd,const struct attribute *attr, int type, mode_t amode) 482 { 483 umode_t mode = (amode & S_IALLUGO) | S_IFREG; 484 struct sysfs_addrm_cxt acxt; 485 struct sysfs_dirent *sd; 486 int rc; 488 sd = sysfs_new_dirent(attr->name, mode, type); 489 if (!sd) 490 return -ENOMEM; 491 sd->s_attr.attr = (void *)attr; 493 sysfs_addrm_start(&acxt, dir_sd); 494 rc = sysfs_add_one(&acxt, sd); 495 sysfs_addrm_finish(&acxt); 497 if (rc) 498 sysfs_put(sd); 500 return rc; 501 } 第488行函数在cache中创建一个sysfs_dirent对象 ,接下来sd->s_attr.attr = (void *)attr;初始化文件属性 第493-495行函数的目的会根据父目录的sysfs_dirent对象把刚才建立的sysfs_dirent加入到目录树中. VFS动态创建sysfs文件 先看看sysfs目录文件索引节点操作方法的定义 const struct inode_operations sysfs_dir_inode_operations = { .lookup = sysfs_lookup, .setattr = sysfs_setattr, }; 在以前的文章中已经介绍过vfs查找文件创建inode的过程 inode->i_op->lookup() 在sysfs中目录文件inode定义的这个回调函数是sysfs_lookup() 665 static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) 667 { 668 struct dentry *ret = NULL; 669 struct sysfs_dirent *parent_sd = dentry->d_parent->d_fsdata; 670 struct sysfs_dirent *sd; 671 struct inode *inode; 673 mutex_lock(&sysfs_mutex); 675 sd = sysfs_find_dirent(parent_sd, dentry->d_name.name); 677 /* no such entry */ 678 if (!sd) { 679 ret = ERR_PTR(-ENOENT); 680 goto out_unlock; 681 } 683 /* attach dentry and inode */ 684 inode = sysfs_get_inode(sd); 685 if (!inode) { 686 ret = ERR_PTR(-ENOMEM); 687 goto out_unlock; 688 } 690 /* instantiate and hash dentry */ 691 dentry->d_op = &sysfs_dentry_ops; 692 dentry->d_fsdata = sysfs_get(sd); 693 d_instantiate(dentry, inode); 694 d_rehash(dentry); 696 out_unlock: 697 mutex_unlock(&sysfs_mutex); 698 return ret; 699 } 先看第669行,在上篇文章中介绍过sysfs根目录的sysfs_dirent对象初始化给了根目录的dentry. 这个时候就需要取出这个sysfs_dirent对象了 第675行代码就是根据文件名字查找出对应的sysfs_dirent对象. 第684行函数会在内存中建立文件的索引节点inode, 并由sfs_dirent对象初始化这个indoe, 初始化indoe的函数为sysfs_init_inode() 前面已经分析过了. 第692行函数dentry->d_fsdata = sysfs_get(sd); 把这个文件的sysfs_dirent对象初始化给目录项对象dentyr. 693-694行,关联文件inode和dentry, 并把dentry加入到对应的散列表中. 到这里这个文件的inode和dentry就在内存中建立起来了.
转载请注明原文地址: https://www.6miu.com/read-48420.html

最新回复(0)