美文网首页
浅尝辄止70-内核那些“非显式定义”宏

浅尝辄止70-内核那些“非显式定义”宏

作者: 阿棍儿_Leon | 来源:发表于2019-01-07 13:03 被阅读0次

如果你顺着上一篇的线索去读mark_buffer_dirty的实现会很困惑,因为很多“函数”的定义找不到。

非显式定义宏

有些函数、变量或类型的名字不是直接写出来的,而是用宏的##符号定义出来的,这意味着这些名字在定义的地方可以不出现,如果你不知道的话,就很难找到他们的定义。
mark_buffer_dirty[kernel/fs/buffer.c]这个函数看起来不长,但是里面有好几个东西找不到的定义,包括buffer_uptodatebuffer_dirtytest_set_buffer_dirtyTestSetPageDirty

void mark_buffer_dirty(struct buffer_head *bh)
{
    WARN_ON_ONCE(!buffer_uptodate(bh));

    trace_block_dirty_buffer(bh);

    /*
     * Very *carefully* optimize the it-is-already-dirty case.
     *
     * Don't let the final "is it dirty" escape to before we
     * perhaps modified the buffer.
     */
    if (buffer_dirty(bh)) {
        smp_mb();
        if (buffer_dirty(bh))
            return;
    }

    if (!test_set_buffer_dirty(bh)) {
        struct page *page = bh->b_page;
        if (!TestSetPageDirty(page)) {
            struct address_space *mapping = page_mapping(page);
            if (mapping)
                __set_page_dirty(page, mapping, 0);
        }
    }
}

buffer_uptodate

事实上名字叫做buffer_uptodate的函数是存在的,它在kernel/include/linux/buffer_head.h里面

#define BUFFER_FNS(bit, name)                       \
static inline void set_buffer_##name(struct buffer_head *bh)        \
{                                   \
    set_bit(BH_##bit, &(bh)->b_state);              \
}                                   \
static inline void clear_buffer_##name(struct buffer_head *bh)      \
{                                   \
    clear_bit(BH_##bit, &(bh)->b_state);                \
}                                   \
static inline int buffer_##name(const struct buffer_head *bh)       \
{                                   \
    return test_bit(BH_##bit, &(bh)->b_state);          \
}
//...
BUFFER_FNS(Uptodate, uptodate)

将宏展开就是

static inline void set_buffer_uptodate(struct buffer_head *bh)
{
    set_bit(BH_Uptodate, &(bh)->b_state);
}
static inline void clear_buffer_uptodate(struct buffer_head *bh)
{
    clear_bit(BH_Uptodate, &(bh)->b_state);
}
static inline int buffer_uptodate(const struct buffer_head *bh)
{
    return test_bit(BH_Uptodate, &(bh)->b_state);
}

buffer_dirty

同上,将BUFFER_FNS(Dirty, dirty)展开

static inline void set_buffer_dirty(struct buffer_head *bh)
{
    set_bit(BH_Dirty, &(bh)->b_state);
}
static inline void clear_buffer_dirty(struct buffer_head *bh)
{
    clear_bit(BH_Dirty, &(bh)->b_state);
}
static inline int buffer_dirty(const struct buffer_head *bh)
{
    return test_bit(BH_Dirty, &(bh)->b_state);
}

test_set_buffer_dirty

也是一样的

#define TAS_BUFFER_FNS(bit, name)                   \
static inline int test_set_buffer_##name(struct buffer_head *bh)    \
{                                   \
    return test_and_set_bit(BH_##bit, &(bh)->b_state);      \
}                                   \
static inline int test_clear_buffer_##name(struct buffer_head *bh)  \
{                                   \
    return test_and_clear_bit(BH_##bit, &(bh)->b_state);        \
}
//...
TAS_BUFFER_FNS(Dirty, dirty)

展开TAS_BUFFER_FNS(Dirty, dirty)

static inline int test_set_buffer_dirty(struct buffer_head *bh)
{
    return test_and_set_bit(BH_Dirty, &(bh)->b_state);
}
static inline int test_clear_buffer_dirty(struct buffer_head *bh)
{
    return test_and_clear_bit(BH_Dirty, &(bh)->b_state);
}

TestSetPageDirty

它的定义可以从kernel/include/linux/page-flags.h找到,线索如下

#define TESTSETFLAG(uname, lname)                   \
static inline int TestSetPage##uname(struct page *page)         \
        { return test_and_set_bit(PG_##lname, &page->flags); }
//...
TESTSETFLAG(Dirty, dirty)

都是一个套路,我就不展开了。

遇到这种情况,如果猜它是非显式定义的宏,还是有一点办法的,例如可以把名字拆开,然后搜索那个名字。例如TestSetPageDirty的形式是TestSetPagexxxx,前面的TestSetPage部分看起来是不变的,所以搜它就可以找到上面这个线索。

相关文章

  • 浅尝辄止70-内核那些“非显式定义”宏

    如果你顺着上一篇的线索去读mark_buffer_dirty的实现会很困惑,因为很多“函数”的定义找不到。 非显式...

  • 显式动画Animation<转>

    当需要对非Root Layer进行动画或者需要对动画做更多自定义的行为的时候,就必须使用到显式动画了,显式动画的基...

  • linux 驱动开发 - 内核模块

    一、Linux内核简介 1.宏内核与微内核 内核分为四大类:单内核(宏内核);微内核;混合内核;外内核。 宏内核(...

  • 操作系统100问

    1.什么是微内核?万栩童\李明霞 内容:微内核定义?微内核包括哪些功能?相对于宏内核,操作系统采用微内核由什么好处...

  • 懒加载

    宏式懒加载 定义一个懒加载的宏 使用

  • iptables系列二

    iptables系列之基本应用及显式扩展 netfilter:Framework,TCP,内核中 iptables...

  • java中父子类静态代码块、非静态代码块、构造方法等的执行顺序

    输出结果: 解释 非静态实例变量显式赋值代码和非静态代码块代码按代码顺序从上往下执行 类变量显式赋值代码和静态代码...

  • 安卓中的intent

    intent分为显式intent和隐式intent 创建显式intent时需要指明被启动的类的定义,明确说明了要启...

  • Vue之prop

    这里暂时仅介绍下“非prop特性(attr)”一般的特性是显式定义的(即 prop特性),如下面代码中的 post...

  • selenium的webdriver三种等待方式对比

    1、显式等待 一个显式等待是你定义的一段代码,用于等待某个条件发生然后再继续执行后续代码。显式等待是等元素加载! ...

网友评论

      本文标题:浅尝辄止70-内核那些“非显式定义”宏

      本文链接:https://www.haomeiwen.com/subject/wjqurqtx.html