05.Binder系统:第6课第9节_Binder系统_server的多线程实现

在binder系统中,由一个server进程提供服务,有一个或者多个client向他发送服务请求,并且是有可能同时发生请求的,假若client进程非常的多,server进程忙不过来怎么办呢?

忙不过来时,创建多线程,由这些线程处理这些服务。那么怎么才能判断他忙不过来?通过前面的小节我们知道,对于每一个进程都存在一个binder_proc,binder_proc中有一个todo链表,当client发送请求的时候,会把数据放入到todo链表,并且唤醒等待在todo这个链表上的线程,如果有线程在wait这里等待,则代表忙得过来,如果没有一个线程在等待,就代表已经忙不过来了,下图四个简要框图:
在这里插入图片描述

这个时候,驱动程序就会向server进程发出相应,告诉server进程需要创建更多的线程。
1.是在驱动程序中判断,是否忙得过来。
2.驱动程序向APP发出请求,创建新线程。
3.APP创建新线程

围绕着上面3点我们去查看源代码(SDK/kernel/driver/android/binder.c),找到其中的binder_thread_read函数,在该函数的最末尾部分,可以看到如下代码:


binder_inner_proc_lock(proc);
	

	/*当proc->requested_threads == 0:未处理的新线程请求,list_empty(&thread->proc->waiting_threads):等待的线程为0时,
	proc->requested_threads_started < proc->max_threads:已经启动的线程数,小于设定的最大值*/
	if (proc->requested_threads == 0 &&
	    list_empty(&thread->proc->waiting_threads) &&
	    proc->requested_threads_started < proc->max_threads &&
	    (thread->looper & (BINDER_LOOPER_STATE_REGISTERED |
	     BINDER_LOOPER_STATE_ENTERED)) /* the user-space code fails to */
	     /*spawn a new thread if we leave this out */) {
	     /*线程数目+1,当新线程运行完成的时候-1*/
		proc->requested_threads++;
		binder_inner_proc_unlock(proc);
		binder_debug(BINDER_DEBUG_THREADS,
			     "%d:%d BR_SPAWN_LOOPER\n",
			     proc->pid, thread->pid);
		/*发送一个创建线程的请求给应用程序*/
		if (put_user(BR_SPAWN_LOOPER, (uint32_t __user *)buffer))
			return -EFAULT;
		binder_stat_br(proc, thread, BR_SPAWN_LOOPER);
	} else
		binder_inner_proc_unlock(proc);

其作用就是判断是否发送创建新线程的请求。驱动程序向APP发出"创建新线程请求"的条件:
1.proc->requested_threads == 0(未处理的新线程请求)
2.list_empty(&thread->proc->waiting_threads):等待的线程为0
3.proc->requested_threads_started < proc->max_threads:已经启动的线程数,小于设定最大值数max_threads

在发送请求之后,会执行proc->requested_threads++,当应用程序调用新线程,进行写操作时,会执行proc->requested_threads–。如下:

static int binder_thread_write(struct binder_proc *proc,struct binder_thread *thread,binder_uintptr_t binder_buffer, size_t size,binder_size_t *consumed)
	case BC_REGISTER_LOOPER:
		/*未处理的线程数*/
		proc->requested_threads--;
		/*启动的线程数目+1*/
		proc->requested_threads_started++;
		

表示新的线程已经进入了循环体。

那么我们怎么去写应用程序呢?
1.设置max_threads,如果未设定,默认值为0
2.收到BR_SPAWN_LOOPER时,创建新线程。
3.新线程要执行一个ioctl,发送BC_REGISTER_LOOPER给驱动程序,告诉其已经进入循环体了
4.像主线程一样进入一个循环体:read-driver,处理。

  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
com.miui.frameworks.servicestests (1 Test) [1/1] com.android.server.location.gnss.hal.Gpo4ClientTest#init: FAILED (141ms) STACKTRACE: java.lang.SecurityException: uid 10289 does not have android.permission.ACCESS_COARSE_LOCATION or android.permission.ACCESS_FINE_LOCATION. at android.os.Parcel.createExceptionOrNull(Parcel.java:3011) at android.os.Parcel.createException(Parcel.java:2995) at android.os.Parcel.readException(Parcel.java:2978) at android.os.Parcel.readException(Parcel.java:2920) at android.location.ILocationManager$Stub$Proxy.registerLocationListener(ILocationManager.java:1291) at android.location.LocationManager.requestLocationUpdates(LocationManager.java:1551) at android.location.LocationManager.requestLocationUpdates(LocationManager.java:1234) at android.location.LocationManager.requestLocationUpdates(LocationManager.java:1199) at com.android.server.location.gnss.hal.Gpo4Client.registerPassiveLocationUpdates(Gpo4Client.java:198) at com.android.server.location.gnss.hal.Gpo4Client.init(Gpo4Client.java:78) at com.android.server.location.gnss.hal.Gpo4ClientTest.init(Gpo4ClientTest.java:209) ... 8 trimmed Caused by: android.os.RemoteException: Remote stack trace: at com.android.server.location.LocationPermissions.enforceLocationPermission(LocationPermissions.java:116) at com.android.server.location.LocationManagerService.registerLocationListener(LocationManagerService.java:786) at android.location.ILocationManager$Stub.onTransact(ILocationManager.java:582) at android.os.Binder.execTransactInternal(Binder.java:1285) at android.os.Binder.execTransact(Binder.java:1249)
06-01

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

江南才尽,年少无知!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值