[Ce-android-mainline] binder re-implementation
neilb at suse.de
Mon Jan 30 23:38:22 UTC 2012
On Fri, 27 Jan 2012 13:51:19 +0000 Arnd Bergmann <arnd at arndb.de> wrote:
> I don't understand the binder requirements well enough to judge if there
> are any fundamental differences that we can't work around in message queues.
Partly triggered by this comment I decided to write out what I understand the
requirements to be, and then the weaknesses.
I was going to add a more concrete description of a possible solution but
kept hitting the same recurring difficulties (I'm probably trying too hard -
I usually do).
So here it is with just the problem statement, not the solution.
The features of Android Binder are:
- reliable datagram messaging.
A message can be sent from one process to another and can convey
a byte string, some file descriptors, and some object descriptors (see below).
A message also converys the process id and uid of the sending process.
- object descriptors
Each 'object' belongs to a single process. A descriptor for the object
can be passed to another process in a message.
Object descriptors are the primary addressing mechanism for messaging.
A message is addressed to an object, and it is passed to the process
(thread-group) which owns that object.
As object descriptors cannot be faked, they can also be used as credentials.
If a particular object is only given out in restricted circumstances, then
any process which can pass a descriptor for an object must have been able
to receive it and so is in the appropriate restricted set.
So it must be possible to compare object descriptors for equality.
- well known object.
There is a well-known object that every process automatically owns a descriptor
for. This is identified by descriptor '0'. Only a single privileged process
can request to receive messages destined for object '0'.
- death notifications
A process can request notification when an object dies. When the process
which owns the object exits (or closes its Binder handle) the notification
- Transaction tracking.
Some messages are one-shot and do not expect a reply and are not involved in
Otherwise each thread can only be involved in one transaction at a time.
When a thread sends a message and waits for a reply, it will only be passed
a genuine reply to that message, or a new message in a subordinate request
in the same transaction.
i.e. If 'A' sends a request to 'B' and 'B' find that to complete the request
it needs to call some object which happens to be owned by 'A', then that call
will be flagged as being in the same transaction so 'A' will be chosen to
process it. If at this time 'C' sends a message to an object owned by 'A',
the message will either be queued until the current transaction completes, or
if 'A' is part of the thread group, the message can be handled by some other
thread in the group.
- process priority follows transaction
With a transaction there is only one thread active at a time. Other threads
which are part of the transaction will be waiting for a reply.
Binder allows the priority of the initiating thread to be handed on to other
threads taking part in the transaction so the whole transaction runs
with the priority of the initiating thread.
- single-copy messaging.
When a message is sent from A to B it is copied exactly once by the kernel,
from the address space of A into a buffer which is managed by the kernel
and mapped into the address space of B. B can use the information directly
Note that as there is no 'writev' style interface, 'A' may need to copy parts
of the message into a buffer to linearise it, so this may not always provide
true single-copy messaging.
- thread management.
binder can alter the user-space part of the threads when all threads in the
thread pool are busy so that it can start new threads if it wishes.
This happens in a controlled way so that it is easy to ensure that only
one thread attempts to create new threads.
Weaknesses in the Android Binder implementation.
(A 'binder handle' is a file descriptor obtained by opening /dev/binder.)
- The identity of a binder handle is closely linked with the process
that is using it. If it is passed to another process - e.g. by 'fork'
or some form of IPC - it will behave very differently.
- The binder handle is intended to be shared between threads of a
thread group. However it behaves slightly differently in each thread
to implement the transaction semantics. This is 'odd'.
- The ioctl to send a message does not take an iovec list, so true
single-copy may not always be possible.
- The mapped receive buffer imposes an arbitrary limit on the total
size of active transaction for a process.
- There is only one 'well known object'. So binder cannot be used
concurrently for several independent purposes unless there is a
single broker which works with all the different uses. Having
multiple 'well known objects' would make it a lot easier to have
multiple independant users.
- 'death notifications' are a useful broadcast mechanism, but are
very narrow in application. The same basic mechanism could provide
a more general 'broadcast' or 'publish/subscribe' mechanism.
- binder ensures that if a process receives a descriptor for a given object
twice, they will both by the same byte-string for that process.
This seems natural, but
a/ is different from the way passing file descriptors works (you always
receive a new file descriptor)
b/ requires extra linkage and lookups in the kernel, and
requires a complex ref-counting protocol between user-space and
kernel which would not otherwise be necessary.
- binder shares a lot of concepts with unix-domain sockets but uses
none of the infrastructure. Thus we find little things are missing
like that fact that while a pid and uid can be sent in a message,
the gid is not.
-------------- next part --------------
A non-text attachment was scrubbed...
Size: 828 bytes
Desc: not available
More information about the Ce-android-mainline