• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

systrace学习atrace打开各系统层tag开关的原理

武飞扬头像
aaajj
帮助1

atrace命令可以开启trace,让系统中埋下的trace标记开始记录,这是怎么实现的呢,

我们以系统层的trace为例来查看,

atrace的代码

frameworks/native/cmds/atrace/atrace.cpp

93/* Tracing categories */
94static const TracingCategory k_categories[] = {
95    { "gfx",        "Graphics",         ATRACE_TAG_GRAPHICS, {
96        { OPT,      "events/mdss/enable" },
97        { OPT,      "events/sde/enable" },
98    } },
99    { "input",      "Input",            ATRACE_TAG_INPUT, { } },
100    { "view",       "View System",      ATRACE_TAG_VIEW, { } },
101    { "webview",    "WebView",          ATRACE_TAG_WEBVIEW, { } },
102    { "wm",         "Window Manager",   ATRACE_TAG_WINDOW_MANAGER, { } },

里面通过设置属性的值,来传递信息,即哪些tag需要进行记录

606// Set the trace tags that userland tracing uses, and poke the running
607// processes to pick up the new value.
608static bool setTagsProperty(uint64_t tags)
609{
610    std::string value = android::base::StringPrintf("%#" PRIx64, tags);
611    if (!android::base::SetProperty(k_traceTagsProperty, value)) {
612        fprintf(stderr, "error setting trace tags system property\n");
613        return false;
614    }
615    return true;
616}
60const char* k_traceTagsProperty = "debug.atrace.tags.enableflags";

执行函数由于执行的次数很多,所以没有必要每次都读取属性 debug.atrace.tags.enableflags的值来判断当前tag是否需要打印,只需要读一次,保存下来即可。

但是进程怎么知道属性值变化了呢,这里调用每个系统服务的SYSPROPS_TRANSACTION方法,来推送,

531// Poke all the binder-enabled processes in the system to get them to re-read
532// their system properties.
533static bool pokeBinderServices()
534{
535    sp<IServiceManager> sm = defaultServiceManager();
536    Vector<String16> services = sm->listServices();
537    for (size_t i = 0; i < services.size(); i  ) {
538        sp<IBinder> obj = sm->checkService(services[i]);
539        if (obj != NULL) {
540            Parcel data;
541            if (obj->transact(IBinder::SYSPROPS_TRANSACTION, data,
542                    NULL, 0) != OK) {
543                if (false) {
544                    // XXX: For some reason this fails on tablets trying to
545                    // poke the "phone" service.  It's not clear whether some
546                    // are expected to fail.
547                    String8 svc(services[i]);
548                    fprintf(stderr, "error poking binder service %s\n",
549                        svc.string());
550                    return false;
551                }
552            }
553        }
554    }
555    return true;
556}
学新通

SYSPROPS_TRANSACTION 方法执行起来做什么?

status_t BBinder::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t /*flags*/)
{
    switch (code) {
        ...
        case SYSPROPS_TRANSACTION: {
            report_sysprop_change();
            return NO_ERROR;
        }
        ...
    }
}
 

report_sysprop_change()方法会调用属性变化的回调函数,

  1.  
    void report_sysprop_change() {
  2.  
    do_report_sysprop_change();
  3.  
     
  4.  
    #if defined(__ANDROID__)
  5.  
    // libutils.so is double loaded; from the default namespace and from the
  6.  
    // 'sphal' namespace. Redirect the sysprop change event to the other instance
  7.  
    // of libutils.so loaded in the 'sphal' namespace so that listeners attached
  8.  
    // to that instance is also notified with this event.
  9.  
    static auto func = get_report_sysprop_change_func();
  10.  
    if (func != nullptr) {
  11.  
    (*func)();
  12.  
    }
  13.  
    #endif
  14.  
    }

所以,服务进程中写了回调函数后,就可以更新属性的值了。

这里使用了binder来进行通知。

InputDispatcher里的trace调用

