乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      對proc文件系統(tǒng)的分析(三)

       幸福的樂土 2012-01-05
      作者:

      zmwillow
      (journeyman)不知正確與否。

      這樣是表示對作者的尊重。

      如果有不對,請通知我,我將即時更改.

       
      五) 對proc文件的管理
      前面我們提過,相對于其他邏輯文件系統(tǒng)的具體文件組織形式(比如ext2文件系統(tǒng)的 inode),proc文件系統(tǒng)也有自己的組織結(jié)構(gòu),那就是proc_dir_entry結(jié)構(gòu),所有屬于proc文件系統(tǒng)的文件,都對應(yīng)一個 proc_dir_entry結(jié)構(gòu),并且在VFS需要讀取proc文件的時候,把這個結(jié)構(gòu)和VFS的inode建立鏈接(即由 inode->u.generic_ip指向該prc_dir_entry結(jié)構(gòu))。
      因此,proc文件系統(tǒng)實現(xiàn)了一套對proc_dir_entry結(jié)構(gòu)的管理,下面我們就此進(jìn)行一個分析。
      1 proc_dir_entry結(jié)構(gòu)
      首先我們看一下proc_dir_entry結(jié)構(gòu),這個結(jié)構(gòu)在proc_fs.h中定義:
      struct proc_dir_entry {
      unsigned short low_ino;
      unsigned short namelen;
      const char *name;
      mode_t mode;
      nlink_t nlink;
      uid_t uid;
      gid_t gid;
      unsigned long size;
      struct inode_operations * proc_iops;
      struct file_operations * proc_fops;
      get_info_t *get_info;
      struct module *owner;
      struct proc_dir_entry *next, *parent, *subdir;
      void *data;
      read_proc_t *read_proc;
      write_proc_t *write_proc;
      atomic_t count; /* use count */
      int deleted; /* delete flag */
      kdev_t rdev;
      };
      在這個結(jié)構(gòu)中,描述了一個proc文件的全部信息,每一個proc文件正是使用proc_dir_entry結(jié)構(gòu)來表示的。下面我們看一下它最重要的幾個域:
      low_ino:這是用來唯一標(biāo)志proc_dir_entry結(jié)構(gòu)的節(jié)點號,也就是proc文件系統(tǒng)內(nèi)的索引節(jié)點的標(biāo)號,除了根結(jié)點,其他的節(jié)點號都是在創(chuàng)建proc_dir_entry的時候,由make_inode_number()動態(tài)創(chuàng)建的。
      name:即這個proc文件的名字。
      mode: 該proc文件的模式由兩部分用位或運(yùn)算組成,第一部分是文件的類型,可以參考include/linux/stat.h中的定義,比如,S_IFREG 表示普通文件,而S_IFDIR表示目錄文件。第二部分是該文件的權(quán)限,同樣可以參考include/linux/stat.h中的定義,比 如,S_IRUSR表示該文件能夠被擁有者讀,S_IROTH 表示該文件可以被其他人讀取。但真正的權(quán)限檢查,我們可以放到后面提到的inode_operations結(jié)構(gòu)中。
      size:即我們使用“l(fā)s”命令時,所顯示出的文件大小。
      proc_iops: 這是一個inode_operations結(jié)構(gòu),其中設(shè)置了針對這個proc索引節(jié)點的操作函數(shù),這樣,我們就可以針對不同類型的proc文件,提供不同 的方法,以完成不同的工作。比如我們上面提到的對proc文件的權(quán)限檢查,就可以放在這個結(jié)構(gòu)中。
      proc_fops:這是一個file_operations結(jié)構(gòu),其中放置了針對這個proc文件的操作函數(shù),我們可以把對proc文件的讀寫操作,放在這個結(jié)構(gòu)中,用以實現(xiàn)對/proc目錄中的文件的讀,寫功能。
      get_info:當(dāng)用戶向proc文件讀取的數(shù)據(jù)小于一個頁面大小時,可以使用這個函數(shù)向用戶返回數(shù)據(jù)。
      struct proc_dir_entry *next, *parent, *subdir:使用這些鏈表,在內(nèi)存中,proc_dir_entry結(jié)構(gòu)就以樹的形式鏈接在一起。
      read_proc_t *read_proc 和write_proc_t *write_proc:這兩個函數(shù)提供了對proc文件進(jìn)行操作的簡單接口。我們知道,對于proc文件,我們可以從中讀取核心數(shù)據(jù),還可以向其中寫入 數(shù)據(jù),因此,對于一些功能比較簡單的proc文件,我們只要實現(xiàn)這兩個函數(shù)(或其中之一)即可,而不用設(shè)置inode_operations結(jié)構(gòu),這樣, 整個操作比較簡單。實際上,我們會在后面的分析中看到,在注冊proc文件的時候,會自動為proc_fops設(shè)置一個缺省的 file_operations結(jié)構(gòu),如果我們只實現(xiàn)了上面提到的兩個讀寫操作,而沒有設(shè)置自己file_operations結(jié)構(gòu),那么,會由缺省的 inode_operations結(jié)構(gòu)中的讀寫函數(shù)檢查調(diào)用這兩個函數(shù)。
      atomic_t count:該結(jié)構(gòu)的使用計數(shù)。當(dāng)一個proc_dir_entry結(jié)構(gòu)的count減為零時,會釋放該結(jié)構(gòu),這種結(jié)果就像把一個ext2文件系統(tǒng)的文件從磁盤上刪除掉一樣。
      int deleted:這是一個刪除標(biāo)志,當(dāng)我們調(diào)用remove_proc_entry函數(shù)要刪除一個proc_dir_entry時,如果發(fā)現(xiàn)該結(jié)構(gòu)還在使用,就會設(shè)置該標(biāo)志并且推出。
      2 建立proc文件
      在了解了proc_dir_entry結(jié)構(gòu)之后,我們來看一看proc文件系統(tǒng)是如何管理自己的文件結(jié)構(gòu)的。
      首先我們看一看它是如何創(chuàng)建proc文件的,參考文件fs/proc/generic.c,其中,有一個函數(shù)create_proc_entry,由它創(chuàng)建并注冊proc文件,下面我們看一下它的源碼:
      struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode, struct proc_dir_entry *parent)
      {
      struct proc_dir_entry *ent = NULL;
      const char *fn = name;
      int len;

      if (!parent && xlate_proc_name(name, &parent, &fn) != 0)
      goto out;
      len = strlen(fn);

      ent = kmalloc(sizeof(struct proc_dir_entry) + len + 1, GFP_KERNEL);
      if (!ent)
      goto out;
      memset(ent, 0, sizeof(struct proc_dir_entry));
      memcpy(((char *) ent) + sizeof(*ent), fn, len + 1);
      ent->name = ((char *) ent) + sizeof(*ent);
      ent->namelen = len;

      if (S_ISDIR(mode)) {
      if ((mode & S_IALLUGO) == 0)
      mode |= S_IRUGO | S_IXUGO;
      ent->proc_fops = &proc_dir_operations;
      ent->proc_iops = &proc_dir_inode_operations;
      ent->nlink = 2;
      } else {
      if ((mode & S_IFMT) == 0)
      mode |= S_IFREG;
      if ((mode & S_IALLUGO) == 0)
      mode |= S_IRUGO;
      ent->nlink = 1;
      }
      ent->mode = mode;

      proc_register(parent, ent); /* link ent to parent */

      out:
      return ent;
      }
      我 們看到,首先,該函數(shù)會做一些必要的檢查,比如要確保它的父節(jié)點必須存在等等。其次會創(chuàng)建一個proc_dir_entry結(jié)構(gòu),并且為該文件的名字也分 配空間,并用->name指向它。再次,會根據(jù)該文件的類型,設(shè)置適當(dāng)?shù)哪J胶玩溄訑?shù)。最后,會調(diào)用proc_register(parent, ent)函數(shù),將這個結(jié)構(gòu)鏈接到proc文件樹中。
      下面我們看一下它的實現(xiàn)代碼:
      static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp)
      {
      int i;
      i = make_inode_number();
      if (i < 0)
      return -EAGAIN;
      dp->low_ino = i;
      dp->next = dir->subdir;
      dp->parent = dir;
      dir->subdir = dp;
      if (S_ISDIR(dp->mode)) {
      if (dp->proc_iops == NULL) {
      dp->proc_fops = &proc_dir_operations;
      dp->proc_iops = &proc_dir_inode_operations;
      }
      dir->nlink++;
      } else if (S_ISLNK(dp->mode)) {
      if (dp->proc_iops == NULL)
      dp->proc_iops = &proc_link_inode_operations;
      } else if (S_ISREG(dp->mode)) {
      if (dp->proc_fops == NULL)
      dp->proc_fops = &proc_file_operations;
      }
      return 0;
      }
      這 個函數(shù)主要完成三部分的工作,第一,使用make_inode_number()函數(shù)動態(tài)的到一個節(jié)點號,并且設(shè)置low_ino。第二步,將這個 proc_dir_entry結(jié)構(gòu)鏈接到它的父節(jié)點上。第三步,根據(jù)文件類型的不同,設(shè)置不同的(索引節(jié)點和文件)缺省操作函數(shù)集。
      這樣,一個proc文件就注冊成功了。
      3 刪除proc文件
      在同一源文件中,提供了刪除proc_dir_entry結(jié)構(gòu)的函數(shù),即remove_proc_entry,下面我們分析一下它的實現(xiàn)過程。
      void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
      {
      struct proc_dir_entry **p;
      struct proc_dir_entry *de;
      const char *fn = name;
      int len;

      if (!parent && xlate_proc_name(name, &parent, &fn) != 0)
      goto out;
      len = strlen(fn);
      for (p = &parent->subdir; *p; p=&(*p)->next ) {
      if (!proc_match(len, fn, *p))
      continue;
      de = *p;
      *p = de->next;
      de->next = NULL;
      if (S_ISDIR(de->mode))
      parent->nlink--;
      clear_bit(de->low_ino-PROC_DYNAMIC_FIRST,
      (void *) proc_alloc_map);
      proc_kill_inodes(de);
      de->nlink = 0;
      if (!atomic_read(&de->count))
      free_proc_entry(de);
      else {
      de->deleted = 1;
      printk("remove_proc_entry: %s/%s busy, count=%d\n",
      parent->name, de->name, atomic_read(&de->count));
      }
      break;
      }
      out:
      return;
      }
      該函數(shù)在參數(shù)parent的所有孩子中查找指定的名字,如果找到匹配的節(jié)點,即proc_match(len, fn, *p),那么,就將該結(jié)構(gòu)從樹結(jié)構(gòu)中去掉。然后,如果刪除的proc_dir_entry是目錄結(jié)構(gòu),那么,就減少其父節(jié)點的鏈接數(shù)。
      然后,調(diào)用clear_bit(de->low_ino-PROC_DYNAMIC_FIRST, (void *) proc_alloc_map)函數(shù),清除該節(jié)點號。
      最后,將該結(jié)構(gòu)的鏈接數(shù)置零,并調(diào)用atomic_read(&de->count)來檢查它的引用計數(shù),如果是零,那么就使用函數(shù)free_proc_entry釋放該節(jié)點,否則,就將它的刪除標(biāo)記位置一,在以后適當(dāng)?shù)貦C(jī)會中,再將其釋放。
      4 其他管理函數(shù)
      除此之外,我們看到還有一些函數(shù),可以方便我們管理和使用proc文件系統(tǒng),我們簡單地介紹一下:
      struct proc_dir_entry *proc_mkdir(const char *name, struct proc_dir_entry *parent)函數(shù),這個函數(shù)用來在proc文件系統(tǒng)中注冊一個子目錄,根據(jù)它的參數(shù),我們就可以看出它的功能。在這個函數(shù)里,將動態(tài)分配一個 proc_dir_entry結(jié)構(gòu)以及它的名字,然后,設(shè)置目錄文件的缺省操作(proc_iops以及proc_fops)以及nlink值,最后,調(diào) 用proc_register函數(shù)將其注冊。
      struct proc_dir_entry *proc_mknod(const char *name, mode_t mode, struct proc_dir_entry *parent, kdev_t rdev)函數(shù),用來在proc文件系統(tǒng)中建立一個設(shè)備文件,因此,在創(chuàng)建proc_dir_entry結(jié)構(gòu)后,沒有設(shè)置缺省操作,而是使用 ->rdev = rdev指定了設(shè)備。最后,調(diào)用proc_register函數(shù)將其注冊。
      struct proc_dir_entry *proc_symlink(const char *name, struct proc_dir_entry *parent, const char *dest)函數(shù),該函數(shù)創(chuàng)建了一個鏈接文件,使用->mode = S_IFLNK|S_IRUGO|S_IWUGO|S_IXUGO來標(biāo)志,它和其他文件的建立很相似,只是,它將鏈接的目標(biāo)文件名放在了 ->data域中。最后,它同樣調(diào)用proc_register函數(shù)將該結(jié)構(gòu)注冊。

        本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多