面试可能会问到的问题
- 从IPC的办法问到Binder的优势
- 为什么zygote跟其他服务进程的通讯不运用Binder
- Binder线程池和Binder机制
等等这些问题都是根据你对Binder的了解还有对其他IPC通讯的了解
IPC办法有多少种
- 传统的IPC办法有Socket、同享内存、管道、信号量等
- 安卓特有的是
Binder
,其他体系也有自己界说的比方window的wfc(Windows Communication Foundation)
Binder机制的优势
- 参阅博客
传统的ipc管道跟信号量都是比较轻的,基本不能用于复杂的IPC通讯,Socket有个缺陷便是数据要仿制两遍,第一遍是进程A仿制到Socket通道,第二遍是Socket通道仿制到进程B。同享内存的缺陷便是不方便办理,假如频频的对同享内存进行操作很可能会导致死锁、饥饿等问题。
为了处理这个痛点,安卓规划了Binder的通讯机制,供给更高效、安全、可靠的办法。下图是Binder机制图。只需求在内核里边仿制一遍,这儿能够简略的了解为单例形式,大家都只需求对Binder内存区域做操作,内存只要一份。
还有一些概念,比方咱们应该都传闻Binder是内核里边的,Binder是怎么用到安卓体系里边的,再看一个图 这儿边有四个角色,其实很好了解,两个进程、一个Binder内核空间、一个ServiceManager服务。两个进程时选用的C/S结构一个客户端一个服务端。
-
Binder
内核空间便是一块存在于内核区的内存了解为一个通道 -
ServiceManager
是安卓的中心服务之一,AMS、PMS、WMS这些是相同的。它里边供给了许多线程池。Binder线程池只是其中的一种。在这儿能够了解为是办理Binder给外部用的供给了一个注册机制用于辨认不同的进程。下面是其他的几个线程池- Activity Manager线程池:用于处理Activity发动、停止等操作,确保UI界面的流畅性。
- JobScheduler线程池:用于调度履行后台任务。
- MediaServer线程池:用于处理音视频等媒体数据。
- SurfaceFlinger线程池:用于处理UI界面绘制等操作。
有没有想过为什么要搞那么线程池,还要搞那么多个。其实也比较好了解,因为ServiceManager这个类的有许多当地用到,不可能是单线程处理的,这样就阻塞了。为什么搞那么多线程池是因为不同的功用不同比方有些调用比较频频有些需求比较多的cpu。只要一个线程池的话很简略会导致占用时间过长等问题。
-
server进程
需求供给办法被他人调用,需求先在ServiceManager里边注册。 - server注册完以后会供给接口给
client进程
调用
来到这儿应该能够答复剩下的那两个问题了。
Binder线程池和Binder机制
- Binder线程池是ServiceManager供给的,运用的是Binder内核机制。
- Binder机制是安卓为了供给更高效、安稳、可靠的办法完成的一套根据内核的IPC机制。
为什么zygote进程跟其他进程通讯运用socket而不是binder
- Binder虽然在内核,但是供给服务的是ServiceManager,这个时分假如要给AMS供给Binder IPC就需求等ServiceManager先初始化好,这个是没办法确保的,假如要确保这个先后顺序又要搞多一套进程通讯就更麻烦了。
- 别的,因为Zygote进程只与少数几个进程进行通讯,运用Socket通讯的开支相对较小,因而选择Socket通讯愈加适宜。并且这儿边是优化过的LocalSocket效率会更高。
上面一直说内核空间,那内核空间跟用户空间有什么区别呢?
-
内核程序运行在操作体系的内核空间,具有更高的权限和更快的履行速度,能够完成更底层的操作,如硬件驱动、文件体系等,因而一般用于操作体系的中心功用的完成。
-
用户程序运行在操作体系的用户空间,具有更多的自由度和可移植性,能够完成更丰厚的功用,如应用程序、服务进程等,因而一般用于操作体系的外围功用和应用程序的完成。
简略的说便是内核空间有操作内存的办法,但是这一块对用户空间是关闭的,用户空间里边操作的都是内核供给的服务。比方操作文件用到的文件体系模块
和操作内存用到的内存办理模块
。拿内存办理模块里边用到的kmalloc
和kfree
来说。这两个办法在用户空间就调用不到,这是内核封装的办法。
`kmalloc()` 和 `kfree()`: 内核内存分配器,用于在内核空间中动态分配和开释内存。
// 这个还并不是c/c++的原生办法,是内核自己封装的
再看一下比方运用Binder的时分咱们传的是一个序列化的文件,那他是怎么映射到内存中的?
在内核中有vm_map_ram
和vm_insert_page
这些办法能够把文件插入到内存地址中。而假如在用户空间需求跟这些打交道用到的还是内存办理模块的mmap
这些。
mmap
的完成在内核中运用了 vm_area_struct
。意思是内存办理模块供给给外面的一层封装。所以与其这么麻烦还不如直接放到内核里边更适宜。
这些办法其实都不重要,只需求知道一点,这些办法在用户进程空间是拿不到的
根据Binder的IPC
这儿是一些基础,能够不看了。因为这些用的少,方便自己以后看
AIDL
服务端
// IMyService.aidl
interface IMyService {
int add(int a, int b);
}
// MyService.java
public class MyService extends Service {
@Override
public IBinder onBind(Intent intent) {
return new MyBinder();
}
private class MyBinder extends IMyService.Stub {
@Override
public int add(int a, int b) throws RemoteException {
return a + b;
}
}
}
客户端
// MainActivity.java
public class MainActivity extends AppCompatActivity {
private IMyService mService;
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mService = IMyService.Stub.asInterface(service);
try {
int result = mService.add(1, 2);
Toast.makeText(MainActivity.this, "Result: " + result, Toast.LENGTH_SHORT).show();
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
mService = null;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(this, MyService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(mConnection);
}
}
Messager
轻量级的AIDL只能单线程 服务端 MessengerService.java:
public class MessengerService extends Service {
private static class IncomingHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
String clientMessage = (String) msg.obj;
Log.i("MessengerService", "Received message from client: " + clientMessage);
// Send a response back to the client
Messenger clientMessenger = msg.replyTo;
Message replyMessage = Message.obtain(null, 2);
Bundle bundle = new Bundle();
bundle.putString("serverResponse", "Hello from server!");
replyMessage.setData(bundle);
try {
clientMessenger.send(replyMessage);
} catch (RemoteException e) {
Log.e("MessengerService", "Failed to send message to client", e);
}
break;
default:
super.handleMessage(msg);
}
}
}
private final Messenger mMessenger = new Messenger(new IncomingHandler());
@Override
public IBinder onBind(Intent intent) {
return mMessenger.getBinder();
}
}
客户端 MessengerClient.java:
public class MessengerClient extends AppCompatActivity {
private Messenger mMessenger;
private static class IncomingHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 2:
String serverMessage = msg.getData().getString("serverResponse");
Log.i("MessengerClient", "Received message from server: " + serverMessage);
break;
default:
super.handleMessage(msg);
}
}
}
private final Messenger mClientMessenger = new Messenger(new IncomingHandler());
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(this, MessengerService.class);
bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(mServiceConnection);
}
private final ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mMessenger = new Messenger(service);
sendMessageToServer();
}
@Override
public void onServiceDisconnected(ComponentName name) {
mMessenger = null;
}
};
private void sendMessageToServer() {
if (mMessenger == null) {
return;
}
Message message = Message.obtain(null, 1);
message.obj = "Hello from client!";
message.replyTo = mClientMessenger;
try {
mMessenger.send(message);
} catch (RemoteException e) {
Log.e("MessengerClient", "Failed to send message to server", e);
}
}
}
广播、内容供给者
……