欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 国际 > Android Binder调用的优先级

Android Binder调用的优先级

2025/3/29 21:25:38 来源:https://blog.csdn.net/LiuYong_01/article/details/146511405  浏览:    关键词:Android Binder调用的优先级

在SF调用hwc的binder_f1函数中hwc调用SF的binder_f2,会导致线程的优先级从97降级为120。

sf sync binder to HWC    SF优先级是97,call到HWC,HWC的优先级是97
HWC sync binder to sf    这里binder嵌套,HWC call到SF,SF的优先级被改为120了,从trace上看HWC的优先级全程是97
sf reply hwc
hwc reply sf

 

inder调用的优先级继承

Binder默认支持client端调用server端的时候,将Client端的线程优先级传递给server端。

在Android系统中,Binder是进程间通信(IPC)的核心机制。Binder调用涉及优先级继承(Priority Inheritance),这是一种解决优先级反转问题的机制。优先级反转是指高优先级任务因为等待低优先级任务持有的资源而被阻塞,而低优先级任务又因为中等优先级任务的抢占而无法释放资源,从而导致高优先级任务长时间无法执行。

Android的Binder机制通过优先级继承来解决这个问题:当高优先级任务等待低优先级任务持有的Binder资源时,低优先级任务会临时继承高优先级任务的优先级,从而尽快完成资源释放,避免高优先级任务被长时间阻塞。

然而,在某些情况下,可能需要降低或调整Binder调用的优先级继承行为,例如为了避免过渡提升低优先级任务的优先级,或者为了优化系统性能。

理解Binder优先级继承机制

Binder线程优先级:每个Binder线程都有一个优先级,通常由进程的优先级和线程的调度策略决定。

优先级继承:当高优先级任务等待低优先级任务持有的Binder资源时,低优先级任务会临时继承高优先级任务的优先级。

恢复优先级:当低优先级任务释放资源后,其优先级会恢复到原来的值。

降低Binder优先级继承的方法

方法1:调整Binder线程的优先级

  • 通过修改Binder线程的优先级,可以间接影响优先级继承的行为。

  • 使用setpriority() 或 sched_setscheduler() 系统调用调整线程的优先级。

代码示例:

#include <sys/resource.h>
#include <unistd.h>
#include <sched.h>// 设置线程的优先级
int set_thread_priority(int tid, int priority) {struct sched_param param;param.sched_priority = priority;return sched_setscheduler(tid, SCHED_FIFO, &param);
}

方法2:修改Binder驱动的优先级继承策略

  • Binder驱动的优先级继承行为可以通过修改内核代码来调整。

  • 在Binder驱动源码中,优先级继承的逻辑通常位于binder.c文件中,具体函数为binder_transaction() 和 binder_set_priority()。

  • 可以通过修改以下逻辑来降低优先级继承的影响:

    • 减少优先级继承的提升幅度。

    • 限制优先级继承的持续时间。

方法3:禁用或限制优先级继承

  • 在某些情况下,可以完成禁用优先级继承,但是可能会导致优先级反转问题。

  • 在Binder驱动中,可以通过修改代码来禁用优先级继承逻辑。

修改示例:

// 在 binder_transaction() 中注释掉优先级继承的逻辑
// if (target_thread->priority < current->priority) {
//     binder_set_priority(target_thread, current->priority);
// }

方法4:使用Android系统属性

  • Android提供了一些系统属性,可以调整Binder的行为。

  • 例如,可以通过修改debug.binder.priority属性来调整Binder线程的默认优先级。

命令示例:

adb shell setprop debug.binder.priority <value>

注意事项

  • 优先级反转风险:降低或禁用优先级继承可能会导致优先级反转问题,从而影响系统的实时性和响应性。

  • 系统稳定性:修改 Binder 驱动的行为可能会影响系统的稳定性,尤其是在多任务和高负载场景下。

  • 测试和验证:在修改优先级继承逻辑后,必须进行充分的测试,确保系统性能和稳定性不受影响。

示例场景

  • 场景 1:在实时性要求不高的系统中,降低 Binder 优先级继承以减少对低优先级任务的干扰。

  • 场景 2:在性能测试中,禁用优先级继承以观察系统的行为。

线程优先级降级原因分析

首先查看binder驱动中的定义binder_priority接口体。

/*** struct binder_priority - scheduler policy and priority* @sched_policy            scheduler policy* @prio                    [100..139] for SCHED_NORMAL, [0..99] for FIFO/RT** The binder driver supports inheriting the following scheduler policies:* SCHED_NORMAL* SCHED_BATCH* SCHED_FIFO* SCHED_RR*/
struct binder_priority {unsigned int sched_policy;int prio;
};

[100..139] for SCHED_NORMAL, [0..99] for FIFO/RT这段注释可得出,binder驱动中奖sched_prlicy改成了SCHED_NORMAL

在binder驱动中搜索SCHED_NORMAL,可以找到几处用到=SCHED_NORMAL代码。

初始化,设置进程的default_priority

static int binder_open(struct inode *nodp, struct file *filp)
{
...if (binder_supported_policy(current->policy)) {proc->default_priority.sched_policy = current->policy;proc->default_priority.prio = current->normal_prio;} else {proc->default_priority.sched_policy = SCHED_NORMAL;proc->default_priority.prio = NICE_TO_PRIO(0);}
...
}

MIN_NICE是-20,对应优先级应该是100

