/procのls一覧表示について


Rev.1を表示中。最新版はこちら

プロック擬似ファイルは実ファイルを持たないファイルシステムであり、このファイルを介してシス

テム情報およびプロセス情報をを設定確認できる機能を提供している。
[root@localhost proc]# ls -f
.              mtrr           vmstat        loadavg  151  542
..             irq            pagetypeinfo  self     155  543
crypto         cgroups        buddyinfo     1        156  592
key-users      sys            vmallocinfo   2        157  914
keys           bus            slabinfo      3        159  1276
swaps          tty            interrupts    4        164  1277
latency_stats  driver         stat          5        167  1278
kallsyms       fs             partitions    6        217  1301
dma            sysvipc        cpuinfo       7        218  1384
timer_stats    net            devices       8        219  1393
timer_list     sysrq-trigger  locks         9        267  1404
iomem          vmcore         kmsg          10       268  1405
ioports        kpageflags     mounts        11       456  1483
sched_debug    kpagecount     execdomains   85       459  1521
mdstat         kcore          cmdline       86       494  1523
scsi           schedstat      filesystems   88       501  2112
misc           modules        version       89       504
acpi           diskstats      meminfo       91       537
fb             zoneinfo       uptime        92       541

本ファイルシステムは、proc_root_initでprocファイルシステム登録、マウント処理が行われ、マウ

ント処理後、struct proc_dir_entry proc_rootをrootエントリーとして、proc_misc_init等でシス

テムに関するものはprocファイルシステム以下に静的にディレクトリが作成され、プロセスに関する

ものは動的に作成されるようになっている。

lsで/proc下のファイルを表示した場合、file_opretaionのproc_root_inode_operationsの.readdir

のコールバック関数により/proc下のファイル一覧情報が取得される。このfile_opretaionはマウン

ト時にスーパブロック取得において、rootのinodeに設定されるのinodeオペレーションにproc_root

の.proc_fopsをinode->i_fopに設定することで実現している。

struct proc_dir_entry proc_root = {
       .low_ino        = PROC_ROOT_INO, 
       .namelen        = 5, 
       .name           = "/proc",
       .mode           = S_IFDIR | S_IRUGO | S_IXUGO, 
       .nlink          = 2, 
       .count          = ATOMIC_INIT(1),
       .proc_iops      = &proc_root_inode_operations, 
       .proc_fops      = &proc_root_operations,
       .parent         = &proc_root,
};
static const struct file_operations proc_root_operations = {
       .read            = generic_read_dir,
       .readdir         = proc_root_readdir,
};

mount時に呼ばれてスーパブロックを取得する。この時rootのinodeにproc_rootの時に.proc_iopsお

