In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-16 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >
Share
Shulou(Shulou.com)06/02 Report--
This article introduces how to use Binder mechanism to achieve inter-process communication in Android, the content is very detailed, interested friends can refer to, hope to be helpful to you.
Step 1: get ManagerService service proxy BpBinder (0) and BpManagerService
Step 2: package some information of the service through the addService method in BpManagerService, and then send the information to the kernel through BpBinder (0) and wait for the ManagerService process to read it. Because there is a Loop in the ManagerService process that has been reading the kernel information, the ManagerService process quickly gets the information sent by service to the kernel. The ManagerService process adds some information about the service service to the maintenance list and sends the added result to the kernel. Then service waits for the kernel to reply and decode and analyze the returned information.
Step 3: execute a Loop to read the client request from the kernel
Code
Here is the code to add a service
Step one:
Sp proc (ProcessState::self ())
Sp sm = defaultServiceManager ()
Step 2:
DefaultServiceManager ()-> addService (String16 ("media.player"), new MediaPlayerService ())
Step 3:
ProcessState::self ()-> startThreadPool ()
IPCThreadState::self ()-> joinThreadPool ()
Code analysis
Sp proc (ProcessState::self ())
Create an instance of ProcessState
ProcessState::mDriverFD=open_driver ()
ProcessState::mVMstart = mmap (… , mDriverFD,...)
Mmap (0, … , mDriverFD,0); / / just to make communication faster, you can take it as nothing, just use read/write (mDriverFD)
Sp sm = defaultServiceManager ()
The main execution is as follows
Sp gDefaultServiceManager = interface_cast (PorcessState::self ()-> getContextObject (NULL))
Where PorcessState::self ()-> getContextObject (NULL) is to execute PorcessState::getStrongProxyForHandle (0); it mainly creates the corresponding sp b = new BpBinder (0) based on the given parameter (0 here).
Here we first explain the template class interface_case. The function of this template class is to convert the BpBinder (x) corresponding to the service xxxService into the corresponding BpxxxService as follows:
Sp BpxxxService= interface_cast (newBpBinder (x))
Its essence is to call the asInterface method of a given type parameter, that is, IxxxService::asInterface (new BpBinder (x)), and IxxxService inherits publicIInterface
IxxxService implements the asInterface method with macro declare _ META_INTERFACE (xxxService) and IMPLEMENT_META_INTERFACE (xxxService, "android.os.IxxxService"). After expansion, such as new BpxxxService (new BpBinder (x)), BpxxxService is obtained from BpBinder (x).
For example, the type parameter given in this example is IServiceManager, so the above is equivalent to
Sp gDefaultServiceManager = IServiceManager::asInterface (new BpBinder (0)); IServiceManager inherits publicIInterface
The macro declare _ META_INTERFACE (ServiceManager) and IMPLEMENT_META_INTERFACE (ServiceManager, "android.os.IServiceManager") are used to implement the asInterface method, and this asInterface method finally executes new BpServiceManager (new BpBinder (0)).
That is, sp sm = newBpServiceManager (new BpBinder (0))
As a result, BpBinder (0) and BpServiceManager are obtained.
As you can see from this, if you create a service xxxService yourself, follow these steps
Create class class IxxxService:publice IInterface
{
DECLARE_META_INTERFACE (xxxService); / / declare the asInterface method
Virtual function (); / / virtual function, implemented by BpxxxService
...
}
IMPLEMENT_META_INTERFACE (xxxService, "android.os.IxxxService"); / / define asInterface
Expand is equivalent to spIxxxService::asInterface (BpBinder) {
Return new BpxxxService
}
When you have Bpbinder (x) for this service, you can get the BpxxxService as follows
Spsm = new BpxxxService (new BpBinder (x))
Note:
1:BpxxxService type is sp
2:BpBinder (x) is equivalent to the proxy of the binder entity corresponding to xxxService
3: why would the client create another BpxxxService through BpBinder (X)? Since one of the mRemote variables in the base class of the BpxxxService object is Bpbinder (x), why not just use BpBinder (x)? Because the BpxxxService object also implements some business logic that BpBinder (x) does not have (implementing the methods in the base class IxxxService), such as the addService method provided in BpServiceManager, these methods have corresponding services on the server. For example, the addService method packages the requested command "addService" and data into a Parcel type, and then sends it to xxxService through BpBinder (x). In fact, it is sent to the binder device in the driver first, and there will be Loop loops in the xxxService service that always read messages from binder devices. After reading the message, the message is parsed into command + data, then the corresponding service is called according to the command such as "addService", and then the result is fed back to the binder device. After receiving the feedback from the binder device, the client parses the returned data into command + data, and then executes the corresponding logic according to the command and data.
The client packages the data through the method in BpxxxService-- > Bpbinder (x)-- > binder device-- > server Loop acquires data and parses it into command + data-- > fetches the service specified by the command, which involves BBinder and BnxxxService, and returns data.
The client parses the returned data and executes the corresponding logic transact ()
After analyzing IPCThreadState, you only need to know that each thread has an instance of IPCThreadState, which has an attribute mIn,mOut, in which mIn is used to accept parcel type data from binder devices, mOut is used to store parcel type data sent to binder devices, and IPCThreadState::self ()-> transact () finally completes the interaction with binder devices. In this interface, writeTransactionData is first called to encapsulate the data of type parcel and the command code of type int32_t into the mOut of the IPCThreadState instance, and then IPCThreadState::self ()-> transact () calls the IPCThreadState::self ()-> waitForResponse interface, where talkWithDriver () is called to exchange data with binder devices (talkwithDriver is mainly implemented by ioctl (mProcess- > mDriverFD,BINDER_WRITE_READ, & bwr)). Store the returned data in the mIn of the IPCThreadState instance, and then call executeCommand () to parse according to the command code and data in mIn to invoke various business logic
The Loop loop implementation code for the ServiceManager service is shown below:
Struct binder_state * bs
Void * svcmgr = BINDER_SERVICE_MANAGER
Bs = binder_open (128 / 1024); / / it should be to open the binder device.
Binder_become_context_manager (bs) / / become manager
Svcmgr_handle = svcmgr
Binder_loop (bs, svcmgr_handler); / / Loop
New MediaPlayerService (), MediaPlayerService inherits BnMediaPlayService,BnMediaPlayService inherits BnInterface, BnInterface inherits BBinder, and BBinder inherits IBinder, so MediaPlayerService inherits IBinder,addService the second parameter type is IBinder instance-MediaPlayService, that is, instance-BnMediaPlaySerivce.
ProcessState::self ()-> startThreadPool ()
IPCThreadState::self ()-> joinThreadPool ()
After creating a MediaPlayerService service (that is, creating a BnMediaPlaySerivce), add it to a list maintained by serviceManage. Next, BnMediaPlaySerivce should also play the role of a service, creating a Loop to wait for a request from the client client, so there should also be a loop, that is, the following two pieces of code
ProcessState::self ()-> startThreadPool ()
IPCThreadState::self ()-> joinThreadPool ()
First analyze ProcessState::self ()-> startThreadPool ()
Its call
Sp t = new PoolThread (isMain); isMain is TRUE
T-> run (buf); / / this sentence results in a call to t-> threadLoop, where IPCThreadState::self ()-> joinThreadPool (mIsMain) is executed.
So in the final analysis, we all call IPCThreadState::self ()-> joinThreadPool (mIsMain).
The main thing here is to execute a loop.
Do {
Int32_tcmd
Result = talkWithDriver ()
Result = executeCommand (cmd)
}
} while (result! =-ECONNREFUSED & & result! =-EBADF)
Summary: call talkWithDriver () to exchange data with binder devices (talkwithDriver is mainly implemented by ioctl (mProcess- > mDriverFD,BINDER_WRITE_READ, & bwr), store the returned data in the mIn of the IPCThreadState instance, and then call executeCommand () to parse according to the command code and data in mIn to call your own (here BnMediaPlaySerivce) various business logic For example, if the command is BR_TRANSACTION, reinterpret_cast (tr.cookie)-> transact (tr.code,buffer, & reply, tr.flags) will be called. The result calls the oNTransact method of BnMediaPlaySerivce
This will call different business logic according to the command code and data obtained from the mIn, and then dispatch the functions to the derived class MediaService (created by themselves), which will do the actual work.
There are often the following situations where 2:client accesses a service service
Process
Step 1: get ManagerService service proxy BpBinder (0) and BpManagerService
Step 2: package some information of the service through the getService method in BpManagerService, and then send the information to the kernel through BpBinder (0) and wait for the ManagerService process to read it. Because there is a Loop in the ManagerService process that has been reading the kernel information, it quickly gets the information that client sends to the kernel. The ManagerService process sends what client wants to know to the kernel, and client returns when the kernel has a reply. Decode the returned information and analyze whether there is a service service. If there is a service, the returned information contains the Bpbinder (x) of the service. Client can be obtained by spBpservice = interface_cast (Bpbinder (x)). To get the services corresponding to service in BpService,BpService
Step 3: access the service
Before client accesses these services, it first calls the specific service in BpService to package the data and commands, and sends the information to the kernel through Bpbinder (x), because service also has a Loop reading kernel information all the time, so service quickly gets the information from client. After parsing, the data is sent to the method contained in the Bnservice object for parsing according to the command code in the information, and then the processed data is sent to the kernel. Client returns after waiting for the message received by the kernel, decodes the returned message and then processes it
Code
Here is the code for client to get the service
Step one:
Sp proc (ProcessState::self ())
Sp sm=defaultServiceManager ()
See above
Step 2:
Sp binder = sm- > getServices (String16 ("media.player"))
Sp sMediaPlayService = interface_cast (binder)
On how to use the Binder mechanism in Android to achieve inter-process communication is shared here, I hope the above content can be of some help to you, can learn more knowledge. If you think the article is good, you can share it for more people to see.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.