3868void InputDispatcher::traceInboundQueueLengthLocked() {
3869    if (ATRACE_ENABLED()) {
3870        ATRACE_INT("iq", mInboundQueue.count());
3871    }
3872}

ATRACE_ENABLED

156#define ATRACE_GET_ENABLED_TAGS() atrace_get_enabled_tags()
157static inline uint64_t atrace_get_enabled_tags()
158{
159    atrace_init();
160    return atrace_enabled_tags;
161}
162
163/**
164 * Test if a given tag is currently enabled.
165 * Returns nonzero if the tag is enabled, otherwise zero.
166 * It can be used as a guard condition around more expensive trace calculations.
167 */
168#define ATRACE_ENABLED() atrace_is_tag_enabled(ATRACE_TAG)
169static inline uint64_t atrace_is_tag_enabled(uint64_t tag)
170{
171    return atrace_get_enabled_tags() & tag;
172}
学新通

调用traceInit()可以设置属性变化的回调,会调用

22static void traceInit() {
23    ::android::add_sysprop_change_callback(atrace_update_tags, 0);
24}

这里有个很有意思的知识点,在代码中搜不到traceInit的调用,只看到定义,

20static void traceInit() __attribute__((constructor));
21
22static void traceInit() {
23    ::android::add_sysprop_change_callback(atrace_update_tags, 0);
24}

那到底是怎样设置的回调函数呢?

其实设置了  __attribute__((constructor))  这个高端写法,在main函数开始的地方,就会调用traceInit方法,我们可以搜一下  __attribute__((constructor))这个用法。也可以写个例子来验证这种调用,情况确实如此。

查看atrace_update_tags的定义,在里面读取属性"debug.atrace.tags.enableflags"的值,更新了atrace_enabled_tags的值,

98/**
99 * If tracing is ready, set atrace_enabled_tags to the system property
100 * debug.atrace.tags.enableflags. Can be used as a sysprop change callback.
101 */
102void atrace_update_tags();

在 system/core/libcutils/trace-dev.inc

里有其实现,获取了要监控的属性值

136// Update tags if tracing is ready. Useful as a sysprop change callback.
137void atrace_update_tags()
138{
139    uint64_t tags;
140    if (CC_UNLIKELY(atomic_load_explicit(&atrace_is_ready, memory_order_acquire))) {
141        if (atomic_load_explicit(&atrace_is_enabled, memory_order_acquire)) {
142            tags = atrace_get_property();
143            pthread_mutex_lock(&atrace_tags_mutex);
144            atrace_enabled_tags = tags;
145            pthread_mutex_unlock(&atrace_tags_mutex);
146        } else {
147            // Tracing is disabled for this process, so we simply don't
148            // initialize the tags.
149            pthread_mutex_lock(&atrace_tags_mutex);
150            atrace_enabled_tags = ATRACE_TAG_NOT_READY;
151            pthread_mutex_unlock(&atrace_tags_mutex);
152        }
153    }
154}
学新通

总结:

细节很多,这里回顾一下大体过程,atrace里设置tag,标识哪些tag可以进行写trace,然后写到属性值debug.atrace.tags.enableflags里,atrace又进行了binder调用所有系统服务的SYSPROPS_TRANSACTION对应的方法,告诉它们,属性值变化了,可以调用属性变化回调函数了。

系统服务进程就调用预定的回调函数,读取debug.atrace.tags.enableflags的值,保存起来,以后就可以用这个值来和tag进行比较,判断当前的tag是否需要写trace,避免每次都属性值,那个读取代价太大。

普通应用中的trace原理类似,也是设置了属性值。

相关知识点:属性值的变化可以设置回调函数。

binder中竟然有个冷门方法SYSPROPS_TRANSACTION,通知属性值的变化。

参考资料:

[Android systrace系列] systrace的信息从哪里来 - zzc1024 - 博客园

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgfagge
系列文章
更多 icon
同类精品
更多 icon
继续加载