よび.proc_fopsが設定される。
int proc_fill_super(struct super_block *s)
{
・・・・・
       struct inode * root_inode;

       s->s_flags |= MS_NODIRATIME | MS_NOSUID | MS_NOEXEC;
       s->s_blocksize = 1024;
       s->s_blocksize_bits = 10;
       s->s_magic = PROC_SUPER_MAGIC;
       s->s_op = &proc_sops;
       s->s_time_gran = 1;
       
       de_get(&proc_root);
       root_inode = proc_get_inode(s, PROC_ROOT_INO, &proc_root);
       if (!root_inode)
               goto out_no_root;
       root_inode->i_uid = 0;
       root_inode->i_gid = 0;
       s->s_root = d_alloc_root(root_inode);
・・・・・


struct inode *proc_get_inode(struct super_block *sb, unsigned int ino,
                               struct proc_dir_entry *de)
{
・・・・・
               if (de->proc_iops)
ルートのIノードオペレーションにproc_root_inode_operationsを設定 
                       inode->i_op = de->proc_iops;
               if (de->proc_fops) {
・・・・・
ルートのIノードファイルオペレーションにproc_root_operationsを設定 
                       inode->i_fop = de->proc_fops;
・・・・・
               
これでlsで/proc一覧表示させると、rootのinodeオペレーションとしてproc_root_operations

の.readdir = proc_root_readdirが呼ばれることになる。最初にproc_readdirで/proc下の静的に作

成されているディレクトリーが表示させ、proc_pid_readdirで動的にプロセスIDを表示させる。

static int proc_root_readdir(struct file * filp,
        void * dirent, filldir_t filldir)
{
・・・・・
       if (nr < FIRST_PROCESS_ENTRY) {
プロセスIDでないものを表示
               int error = proc_readdir(filp, dirent, filldir);
               if (error <= 0) {
                       unlock_kernel();
                       return error;
               }
               filp->f_pos = FIRST_PROCESS_ENTRY;
       }
selfおよびプロセスIDを表示
       ret = proc_pid_readdir(filp, dirent, filldir);
       return ret;
}

proc_readdirはproc_readdir_deを呼び出して、"."、".."および静的に作成した/procファイル以下

のディレクトリー一覧が表示し、proc_pid_readdirでselfディレクトリーを表示して後、next_tgid

でプロセスIDを1から順に、その時のスレッドグループIDを取得し、そのプロセスIDを表示するよう

になっている。next_tgidでPIDTYPE_PIDにつながれたプロセスIDから、グループリーダのプロセス

IDを返す。それをプロセスIDを1から順に調べることで、システムの全グループリーダのプロセ

スIDを表示している。このことから一覧で表示されるプロセスIDは表示だけのもので、この段階

ではその実態(inode等)は有していない。

int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir)
{
・・・・・
     ns = filp->f_dentry->d_sb->s_fs_info;
       iter.task = NULL;
       iter.tgid = filp->f_pos - TGID_OFFSET;
       for (iter = next_tgid(ns, iter);
            iter.task;
            iter.tgid += 1, iter = next_tgid(ns, iter)) {
               filp->f_pos = iter.tgid + TGID_OFFSET;
               if (proc_pid_fill_cache(filp, dirent, filldir, iter) < 0) {
                       put_task_struct(iter.task);
                       goto out;
               }
       }
       filp->f_pos = PID_MAX_LIMIT + TGID_OFFSET;
・・・・・
}

static struct tgid_iter next_tgid(struct pid_namespace *ns, struct tgid_iter iter)
{
・・・・・

       iter.task = NULL;
       pid = find_ge_pid(iter.tgid, ns);
       if (pid) {
               iter.tgid = pid_nr_ns(pid, ns);
               iter.task = pid_task(pid, PIDTYPE_PID);
              if (!iter.task || !has_group_leader_pid(iter.task)) {
                       iter.tgid += 1;
                       goto retry;
               }
               get_task_struct(iter.task);
       }
       rcu_read_unlock();
       return iter;
}

補足
プロセスID以外はファイルシステム作成時、proc_misc_initがコールされ、proc_createでディレ

クトリ名と処理するコールバックを個々に設定することで作成している。
void __init proc_misc_init(void)
{
       static struct {
               char *name;
               int (*read_proc)(char*,char**,off_t,int,int*,void*);
       } *p, simple_ones[] = {
               {"loadavg",     loadavg_read_proc},
               {"uptime",      uptime_read_proc},
               {"meminfo",     meminfo_read_proc},
               {"version",     version_read_proc},
・・・・・
               {"filesystems", filesystems_read_proc},
               {"cmdline",     cmdline_read_proc},
               {"execdomains", execdomains_read_proc},
               {NULL,}
       };
       for (p = simple_ones; p->name; p++)
               create_proc_read_entry(p->name, 0, NULL, p->read_proc, NULL);

       proc_symlink("mounts", NULL, "self/mounts");

・・・・・
       proc_create("stat", 0, NULL, &proc_stat_operations);
       proc_create("interrupts", 0, NULL, &proc_interrupts_operations);
       proc_create("buddyinfo", S_IRUGO, NULL, &fragmentation_file_operations);
       proc_create("pagetypeinfo", S_IRUGO, NULL, &pagetypeinfo_file_ops);
       proc_create("vmstat", S_IRUGO, NULL, &proc_vmstat_file_operations);
       proc_create("zoneinfo", S_IRUGO, NULL, &proc_zoneinfo_file_operations);
・・・・・
}



最終更新 2010/02/28 21:58:23 - north
(2010/02/28 21:58:23 作成)


検索

アクセス数
3575105
最近のコメント
コアダンプファイル - sakaia
list_head構造体 - yocto_no_yomikata
勧告ロックと強制ロック - wataash
LKMからのファイル出力 - 重松 宏昌
kprobe - ななし
ksetの実装 - スーパーコピー
カーネルスレッドとは - ノース
カーネルスレッドとは - nbyst
asmlinkageってなに? - ノース
asmlinkageってなに? - よろしく
Adsense
広告情報が設定されていません。