Chinaunix首页 | 论坛 | 博客
  • 博客访问: 96820
  • 博文数量: 29
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 10
  • 用 户 组: 普通用户
  • 注册时间: 2014-09-01 19:43
文章分类
文章存档

2017年(4)

2015年(24)

2014年(1)

我的朋友

分类: LINUX

2017-02-27 11:20:31

浅析linux内核__sysctl_head_next()函数内部实现

  对于__sysctl_head_next的使用感觉很巧妙,因为你会发现很多东西都是使用static定义的,
而却又都能够一一引用到static定义的他们,实现数据很好的隐藏的同时,又不乏可操作性,
linux系统中/proc/sys/目录下的所有内容,就是使用这项技术生成的.[luther.gliethttp]
luther@gliethttp:~$ ls /proc/sys/
debug dev fs kernel net vm

static struct ctl_table_root sysctl_table_root;
static struct ctl_table_header root_table_header = {
    .ctl_table = root_table,
    .ctl_entry = LIST_HEAD_INIT(sysctl_table_root.header_list), // ctl_entry为添加到root所在header_list链表上的指针[luther.gliethttp]
    .root = &sysctl_table_root, // 该header所归属的ctl_table_root,这里为sysctl_table_root
};
static struct ctl_table_root sysctl_table_root = { // sys控制table,该单元包含链接所有header的双向链表[luther.gliethttp]
    .root_list = LIST_HEAD_INIT(sysctl_table_root.root_list),
    .header_list = LIST_HEAD_INIT(root_table_header.ctl_entry),
// header_list链接着所有ctl_table_header类型内存中ctl_entry空间,它的初始值链接到root_table_header,
// 这样header_list将始终至少有1个有效值root_table_header.[luther.gliethttp]
};

struct ctl_table_header *__sysctl_head_next(struct nsproxy *namespaces,
                     struct ctl_table_header *prev)
{
    struct ctl_table_root *root;
    struct list_head *header_list;
    struct ctl_table_header *head;
    struct list_head *tmp;

    spin_lock(&sysctl_lock);
    if (prev) { // 是否接续前一个继续查找
        head = prev;
        tmp = &prev->ctl_entry;
        unuse_table(prev);
        goto next;
    }
    tmp = &root_table_header.ctl_entry; // 取出root_table内容[luther.gliethttp]
    for (;;) {
        head = list_entry(tmp, struct ctl_table_header, ctl_entry);

        if (!use_table(head)) // 该head是否仍然可用,如果可用那么返回该head,否则从该head所属root继续取下一个head.
            goto next;
        spin_unlock(&sysctl_lock);
        return head;
    next:
        root = head->root; // 该header所归属的ctl_table_root.[luther.gliethttp]
        tmp = tmp->next;
        header_list = lookup_header_list(root, namespaces);
        if (tmp != header_list)
// header_list为该root管理的链表头,如果tmp等于链表头,说明链表已经遍历完毕,否则continue[luther.gliethttp].
            continue;

        do {
            root = list_entry(root->root_list.next, // 从root->root_list链表中取出下一个root,该root也管理着它
            // 自己所要管理的header_list链表[luther.gliethttp].
            // 每一个创建的ctl_table_root都有一个它管理的相应的ctl_table_header,该ctl_table_header的.root指向
            // 该ctl_table_root
                    struct ctl_table_root, root_list);
            if (root == &sysctl_table_root) // root是否已经到了链表头sysctl_table_root了,如果到了,说明root已经空了[luther.gliethttp]
                goto out;
            header_list = lookup_header_list(root, namespaces); //取出该root管理的header_list.[luther.gliethttp]
        } while (list_empty(header_list));
// 如果该root管理的header_list不存在内容,那么回到上面继续从root->root_list链表中取出下一个root
        tmp = header_list->next; // 好了,该root的header_list管理内容非空.[luther.gliethttp]
    }
out:
    spin_unlock(&sysctl_lock);
    return NULL;
}

阅读(1833) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~