static void binder_do_set_priority(struct binder_thread *thread,const struct binder_priority *desired,bool verify)
{
...if (verify && is_rt_policy(policy) && !has_cap_nice) {long max_rtprio = task_rlimit(task, RLIMIT_RTPRIO);if (max_rtprio == 0) {policy = SCHED_NORMAL;priority = MIN_NICE;//-20} else if (priority > max_rtprio) {priority = max_rtprio;}}
...
}

NICE_TO_PRIO(0)120

static void binder_transaction_priority(struct binder_thread *thread,struct binder_transaction *t,struct binder_node *node)
{
...if (!node->inherit_rt && is_rt_policy(desired.sched_policy)) {desired.prio = NICE_TO_PRIO(0);desired.sched_policy = SCHED_NORMAL;}
...
}

总结

HWC作为97的优先级调用SF的时候,会调用binder_transaction_priority这个函数,由于调用SFbinder nodeinherit_rtfalse,并且desired.sched_policy也就是HWCsched_policyis_rt_policy,因为97就是FIFO/RT,这里具体是哪个policy就不重要了。最后就将desired.prio设置成了120。

static bool is_rt_policy(int policy)
{return policy == SCHED_FIFO || policy == SCHED_RR;
}

为什么SF的binder node的inherit_rt为false

因为默认aidlbinder对象inherit_rt就是false

frameworks/native/libs/binder/Parcel.cpp
status_t Parcel::flattenBinder(const sp<IBinder>& binder) {if (binder != nullptr) {if (!local) {...} else {int policy = local->getMinSchedulerPolicy();int priority = local->getMinSchedulerPriority();if (policy != 0 || priority != 0) {// override value, since it is set explicitlyschedBits = schedPolicyMask(policy, priority);}obj.flags = FLAT_BINDER_FLAG_ACCEPTS_FDS;if (local->isRequestingSid()) {obj.flags |= FLAT_BINDER_FLAG_TXN_SECURITY_CTX;}if (local->isInheritRt()) {//调用BBinder的isInheritRtobj.flags |= FLAT_BINDER_FLAG_INHERIT_RT;}obj.hdr.type = BINDER_TYPE_BINDER;obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs());obj.cookie = reinterpret_cast<uintptr_t>(local);}} else {...}
}bool BBinder::isInheritRt() {Extras* e = mExtras.load(std::memory_order_acquire);return e && e->mInheritRt;
}

除非主动调用setInheritRT这个接口。


void BBinder::setInheritRt(bool inheritRt) {LOG_ALWAYS_FATAL_IF(mParceled,"setInheritRt() should not be called after a binder object ""is parceled/sent to another process");Extras* e = mExtras.load(std::memory_order_acquire);if (!e) {if (!inheritRt) {return;}e = getOrCreateExtras();if (!e) return; // out of memory}e->mInheritRt = inheritRt;
}

规范的用法

BnCameraDeviceCallbackaidl文件自动生成的,但是要注意,需要在传递给Binder驱动之前,对应的Binder对象就需要设置完成。

::ndk::SpAIBinder AidlCamera3Device::AidlCameraDeviceCallbacks::createBinder() {auto binder = BnCameraDeviceCallback::createBinder();AIBinder_setInheritRt(binder.get(), /*inheritRt*/ true);//调用下面这个函数。return binder;
}void AIBinder_setInheritRt(AIBinder* binder, bool inheritRt) {ABBinder* localBinder = binder->asABBinder();if (localBinder == nullptr) {LOG(FATAL) << "AIBinder_setInheritRt must be called on a local binder";}localBinder->setInheritRt(inheritRt);
}

HWBinder的inherit_rt默认为true

HWBinder有一些特殊,就是默认加了FLAT_BINDER_FLAG_INHERIT_RT,所以HWBinder默认是可以继承RT的调度策略的。

system/libhwbinder/Parcel.cpp
status_t flatten_binder(const sp<ProcessState>& /*proc*/,const sp<IBinder>& binder, Parcel* out)
{if (binder != nullptr) {BHwBinder *local = binder->localBinder();if (!local) {} else {// Get policy and convert itint policy = local->getMinSchedulingPolicy();int priority = local->getMinSchedulingPriority();obj.flags = priority & FLAT_BINDER_FLAG_PRIORITY_MASK;obj.flags |= FLAT_BINDER_FLAG_ACCEPTS_FDS | FLAT_BINDER_FLAG_INHERIT_RT;//默认就加了obj.flags |= (policy & 3) << FLAT_BINDER_FLAG_SCHED_POLICY_SHIFT;if (local->isRequestingSid()) {obj.flags |= FLAT_BINDER_FLAG_TXN_SECURITY_CTX;}obj.hdr.type = BINDER_TYPE_BINDER;obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs());obj.cookie = reinterpret_cast<uintptr_t>(local);}} else {}return finish_flatten_binder(binder, obj, out);
}

HWC初始化Binder服务的时候,主动调用了AIBinder_setInheritRt

device/generic/goldfish-opengl/system/hwc3/Composer.cpp
::ndk::SpAIBinder Composer::createBinder() {DEBUG_LOG("%s", __FUNCTION__);auto binder = BnComposer::createBinder();AIBinder_setInheritRt(binder.get(), true);return binder;
}

注意:因为HWC改成了aidl,也就意味着图中binder_f1的调用和binder_f2的响应是同一个SF线程。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词