±à¼ÍƼö: |
±¾ÎÄÖ÷Òª½éÉÜÁËBinder¼Ü¹¹¡¢»ù´¡Êý¾Ý½á¹¹¡¢BinderÇý¶¯¡¢Native²ã¼¶µÄBinder½á¹¹¡¢BinderͨÐÅ»úÖÆ¡¢Binder½ø³ÌÓëÏ̡߳¢ServiceManager²éÕÒ·þÎñ¡¢ÍêÕûµÄͨÐÅÁ÷³Ì
µÈÏà¹ØÄÚÈÝ¡£
±¾ÎÄÀ´×ÔÓÚ¼òÊ飬ÓÉ»ðÁú¹ûÈí¼þAnna±à¼¡¢ÍƼö¡£ |
|
Binder
BinderÊÇʲô£¿
BinderÊÇÒ»ÖÖ½ø³Ì¼äͨÐÅ»úÖÆ
ΪʲôÊÇBinder£¿
Binder¼Ü¹¹
BinderͨÐÅ»úÖÆ²ÉÓÃC/S¼Ü¹¹£¬ÕâºÜÖØÒª£¡£¡£¡

@Binder¼Ü¹¹|center
Binder¿ò¼ÜÖÐÖ÷񻃾¼°µ½4¸ö½ÇÉ«Client¡¢Server¡¢Service Manager¼°BinderÇý¶¯£¬ÆäÖÐClient¡¢Server¡¢Service
ManagerÔËÐÐÔÚÓû§¿Õ¼ä£¬BinderÇý¶¯ÔËÐÐÔÚÄں˿ռä
Client´ú±í¿Í»§¶Ë½ø³Ì£¬Server´ú±í¿Í»§¶Ë½ø³ÌÌṩ¸÷ÖÖ·þÎñ£¬ÈçÒôÊÓÆµµÈ
Service ManagerÓÃÀ´¹ÜÀí¸÷ÖÖϵͳ·þÎñ
BinderÇý¶¯Ìṩ½ø³Ì¼äͨÐŵÄÄÜÁ¦
Óû§¿Õ¼äµÄClient¡¢Server¡¢ServiceManagerͨ¹ýopen¡¢mmapºÍioctlµÈ±ê×¼Îļþ²Ù×÷(Ïê¼ûUnix»·¾³±à³Ì)À´·ÃÎÊ/dev/binder£¬½ø¶øÊµÏÖ½ø³Ì¼äͨÐÅ
»ù´¡Êý¾Ý½á¹¹

Binder»ù´¡Êý¾Ý
¹ØÓÚBinder»ù´¡Êý¾Ý£¬¼ûÉÏͼ
BinderÇý¶¯

BinderÇý¶¯¹¤×÷ͼ
/kernel/drivers/staging/android/binder.c
device_initcall(binder_init); |
É豸³õʼ»¯Ê±ºò»áµ÷ÓÃbinder_init½øÐÐbinderÇý¶¯³õʼ»¯
/kernel/drivers/staging/android/binder.c
//°ó¶¨binderÇý¶¯²Ù×÷º¯Êý
static const struct file_operations binder_fops
= {
.owner = THIS_MODULE,
.poll = binder_poll,
.unlocked_ioctl = binder_ioctl,
.compat_ioctl = binder_ioctl,
.mmap = binder_mmap,
.open = binder_open,
.flush = binder_flush,
.release = binder_release,
};
//´´½¨miscÀàÐ͵ÄÇý¶¯
static struct miscdevice binder_miscdev = {
.minor = MISC_DYNAMIC_MINOR,
.name = "binder",
.fops = &binder_fops//°ó¶¨binderÇý¶¯²Ù×÷º¯Êý
}; //binderÇý¶¯³õʼ»¯
static int __init binder_init(void)
{
int ret; binder_deferred_workqueue = create_singlethread_workqueue("binder");
if (!binder_deferred_workqueue)
return -ENOMEM; //´´½¨Ä¿Â¼/binder
binder_debugfs_dir_entry_root = debugfs_create_dir("binder",
NULL);
if (binder_debugfs_dir_entry_root)
//´´½¨Ä¿Â¼/binder/proc
binder_debugfs_dir_entry_proc = debugfs_create_dir("proc",
binder_debugfs_dir_entry_root);
//×¢²ábinderÇý¶¯
ret = misc_register(&binder_miscdev);
//´´½¨ÆäËûÎļþ
if (binder_debugfs_dir_entry_root) {
//´´½¨Îļþ/binder/proc/state
debugfs_create_file("state",
S_IRUGO,
binder_debugfs_dir_entry_root,
NULL,
&binder_state_fops);
//´´½¨Îļþ/binder/proc/stats
debugfs_create_file("stats",
S_IRUGO,
binder_debugfs_dir_entry_root,
NULL,
&binder_stats_fops);
//´´½¨Îļþ/binder/proc/transactions
debugfs_create_file("transactions",
S_IRUGO,
binder_debugfs_dir_entry_root,
NULL,
&binder_transactions_fops);
//´´½¨Îļþ/binder/proc/transaction_log
debugfs_create_file("transaction_log",
S_IRUGO,
binder_debugfs_dir_entry_root,
&binder_transaction_log,
&binder_transaction_log_fops);
//´´½¨Îļþ/binder/proc/failed_transaction_log
debugfs_create_file("failed_transaction_log",
S_IRUGO,
binder_debugfs_dir_entry_root,
&binder_transaction_log_failed,
&binder_transaction_log_fops);
}
return ret;
} |
³õʼ»¯Ö÷Òª×öÁËÁ½¼þÊÂÇé
³õʼ»¯´æ´¢binder´æ´¢ÐÅÏ¢µÄĿ¼
´´½¨binderÉ豸£¬²¢°ó¶¨²Ù×÷º¯ÊýÈçbinder_open¡¢binder_mmap¡¢binder_ioctlµÈ
É豸Æô¶¯Ê±ºò£¬»áµ÷ÓÃbinder_init£¬Ö÷Òª×öÁ½¼þÊÂÇé
1.´´½¨/binder/procĿ¼£¬Ö®ºóÔÚÕâ¸öĿ¼Ï´´½¨state¡¢stats¡¢transactions¡¢transaction_log¡¢failed_transaction_logÎļþ¼Ð£¬·Ö±ð´æ´¢½ø³ÌͨÐŵĸ÷ÖÖÊý¾Ý
2.×¢²áÇý¶¯£¬²¢°ó¶¨Îļþ²Ù×÷º¯Êýbinder_open¡¢binder_mmap¡¢binder_ioctlµÈ£¬Ö®ºó¾Í¿ÉÒÔͨ¹ýRPC»úÖÆÈ¥·ÃÎÊbinderÇý¶¯
Native²ã¼¶µÄBinder½á¹¹

@Server×é¼þÀàͼ|center

@Client×é¼þÀàͼ|center
BinderͨÐÅ»úÖÆ

@Binder·Ö²ã|center
Binder½ø³ÌÓëÏß³Ì

@BinderÇý¶¯ÖеÄÏß³ÌÓëÓû§¿Õ¼äµÄÏß³Ì
ServiceManagerÆô¶¯

@ServiceManagerÆô¶¯
Ô¤±¸ÖªÊ¶²¹³ä
ServiceManagerÆô¶¯Á÷³ÌÖ÷Òª·ÖΪÈý¸öÁ÷³Ì
1.ÒÔϵͳ·þÎñÐÎʽÆô¶¯service_manager,Ö®ºóͨ¹ýÔÚbinder_openº¯Êý´ò¿ªÇý¶¯É豸£¬Çý¶¯²ãÏàÓ¦µÄ¾Í»á´´½¨service_manager¶ÔÓ¦µÄbinder_proc£¬²¢ÇÒÕâÊǸöÌØÊâµÄservice
2.µ÷ÓÃbinder_become_context_managerͨ¹ýioctlµ÷ÓÃÄÚºËÖеÄbinder_ioctl,¾¹ýһϵÁд¦Àíºó£¬binderÇý¶¯»á½«Õâ¸öÌØÊâµÄbinder_node´æµ½¾²Ì¬Ö¸Õëbinder_context_mgr_node
static struct
binder_node *binder_context_mgr_node;
...
static int binder_ioctl_set_ctx_mgr (struct
file *filp)
{
...
//×¢ÒâÕâÀïºóÐøÁ½¸ö²ÎÊý¶¼ÊÇ0
binder_context_mgr_node = binder_new_node(proc,
0, 0);
...
}
... |
3.µ÷ÓÃbinder_loop½øÈëÑ»·½âÎöµÄ¹ý³Ì
int main(int
argc, char** argv){
...
//½øÈëÑ»·£¬µÈ´ý»ò´¦ÀíClient½ø³ÌµÄͨÐÅÇëÇó
binder_loop(bs, svcmgr_handler);
...
} |
ÕâÀïÖ¸¶¨Ñ»·´¦Àíº¯ÊýΪsvcmgr_handler,ºóÐøÔÙ×Ðϸ·ÖÎöÕâ¸öº¯Êý£¬ÏÈ¿´binder_loopʵÏÖ
void binder_loop
(struct binder_state *bs, binder_handler func)
{
...
//ͨÐÅÊý¾Ý
struct binder_write_read bwr;
bwr.write_size = 0;
bwr.write_consumed = 0;
bwr.write_buffer = 0; readbuf[0] = BC_ENTER_LOOPER;
binder_write(bs, readbuf, sizeof(uint32_t));
for (;;) {
bwr.read_size = sizeof(readbuf);
bwr.read_consumed = 0;
bwr.read_buffer = (uintptr_t) readbuf;
res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
...
//½âÎö
res = binder_parse(bs, 0, (uintptr_t) readbuf,
bwr.read_consumed, func);
...
}
} int binder_write (struct binder_state *bs,
void *data, size_t len)
{
struct binder_write_read bwr;
int res; bwr.write_size = len;
bwr.write_consumed = 0;
bwr.write_buffer = (uintptr_t) data;
bwr.read_size = 0;
bwr.read_consumed = 0;
bwr.read_buffer = 0;
res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
...
return res;
} |
Ê×ÏÈ´´½¨Ò»¸öbinder_write_read½á¹¹Ì壬Ȼºóͨ¹ýbinder_writeÏòBinderÇý¶¯Ð´ÈëÃüÁîÐÒéBC_ENTER_LOOPER£¬×¢ÒâÕâ¸öÀíÊä³ö»º³åÇøÊÇûÓÐÊý¾ÝµÄ,binderÇý¶¯¾¹ýһϵÁд¦Àí½øÈëÑ»·×´Ì¬£¬Ö®ºóͨ¹ýÒ»¸öËÀÑ»·À´²»¶ÏµÄ´ÓBinderÇý¶¯¶ÁÈ¡Êý¾Ý£¬Ö®ºó½»ÓÉbinder_parseÈ¥½âÎö¸÷ÖÖÐÒéÊý¾Ý£¬ºóÐøÔÙ·ÖÎöϸ½Ú
BinderÇý¶¯ÊÇÈçºÎ´¦Àí½»»¥Ï¸½ÚµÄ£¬ÎÒÃÇÀ´¿´ÏÂbinder_ioctl_write_readµÄʵÏÖ
static int
binder_ioctl_write_read (struct file *filp,
unsigned int cmd, unsigned long arg,
struct binder_thread *thread)
{
...
//´ÓÎļþ¾ä±úÈ¡³ö½ø³ÌÐÅÏ¢
struct binder_proc *proc = filp->private_data;
//ÃüÁîÐÒé
unsigned int size = _IOC_SIZE(cmd);
...
struct binder_write_read bwr;
//È¡³öbwr½ø³ÌͨÐÅÐÒéÔØÌå
if (copy_from_user(&bwr, ubuf, sizeof(bwr)))
{
...
}
//Èç¹ûÓÐдÈëÊý¾Ý£¬¾Í½»ÓÉbinder_thread_writeÈ¥´¦Àí£¬Ö®ºó
//ͨ¹ýcopy_to_user½«Êý¾Ý·µ»¹¸øÓû§¿Õ¼ä
if (bwr.write_size > 0) {
ret = binder_thread_write(proc, thread,
bwr.write_buffer,
bwr.write_size,
&bwr.write_consumed);
...
if (ret < 0) {
bwr.read_consumed = 0;
if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
...
goto out;
}
}
//Èç¹ûÓÐÊä³öÊý¾Ý£¬Ôòµ÷ÓÃbinder_thread_read½âÎö£¬
//Ö®ºóÅжϽø³ÌµÄÊÂÎñ¶ÓÀïÊÇ·ñΪ¿Õ£¬Èç¹û²»Îª¿Õ¾ÍµÈ´ýÖ´ÐÐ
if (bwr.read_size > 0) {
ret = binder_thread_read(proc, thread, bwr.read_buffer,
bwr.read_size,
&bwr.read_consumed,
filp->f_flags & O_NONBLOCK);
...
if (!list_empty(&proc->todo))
wake_up_interruptible(&proc->wait);
if (ret < 0) {
//½«Ð´³öÊý¾Ý·µ»¹¸øÓû§¿Õ¼ä
if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
...
goto out;
}
}
...
out:
return ret;
}
|
ÖÁÓÚbinder_thread_writeÓëbinder_thread_readÔòÊÇ´¦ÀíÃüÁîÐ(binder_driver_command_protocol)Óë·µ»ØÐÒé(binder_driver_return_protocol
)Ïê¼û/drivers/staging/android/binder.h
ServiceManager×¢²á·þÎñ

@ServiceµÄ×¢²áÁ÷³Ì|center
serviceµÄ×¢²áÁ÷³ÌÈçÉÏͼ£¬ÕâÀïÒÔmedia_serverµÄ×¢²áΪÀý×ÓÈ¥¿´´úÂë
/frameworks/av/services/
mediadrm/mediadrmserver.cpp
int main()
{
...
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm = defaultServiceManager();
...
MediaDrmService::instantiate();
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
} |
¿ÉÒÔ¿´µ½ÒÔÓû§È¨ÏÞÆô¶¯mediadrm·þÎñ£¬ÎļþλÓÚ/system/bin/mediadrmserver
½ÓÏÂÀ´¿´main_mediadrmserver.cpp
/frameworks/av/services/
mediadrm/mediadrmserver.cpp
int main()
{
...
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm = defaultServiceManager();
...
MediaDrmService::instantiate();
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
} |
main()ÖÐÖ÷Òª×öÁËÁ½¼þÊÂÇ飺
1.³õʼ»¯MediaDrmService
2.Ï̳߳سõʼ»¯
ÏÈ¿´µÚÒ»¸ö
/frameworks/av/services/
mediadrm/MediaDrmService.cpp
...
void MediaDrmService::instantiate() {
defaultServiceManager()->addService(
String16("media.drm"), new MediaDrmService());
}
... |
ÕâÀïÃæÖ÷Ҫͨ¹ýdefaultServiceManager()»ñȡһ¸öBpServiceManagerÖ¸ÕëÈ»ºóµ÷ÓÃaddService£¬×¢ÒâÕâÀï´«ÈëµÄÁ½¸ö²ÎÊý¡°media.drm¡±ºÍÒ»¸öMediaDrmService¶ÔÏó
ServiceManager´úÀí¶ÔÏóµÄ»ñÈ¡
ÏÈÀ´¿´defaultServiceManager()µ÷ÓÃ
/frameworks/native/libs/
binder/Static.cpp
...
sp<IServiceManager> gDefaultServiceManager;
... /frameworks/native/libs/ binder/ISerivceManager.cpp
...
sp<IServiceManager> defaultServiceManager()
{
if (gDefaultServiceManager != NULL)
return gDefaultServiceManager;
{
...
while (gDefaultServiceManager == NULL) {
gDefaultServiceManager = interface_cast<IServiceManager>(
ProcessState:: self()->getContextObject(NULL));
...
}
} return gDefaultServiceManager;
}
... |
gDefaultServiceManager¾ÍÊÇÒ»¸öIServiceMangerµÄÖ¸Õë
Ê״λñȡʱºòÒ»¶¨ÊÇͨ¹ýinterface_cast<IServiceManager>(ProcessState::self()
->getContextObject(NULL))ÕâһϵÁÐmethodµ÷ÓûñÈ¡µÄ£¬Ò»²½²½·ÖÎö
ÏÈ¿´ProcessState::self()
/frameworks/native/libs/binder/ProcessState
...
sp<ProcessState> ProcessState::self()
{
Mutex::Autolock _l(gProcessMutex);
if (gProcess != NULL) {
return gProcess;
}
//×¢ÒâÕâÀïµÄÎļþname
gProcess = new ProcessState("/dev/binder");
return gProcess;
}
...
|
ÎҶİë°üÀ±Ìõ£¬Õâ¸öÀ๹ÔìÒ»¶¨³ÖÓдò¿ª/dev/binderµÄ¾ä±ú£¬²»ÐÅÄã¿´¹¹ÔìÉùÃ÷
//ÕâÀïÊÇcpp¹¹Ô캯ÊýÐÎʽ£¬¾ÍÊdzÉÔ±±äÁ¿¸³Öµ
ProcessState::ProcessState(const char *driver)
: mDriverName(String8(driver))
, mDriverFD(open_driver(driver))
, mVMStart(MAP_FAILED)
, mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)
, mThreadCountDecrement(PTHREAD_COND_INITIALIZER)
, mExecutingThreadsCount(0)
, mMaxThreads(DEFAULT_MAX_BINDER_THREADS)
, mStarvationStartTimeMs(0)
, mManagesContexts(false)
, mBinderContextCheckFunc(NULL)
, mBinderContextUserData(NULL)
, mThreadPoolStarted(false)
, mThreadPoolSeq(1)
{
if (mDriverFD >= 0) {
// mmap the binder, providing a chunk of virtual
address space to receive transactions.
//×¢ÒâÕâÀï·ÖÅäµÄBINDER_VM_SIZEΪ1016kb£¬¾ßÌå¼ûºê¶¨Òå´¦
mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ,
MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
if (mVMStart == MAP_FAILED) {
...
close(mDriverFD);
mDriverFD = -1;
mDriverName.clear();
}
}
...
} |
ÔÙÀ´¿´getContextObject
sp<IBinder>
ProcessState:: getContextObject (const sp<IBinder>&
/*caller*/)
{
//×¢ÒâÕâÀï´«ÈëµÄֵΪ0
return getStrongProxyForHandle(0);
} ...
sp<IBinder> ProcessState:: getStrongProxyForHandle(int32_t
handle)
{
sp<IBinder> result;
...
handle_entry* e = lookupHandleLocked(handle);
if (e != NULL) {
...
b = BpBinder::create(handle);
e->binder = b;
if (b) e->refs = b->getWeakRefs();
result = b;
}else{
...
}
return result;
} |
getContextObject()ÄÚ²¿Êǵ÷ÓÃgetStrongProxyForHandle(0)À´»ñȡһ¸öIBinderÖ¸Õë(ÕâÀï0Æäʵ¾ÍÊÇΪÁ˺óÐø²éÕÒ֮ǰServiceManagerÆô¶¯×¢²áÄǸöÌØÊâµÄService×é¼þ)£¬¿ÉÒÔ¿´µ½ÆäʵÕâÀï´´½¨µÄÊÇÒ»¸öBpBinder¶ÔÏ󣬲¢ÇÒËûµÄ¾ä±úÖµÊÇ0
ÎÒÃÇÀ´¿´BpBinderµÄÏà¹Øµ÷ÓÃ
frameworks/native/libs/binder/BpBinder.cpp
//handle¾ä±úÖµ ÓëbinderÇý¶¯ÖеÄbinderÒýÓöÔÏó½øÐйØÁª
BpBinder::BpBinder (int32_t handle, int32_t
trackedUid)
//×¢ÒâÕâÀï´«ÈëµÄÊÇ0
: mHandle(handle)
//×¢ÒâÕâ¸öֵΪ1
, mAlive(1)
, mObitsSent(0)
, mObituaries(NULL)
, mTrackedUid(trackedUid)
{
...
IPCThreadState::self()->incWeakHandle(handle,
this);
} BpBinder* BpBinder::create(int32_t handle)
{
...
return new BpBinder(handle, trackedUid);
} |
»Øµ½defaultServiceManager()£¬×îºóinterface_cast<IServiceManager>(BpBinder(0))ʵ¼ÊÉÏת»»³ÉÁËÕâ¸ö£¬Õâ¸öÔÚÄÄÀﶨÒåÄØ£¿
/frameworks/native/include/
binder/IInterface.h
template<typename INTERFACE>
inline sp<INTERFACE> interface_cast (const
sp<IBinder>& obj)
{
return INTERFACE::asInterface(obj);
}
|
·¢ÏÖËûÊǸöÄÚÁªÄ£°åº¯Êý£¬Êµ¼ÊÉϵ÷ÓõÄÊÇIServiceManager::asInterface(BpBinder(0))£¬ÄÇôIServiceManager::asInterfaceÔÚÄÄÀﶨÒåÄØ£¿
/frameworks/native/libs/binder/
IServiceManager.cpp
IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager"); |
¿´ÉÏÃæÕâ¸öºê¶¨Ò壬ʵ¼Ê¶¨ÒåÔÚ
/frameworks/native/include/binder/IInterface.h
#define IMPLEMENT_META_INTERFACE
(INTERFACE, NAME)
const ::android::String16 I ##INTERFACE::descriptor(NAME);
const ::android::String16&
I##INTERFACE::getInterfaceDescriptor() const
{
return I##INTERFACE::descriptor;
}
::android::sp<I##INTERFACE> I##INTERFACE::asInterface(
const ::android::sp<:: android::IBinder>&
obj)
{
::android::sp<I## INTERFACE> intr;
if (obj != NULL) {
intr = static_cast<I##INTERFACE*>(
obj->queryLocalInterface(
I##INTERFACE::descriptor).get());
if (intr == NULL) {
intr = new Bp##INTERFACE(obj);
}
}
return intr;
}
I##INTERFACE::I##INTERFACE() { }
I##INTERFACE::~I##INTERFACE() { } |
´øÈëת»»Ï£¬·¢ÏÖÎÒÃÇÄõ½µÄÆäʵ¾ÍÊÇÒ»¸öBpServiceManager
½ÓÏÂÀ´ÎÒÃÇÀ´¿´ºóÐøµÄµ÷ÓÃ
BpServiceManager#addService
virtual status_t
addService (const String16& name, const
sp<IBinder>& service,bool allowIsolated,
int dumpsysPriority) {
//ÕâÀïdata±íʾҪдÈëµÄÊý¾Ý£¬reply±íʾ·µ»ØµÄÊý¾Ý
Parcel data, reply;
//´æ´¢ÃèÊö·û"android.os.IServiceManager"
data.writeInterfaceToken (IServiceManager::getInterfaceDescriptor());
//´æ´¢·þÎñÃû×Ö"media.drm"
data.writeString16(name);
//´æ´¢·þÎñMediaDrmService
data.writeStrongBinder(service);
data.writeInt32(allowIsolated ? 1 : 0);
data.writeInt32(dumpsysPriority);
status_t err = remote()-> transact(ADD_SERVICE_TRANSACTION,
data, &reply);
return err == NO_ERROR ? reply.readExceptionCode()
: err;
} |
ÕâÀïʵ¼ÊÉϰÑÉÏÒ»²½´«ÈëµÄÊý¾Ýͨ¹ýParcel´æÆðÀ´£¬È»ºóµ÷ÓÃremote()»ñȡһ¸öBpBinderÈ»ºóµ÷ÓÃÆätransact£¬´«ÈëµÄcodeΪADD_SERVICE_TRANSACTION£¬¾¹ý°ü×°ºódataÖеÄÊý¾Ý³¤ÕâÑù×Ó

@ParcelÊý¾Ý·â×°|center
¼ÇÏÂÀ´ÎÒÃÇÈ¥¿´BpBinder#transact
status_t BpBinder::transact(
uint32_t code, const Parcel& data, Parcel*
reply, uint32_t flags)
{
// Once a binder has died, it will never come
back to life.
//¹¹ÔìÖÐmAlive=1£¬ËùÒÔÕâÀï»á×ß½øif
if (mAlive) {
//ÕâÀïµ÷ÓõÄÊÇIPCThreadState#transact
status_t status = IPCThreadState::self()->transact(
mHandle, code, data, reply, flags);
if (status == DEAD_OBJECT) mAlive = 0;
return status;
} return DEAD_OBJECT;
} |
Ç°ÃæServiceManager´úÀí¶ÔÏó»ñÈ¡BpBinderʱºò£¬mHandleΪ0£¬codeΪADD_SERVICE_TRANSACTION£¬data´æ´¢binderÐÅÏ¢£¬reply´æ´¢Òª·µ»ØµÄÐÅÏ¢£¬flags²é¿´method¶¨ÒåĬÈϲÎÊýΪ0
½ÓÏÂÀ´·ÖÎöIPCThreadState#transact
/frameworks/native/libs/binder/IPCThreadState.cpp
status_t IPCThreadState::
transact(int32_t handle,
uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags)
{
status_t err; //ÔÊÐí·µ»ØÖÐЯ´øÎļþÃèÊö·û
flags |= TF_ACCEPT_FDS;
...
//·â×°BC_TRANSACTIONͨÐÅÇëÇó
err = writeTransactionData (BC_TRANSACTION,
flags, handle, code, data, NULL);
...
//ͬ²½orÒì²½£¬ÕâÀïÊÇͬ²½µ÷ÓÃ
if ((flags & TF_ONE_WAY) == 0) {
...
if (reply) {
//ÏòBinderÇý¶¯·¢ÆðBC_TRANSACTION
err = waitForResponse(reply);
} else {
Parcel fakeReply;
err = waitForResponse(&fakeReply);
...
}
...
}else{
err = waitForResponse(NULL, NULL);
}
return err;
} |
ÉÏÃæÊ×ÏȽ«flagsÓëTF_ACCEPT_FDS×ö»ò²Ù×÷£¬±íʾ½ÓÊÕÎļþÃèÊö·û
Ö®ºóµ÷ÓÃwriteTransactionData½«Êý¾Ý·â×°³ÉÒ»¸öBC_TRANSACTIONÃüÁîÐÒé,ÕâÀïÊÇͬ²½µ÷ÓÃÇÐÐèÒª·µ»Ø£¬ËùÒÔÖ´Ðе½µÄÊÇwaitForResponse(reply)£¬½ÓÏÂÀ´·Ö±ðÀ´¿´writeTransactionData¡¢waitForResponseµÄʵÏÖ
status_t IPCThreadState::
writeTransactionData (int32_t cmd, uint32_t
binderFlags,
int32_t handle, uint32_t code, const Parcel&
data, status_t* statusBuffer)
{
//¶ÔÓ¦ÄÚºËÖÐÒªÇóioЯ´øbinder_transaction_data½á¹¹Ìå
binder_transaction_data tr; tr.target.ptr = 0; /* Don't pass uninitialized
stack data to a remote process */
tr.target.handle = handle;
tr.code = code;
tr.flags = binderFlags;
tr.cookie = 0;
tr.sender_pid = 0;
tr.sender_euid = 0; const status_t err = data.errorCheck();
if (err == NO_ERROR) {
tr.data_size = data.ipcDataSize();
tr.data.ptr.buffer = data.ipcData();
tr.offsets_size = d ata.ipcObjectsCount()*sizeof(binder_size_t);
tr.data.ptr.offsets = data.ipcObjects();
} else if (statusBuffer) {
tr.flags |= TF_STATUS_CODE;
*statusBuffer = err;
tr.data_size = sizeof(status_t);
tr.data.ptr.buffer = reinterpret_cast<uintptr_t>
(statusBuffer);
tr.offsets_size = 0;
tr.data.ptr.offsets = 0;
} else {
return (mLastError = err);
} mOut.writeInt32(cmd);
mOut.write(&tr, sizeof(tr)); return NO_ERROR;
} |
ÕâÀïÖ÷ÒªÊÇ´´½¨Ò»¸öbinder_transaction_data£¬³õÆäʼ»¯ºó½«Òª´«ÊäµÄÊý¾ÝдÈëµ½mOut»º³åÇøÖУ¬×îÖÕÕû¸öÊý¾Ý³¤ÕâÑù×Ó

@writeTransactionData|center
Êý¾Ý·â×°Íê³ÉÒÔºó£¬ÎÒÃÇÀ´¿´waitForResponseµÄʵÏÖ
status_t IPCThreadState::
waitForResponse (Parcel *reply, status_t *acquireResult)
{
uint32_t cmd;
int32_t err;
while (1) {
if ((err=talkWithDriver()) < NO_ERROR) break;
...
//´ÓÊä³ö»º³åÇøÈ¡³ö·µ»ØÐÒéÃüÁî
cmd = (uint32_t)mIn.readInt32();
...
}
...
return err;
}
|
ÕâÀï¿ÉÒÔÊÇÒ»¸öËÀÑ»·£¬²»¶ÏµÄͨ¹ýtalkWithDriverÈ¥¸úbinderÇý¶¯Í¨ÐÅ£¬È»ºó´ÓÊä³ö»º³åÇøÖÐÈ¡³ö·µ»ØÐÒéÈ»ºó´¦Àí·µ»ØÐÒ飬ÕâÀïÏȲ»¿´¾ßÌåµÄÐÒé´¦Àí£¬ÏÈÀ´¿´talkWithDriverµÄʵÏÖ
//ĬÈÏdoReceive
= true
status_t IPCThreadState:: talkWithDriver(bool
doReceive)
{
...
binder_write_read bwr; // Is the read buffer empty?
const bool needRead = mIn.dataPosition() >=
mIn.dataSize(); // We don't want to write anything if we are
still reading
// from data left in the input buffer and the
caller
// has requested to read the next data.
const size_t outAvail = (!doReceive || needRead)
? mOut.dataSize() : 0; bwr.write_size = outAvail;
bwr.write_buffer = (uintptr_t)mOut.data(); // This is what we'll read.
if (doReceive && needRead) {
bwr.read_size = mIn.dataCapacity();
bwr.read_buffer = (uintptr_t)mIn.data();
} else {
bwr.read_size = 0;
bwr.read_buffer = 0;
}
...
// Return immediately if there is nothing to
do.
if ((bwr.write_size == 0) && (bwr.read_size
== 0)) return NO_ERROR; bwr.write_consumed = 0;
bwr.read_consumed = 0;
status_t err;
do{
...
//ÕâÀïͨ¹ýioÏëÇý¶¯Ð´ÈëÒ»¸öbinder_write_read½á¹¹Ìå
if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ,
&bwr) >= 0)
err = NO_ERROR;
else
err = -errno;
} while (err == -EINTR);
if (err >= NO_ERROR) {
if (bwr.write_consumed > 0) {
if (bwr.write_consumed < mOut.dataSize())
mOut.remove(0, bwr.write_consumed);
else {
mOut.setDataSize(0);
processPostWriteDerefs();
}
}
if (bwr.read_consumed > 0) {
mIn.setDataSize(bwr.read_consumed);
mIn.setDataPosition(0);
}
...
return NO_ERROR;
} return err;
} |
ÕâÀïÖ÷Ҫͨ¹ýio¿ØÖÆÃüÁîÏòBinderÇý¶¯Ð´ÈëÒ»¸ötypeΪBINDER_WRITE_READ£¬dataΪbinder_write_read£¬ÆäÊä³ö»º³åÇøÎªÇ°ÃæmOutÖÐдÈëµÄÊý¾Ý
½ÓÏÂÀ´µÄ²Ù×÷¾Íתµ½BinderÇý¶¯ÖнøÐÐÁË£¬ÐèÒª¼Çס£¬Clinet½ø³Ì´ËʱִÐе½µÄλÖÃ
/platform/drivers/staging/
android/binder.c
static long binder_ioctl (struct file *filp,
unsigned int cmd,
unsigned long arg)
{
int ret;
struct binder_proc *proc = filp->private_data;
struct binder_thread *thread;
unsigned int size = _IOC_SIZE(cmd);
...
//ÕâÀï¸ù¾Ý½ø³ÌÕÒµ½¶ÔÓ¦µÄthread£¬Èç¹ûûÕÒµ½¾Í´´½¨Ò»¸ö
thread = binder_get_thread(proc);
...
switch (cmd) {
case BINDER_WRITE_READ:
ret = binder_ioctl_write_read (filp, cmd, arg,
thread);
if (ret)
goto err;
break;
...
}
|
BinderÇý¶¯ÖжÔÓ¦µÄbinder_ioctl()»áµ÷Óã¬Ö®ºó»á´¦ÀícmdΪBINDER_WRITE_READµÄ·ÖÖ§£¬Ö®ºó»áµ÷Óõ½binder_ioctl_write_read()
static int
binder_ioctl_write_read (struct file *filp,
unsigned int cmd, unsigned long arg,
struct binder_thread *thread)
{
int ret = 0;
//´ÓÎļþÃèÊö·ûÖÐÈ¡³ö½ø³ÌµØÖ·
struct binder_proc *proc = filp->private_data;
//cmdÐÅÏ¢
unsigned int size = _IOC_SIZE(cmd);
void __user *ubuf = (void __user *)arg;
struct binder_write_read bwr;
//cmdУÑé
if (size != sizeof (struct binder_write_read))
{
ret = -EINVAL;
goto out;
}
//´ÓÓû§¿Õ¼äÖÐÈ¡³öbinder_write_read½á¹¹Ìå
if (copy_from_user(&bwr, ubuf, sizeof(bwr)))
{
ret = -EFAULT;
goto out;
}
...
//Êä³ö»º³åÇøÓÐÊý¾Ý¾Í´¦ÀíÊä³ö»º³åÇø
if (bwr.write_size > 0) {
//ÕâÀïÊÇÕæÕý´¦ÀíÊä³ö»º³åÊý¾ÝµÄfunc
ret = binder_thread_write(proc, thread,
bwr.write_buffer,
bwr.write_size,
&bwr.write_consumed);
trace_binder_write_done(ret);
if (ret < 0) {
bwr.read_consumed = 0;
if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
ret = -EFAULT;
goto out;
}
}
//ÊäÈ뻺³åÇøÓÐÊý¾Ý¾Í´¦ÀíÊäÈ뻺³åÇø
if (bwr.read_size > 0) {
//ÕâÀïÊÇÕæÕý´¦ÀíÊä³ö»º³åÊý¾ÝµÄfunc
ret = binder_thread_read (proc, thread, bwr.read_buffer,
bwr.read_size,
&bwr.read_consumed,
filp->f_flags & O_NONBLOCK);
trace_binder_read_done(ret);
//Èç¹û½ø³Ìtodo¶ÓÀﲻΪ¿Õ£¬ËµÃ÷ÓÐÊÂÎñÕýÔÚ´¦Àí£¬ÐèÒªµÈ´ý´¦Àí
if (!list_empty(&proc->todo))
wake_up_interruptible(&proc->wait);
if (ret < 0) {
if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
ret = -EFAULT;
goto out;
}
}
...
//½«Êý¾Ýcopy»ØÓû§¿Õ¼ä
if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
{
ret = -EFAULT;
goto out;
}
out:
return ret;
} |
Ç°Ãæµ÷ÓÿÉÖª£¬Êä³ö»º³åÇøÊÇÓÐÊý¾Ý£¬ÊäÈ뻺³åÇøÊÇûÓÐÊý¾ÝµÄ£¬ËùÒÔÉÏÃæ·½·¨Ö´ÐÐÁ÷³ÌÓ¦¸ÃÊÇ£¬Ïȵ÷ÓÃbinder_thread_writeÈ¥´¦ÀíÊä³ö»º³åÇø
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)
{
uint32_t cmd;
void __user *buffer = (void __user *) (uintptr_t)binder_buffer;
void __user *ptr = buffer + *consumed;
void __user *end = buffer + size;
while (ptr < end && thread->return_error
== BR_OK) {
//¸ù¾ÝcmdÈ¡³öÏû·ÑµÄÊý¾ÝÆ«ÒÆµØÖ·
if (get_user(cmd, (uint32_t __user *)ptr))
return -EFAULT;
ptr += sizeof(uint32_t);
...
switch (cmd) {
...
case BC_TRANSACTION:
case BC_REPLY: {
struct binder_transaction_data tr;
if (copy_from_user(&tr, ptr, sizeof(tr)))
return -EFAULT;
ptr += sizeof(tr);
binder_transaction(proc, thread, &tr, cmd
== BC_REPLY);
break;
...
}
*consumed = ptr - buffer;
}
return 0;
} |
ÕâÀïÊÇÈ¡³öcmd£¬È»ºó´¦ÀíBC_TRANSACTIONʱºò£¬ÔÙ½²binder_transaction_dataÈ¡³ö£¬Ö®ºó½»ÓÉbinder_transactionÈ¥´¦Àí
binder_transaction±È½Ï³¤£¬ÆäʵÖ÷Òª·ÖΪÈý¸ö²¿·Ö
1.³õʼ»¯Ä¿±êÏ߳̽ø³Ì
2.·â×°·µ»ØÊý¾Ýbinder_transaction_data
3.Ϊbinder_transaction_data·ÖÅäºÏÊʵÄÏß³Ìor½ø³Ì
static void
binder_transaction (struct binder_proc *proc,
struct binder_thread *thread,
struct binder_transaction_data *tr, int reply)
{
struct binder_transaction *t;
struct binder_work *tcomplete;
binder_size_t *offp, *off_end;
binder_size_t off_min;
struct binder_proc *target_proc;
struct binder_thread *target_thread = NULL;
struct binder_node *target_node = NULL;
struct list_head *target_list;
wait_queue_head_t *target_wait;
struct binder_transaction *in_reply_to = NULL;
...
uint32_t return_error;
...
//Èç¹ûÊÇreply×ßif·ÖÖ§£¬·ñÔò×ßelse·ÖÖ§£¬ÕâÀï×ßelse
if (reply) {
...
}else{
//¸ù¾Ý¾ä±úÕÒ¶ÔÓ¦µÄbinder_ref¡¢binder_node
if (tr->target.handle) {
struct binder_ref *ref;
ref = binder_get_ref(proc, tr->target.handle);
...
else{
//handle=0£¬ÔòÐèÒªÕÒÖ¸Ïòservice_managerµÄbinder_node
target_node = binder_context_mgr_node;
...
}
...
//¸ù¾Ýbinder_nodeÕÒµ½¶ÔÓ¦µÄ½ø³Ìbinder_proc£¬ÕâÀïÒ²¾ÍÊÇservice_manager
target_proc = target_node->proc;
...
//Èç¹ûÊÇͬ²½ÇëÇ󣬳¢ÊÔѰÕÒÒ»¸öÔڵȴýÆäËûÊÂÎïÖ´ÐеÄỊ̈߳¬tipsÓÅ»¯µ÷¶È
if (!(tr->flags & TF_ONE_WAY) &&
thread->transaction_stack) {
struct binder_transaction *tmp;
tmp = thread->transaction_stack;
...
//ÕÒµ½Ò»¸öµÈ´ý±ðµÄÊÂÎñÍê³ÉµÄÒÀÀµÏß³Ì
while (tmp) {
if (tmp->from && tmp->from->proc
== target_proc)
target_thread = tmp->from;
tmp = tmp->from_parent;
}
}
}
//ÓпÕÏÐÏ߳̾ÍÊÇÓÿÕÏÐÏ̵߳ĵȴý¶ÓÁУ¬·ñÔòʹÓýø³ÌµÄÊÂÎï¶ÓÁÐ
if (target_thread) {
e->to_thread = target_thread->pid;
target_list = &target_thread->todo;
target_wait = &target_thread->wait;
} else {
target_list = &target_proc->todo;
target_wait = &target_proc->wait;
}
...
//´´½¨binder_transaction½á¹¹Ì壬BINDER_WORK_TRANSACTION
//ÓÃÓÚÏòÄ¿±ê½ø³Ì·¢ËÍÊý¾Ý
t = kzalloc(sizeof(*t), GFP_KERNEL);
...
binder_stats_created(BINDER_STAT_TRANSACTION);
...
//´´½¨binder_work½á¹¹Ìå, BINDER_STAT_TRANSACTION_COMPLETE
//±ãÓÚÏòÔ´½ø³Ì·µ»ØÊý¾Ý´¦Àí½á¹û
tcomplete = kzalloc(sizeof (*tcomplete), GFP_KERNEL);
...
binder_stats_created (BINDER_STAT_TRANSACTION_COMPLETE);
...
//³õʼ»¯t
if (!reply && !(tr->flags & TF_ONE_WAY))
t->from = thread;
else
t->from = NULL;
t->sender_euid = task_euid(proc->tsk);
//Ä¿±ê½ø³Ì
t->to_proc = target_proc;
//Ä¿±êÏß³Ì
t->to_thread = target_thread;
//code ADD_SERVICE_TRANSACTION
t->code = tr->code;
//flag = TF_ACCEPT_FLAGS
t->flags = tr->flags;
//ÓÅÏȼ¶
t->priority = task_nice(current);
...
//»º³åÇø
t->buffer = binder_alloc_buf(target_proc,
tr->data_size,
tr->offsets_size, !reply && (t->flags
& TF_ONE_WAY));
...
t->buffer->allow_user_free = 0;
t->buffer->debug_id = t->debug_id;
t->buffer->transaction = t;
t->buffer->target_node = target_node;
...
//Ϊt·ÖÅäÄں˻º³åÇø
if (target_node)
binder_inc_node(target_node, 1, 0, NULL);
offp = (binder_size_t *)(t->buffer->data
+
ALIGN(tr->data_size, sizeof(void *)));
//Êý¾Ýcopy
if (copy_from_user(t->buffer->data, (const
void __user *)(uintptr_t)
tr->data.ptr.buffer, tr->data_size)) {
...
goto err_copy_data_failed;
}
if (copy_from_user(offp, (const void __user
*)(uintptr_t)
tr->data.ptr.offsets, tr->offsets_size))
{
...
goto err_copy_data_failed;
}
...
//´¦ÀíBinderÇëÇó£¬ÄÚºËÖкܶ඼ÊǵØÖ·ÆðֹλÖòÙ×÷
off_end = (void *)offp + tr->offsets_size;
off_min = 0;
for (; offp < off_end; offp++) {
struct flat_binder_object *fp;
...
//Ç°Ãæ´æ´¢µÄMediaDrmServiceÐÅÏ¢
fp = (struct flat_binder_object *) (t->buffer->data
+ *offp);
off_min = *offp + sizeof (struct flat_binder_object);
switch(fp->type){
case BINDER_TYPE_BINDER:
case BINDER_TYPE_WEAK_BINDER: {
struct binder_ref *ref;
struct binder_node *node =
binder_get_node(proc, fp->binder);
//Èç¹ûÊÇÊ״ξʹ´½¨ÐµÄbinder_node
if (node == NULL) {
node = binder_new_node (proc, fp->binder,
fp->cookie);
...
//É趨Ïß³ÌÓÅÏȼ¶
node->min_priority = fp->flags & FLAT_BINDER_FLAG_PRIORITY_MASK;
//ÉèÖÃÊÇ·ñ½ÓÊÕÎļþÃèÊö·û
node->accept_fds = !!(fp->flags &
FLAT_BINDER_FLAG_ACCEPTS_FDS);
}
...
//Èç¹ûÊÇÊ״ξʹ´½¨¶ÔÓ¦µÄbinder_ref¶ÔÏó
ref = binder_get_ref_for_node(target_proc, node);
if (ref == NULL) {
return_error = BR_FAILED_REPLY;
goto err_binder_get_ref_for_node_failed;
}
//ÐÞ¸Äflat_binder_objec.type
if (fp->type == BINDER_TYPE_BINDER)
fp->type = BINDER_TYPE_HANDLE;
else
fp->type = BINDER_TYPE_WEAK_HANDLE;
//ÉèÖþä±ú
fp->handle = ref->desc;
//Ôö¼Óbinder_refµÄÒýÓüÆÊý
binder_inc_ref(ref, fp->type == BINDER_TYPE_HANDLE,
&thread->todo);
...
}break;
...
}
}
//·ÖÅäÊÂÎñtµÄÒª½øÈëÄǸöÕ»
if (reply) {
...
binder_pop_transaction (target_thread, in_reply_to);
} else if (!(t->flags & TF_ONE_WAY))
{
...
t->need_reply = 1;
t->from_parent = thread->transaction_stack;
thread->transaction_stack = t;
} else {
...
if (target_node->has_async_transaction) {
target_list = &target_node->async_todo;
target_wait = NULL;
} else
target_node->has_async_transaction = 1;
}
//½«binder_transaction_dataÖ¸ÕëtµÄÀàÐÍÐÞ¸ÄΪBINDER_WORK_TRANSACTION
t->work.type = BINDER_WORK_TRANSACTION;
//Ìí¼Óµ½target_list¶ÓÁÐβ²¿
list_add_tail(&t->work.entry, target_list);
//½«binder_workÖ¸Õëtcomplete.typeÖÃΪ BINDER_WORK_TRANSACTION_COMPLETE
tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;
list_add_tail (&tcomplete->entry, &thread->todo);
//ÕâÀïÓÐÁ½¸öÖ´ÐзÖÖ§
//1.´¦ÀíÀàÐÍΪBINDER_WORK_TRANSACTIONµÄ binder_transaction_data
//2.´¦ÀíÀàÐÍΪBINDER_WORK_TRANSACTION_COMPLETE µÄbinder_work
if (target_wait)
wake_up_interruptible(target_wait);
return;
...
} |
¾¹ýÉÏÃæfuncÒÔºó£¬binderÇý¶¯ÖоͻáΪMediaDrmService´´½¨¶ÔÓ¦µÄbinder_node²¢¼ÓÈëµ½Õû¸öBinderʵÌå¶ÔÏóµÄºìºÚÊ÷ÖУ¬½Ó×Å»á·Ö±ðÏòClient½ø³Ì¡¢ServiceManager·¢ËÍÒ»¸öBINDER_WORK_TRANSACTION_COMPLETEµÄbinder_work¼°BINDER_WORK_TRANSACTIONµÄbinder_transaction
ÖÁ´Ë£¬Ô´Ïß³Ìthread¡¢target_proc»òÕßtarget_thread»á²¢·¢µÄÈ¥Ö´Ðи÷×Ôtodo¶ÓÁÐÖеÄÈÎÎñ
ÏÈÀ´¿´Ô´Ïß³Ì,»Øµ½binder_ioctl_write_readÖУ¬½ÓÏÂÀ´Òª´¦ÀíÊäÈ뻺³åÇø£¬¶ÔÓ¦µÄµ÷ÓÃbinder_thread_read
static int
binder_thread_read (struct binder_proc *proc,
struct binder_thread *thread,
binder_uintptr_t binder_buffer, size_t size,
binder_size_t *consumed, int non_block)
{
void __user *buffer = (void __user *) (uintptr_t)binder_buffer;
void __user *ptr = buffer + *consumed;
void __user *end = buffer + size; int ret = 0;
int wait_for_proc_work;
...
//Ï̻߳½ÐÑ
while (1) {
uint32_t cmd;
struct binder_transaction_data tr;
struct binder_work *w;
struct binder_transaction *t = NULL;
//¼ì²é¹¤×÷¶ÓÁУ¬²¢½«´ý´¦ÀíÏֵ¸øw
if (!list_empty(&thread->todo)) {
w = list_first_entry(&thread-> todo,
struct binder_work,
entry);
} else if (!list_empty(&proc->todo) &&
wait_for_proc_work) {
w = list_first_entry (&proc->todo, struct
binder_work,
entry);
} else {
/* no data added */
if (ptr - buffer == 4 &&
!(thread->looper & BINDER_LOOPER_STATE_NEED_RETURN))
goto retry;
break;
}
switch (w->type) {
...
case BINDER_WORK_TRANSACTION_COMPLETE: {
cmd = BR_TRANSACTION_COMPLETE;
if (put_user(cmd, (uint32_t __user *)ptr))
return -EFAULT;
ptr += sizeof(uint32_t);
binder_stat_br(proc, thread, cmd);
...
//ɾ³ýbinder_work£¬²¢ÊÍ·Å×ÊÔ´
list_del(&w->entry);
kfree(w);
binder_stats_deleted (BINDER_STAT_TRANSACTION_COMPLETE);
} break;
}
done:
*consumed = ptr - buffer;
...
return 0;
} |
ÕâÀï·µ»ØÒ»¸öBR_TRANSACTION_COMPLETEÐÒ飬֮ºó»á¾¹ýһЩÁе÷ÓÃ»á»Øµ½IPCThreadState#waitForResponseÖÐ
status_t IPCThreadState::waitForResponse
(Parcel *reply, status_t *acquireResult)
{
...
uint32_t cmd;
int32_t err; while (1) {
...
cmd = (uint32_t)mIn.readInt32();
...
switch (cmd) {
case BR_TRANSACTION_COMPLETE:
if (!reply && !acquireResult) goto finish;
break;
}
...
}
finish:
...
return error;
} |
IPCThreadState::waitForResponse¶ÔÓÚBR_TRANSACTION_COMPLETE´¦Àí±È½Ï¼òµ¥£¬¾ÍÖ±½Ó·µ»ØÁË
ÎÒÃÇÀ´¿´ÏÂtarget_proc¼´ServiceManagerÊÇÔõô½ÓÊÕ´¦ÀíBINDER_WORK_TRANSACTIONÀàÐ͵Äbinder_transactionµÄ£¬¼ÙÉèServiceManager֮ǰûÓÐͨÐÅ£¬ÄÇôËû¾ÍÔÚBinderÇý¶¯ÖÐÒ»Ö±µÈ´ýÊÂÎñµÄµ½À´£¬ÏÖÔÚÓÐÊÂÎñÁËÄÇô¶ÔÓ¦µÄ¾Í»áµ÷ÓÃbinder_read_thread
static int
binder_thread_read (struct binder_proc *proc,
struct binder_thread *thread,
binder_uintptr_t binder_buffer, size_t size,
binder_size_t *consumed, int non_block)
{
void __user *buffer = (void __user *) (uintptr_t)binder_buffer;
void __user *ptr = buffer + *consumed;
void __user *end = buffer + size;
...
//Ï̻߳½ÐÑ
while (1) {
uint32_t cmd;
struct binder_transaction_data tr;
struct binder_work *w;
struct binder_transaction *t = NULL; //¼ì²é¹¤×÷¶ÓÁУ¬²¢½«´ý´¦ÀíÏֵ¸øw
if (!list_empty(&thread->todo)) {
w = list_first_entry(&thread->todo, struct
binder_work,
entry);
} else if (!list_empty (&proc->todo) &&
wait_for_proc_work) {
w = list_first_entry (&proc->todo, struct
binder_work,
entry);
} else {
/* no data added */
if (ptr - buffer == 4 &&
!(thread->looper & BINDER_LOOPER_STATE_NEED_RETURN))
goto retry;
break;
}
...
switch (w->type) {
case BINDER_WORK_TRANSACTION: {
t = container_of (w, struct binder_transaction,
work);
} break;
...
}
//·µ»ØÐÒéµÄ´¦Àí£¬ÏÖÔÚtarget_nodeÖ¸ÏòµÄÊÇbinder_context_mgr_node
if (t->buffer->target_node) {
struct binder_node *target_node = t->buffer->target_node; tr.target.ptr = target_node->ptr;
tr.cookie = target_node->cookie;
//±£´æÔ±¾µÄÏß³ÌÓÅÏȼ¶£¬±ãÓÚºóÐø»Ö¸´
t->saved_priority = task_nice(current);
//ÐÞ¸ÄbinderÇý¶¯ÖжÔÓ¦procµÄÏß³ÌÓÅÏȼ¶£¨Ä£ÄâClient½ø³ÌµÄÏß³ÌÓÅÏȼ¶£©
if (t->priority < target_node->min_priority
&&
!(t->flags & TF_ONE_WAY))
binder_set_nice(t->priority);
else if (!(t->flags & TF_ONE_WAY) ||
t->saved_priority > target_node->min_priority)
binder_set_nice(target_node->min_priority);
cmd = BR_TRANSACTION;
} else {
...
}
//¿½±´codeÓëflags£¬
//×¢²á·þÎñ¹ý³ÌÖÐÕâÀïÊÇ ADD_SERVICE_TRANSACTION¡¢TF_ACCEPT_FDS
tr.code = t->code;
tr.flags = t->flags;
if (t->from) {
struct task_struct *sender = t->from->proc->tsk;
tr.sender_pid = task_tgid_nr_ns(sender,
task_active_pid_ns(current));
} else {
...
}
//BinderÇý¶¯³ÌÐò·ÖÅ䏸½ø³ÌµÄÄں˻º³åÇøÍ¬Ê±£¬
//Ó³ÉäÁËÓû§µÄÄں˵ØÖ·¡¢Óû§¿Õ¼äµØÖ·
tr.data_size = t->buffer->data_size;
tr.offsets_size = t->buffer->offsets_size;
tr.data.ptr.buffer = (binder_uintptr_t)(
(uintptr_t)t->buffer->data +
proc->user_buffer_offset);
//Ö±½Ó²Ù×÷offsets
tr.data.ptr.offsets = tr.data.ptr.buffer +
ALIGN(t->buffer->data_size,
sizeof(void *)); //Ìṩһ¸ö·µ»ØÐÒéÊý¾ÝµÄ»º³åÇø
if (put_user(cmd, (uint32_t __user *)ptr))
return -EFAULT;
ptr += sizeof(uint32_t);
if (copy_to_user(ptr, &tr, sizeof(tr)))
return -EFAULT;
ptr += sizeof(tr);
...
list_del(&t->work.entry);
t->buffer->allow_user_free = 1;
//cmd = BR_TRANSACTION && ²»ÊÇÕýÔÚ´¦ÀíÒ첽ͨÐÅÇëÇó
//¾ÍÐèÒªµÈ´ý¸Ãͬ²½½ø³ÌͨÐÅÍêÒÔºóÔÙ½øÐÐÏÂÒ»²½µÄ²Ù×÷
if (cmd == BR_TRANSACTION && !(t->flags
& TF_ONE_WAY)) {
t->to_parent = thread->transaction_stack;
t->to_thread = thread;
thread->transaction_stack = t;
} else {
t->buffer->transaction = NULL;
kfree(t);
binder_stats_deleted(BINDER_STAT_TRANSACTION);
}
break;
}
...
return 0
} |
ÕâÀïʵ¼ÊÉÏÊÇ·µ»ØÒ»¸öBR_TRANSACTIONÐÒ飬²¢ÇÒ½«Ö®Ç°Í¨¹ýbinder_transaction´«ÊäµÄÊý¾Ý·â×°µ½binder_transaction_dataÖУ¬ÓÉÓÚÔÚservice_managerÆô¶¯ÖУ¬½øÈëbinder_loopʱºòÖ¸¶¨µÄº¯ÊýÒýÓÃΪsvcmgr_handler,binder_loopÖлáÑ»·Í¨¹ýioctl¿ØÖÆÃüÁîÈ¥ÓëÄں˽»»¥Êý¾Ý£¬binder_parseÓÃÓÚ½âÎöÊý¾Ý
platform/frameworks/native/cmds
/servicemanager/binder.c
int binder_parse (struct binder_state *bs, struct
binder_io *bio,
uintptr_t ptr, size_t size, binder_handler func)
{
int r = 1;
uintptr_t end = ptr + (uintptr_t) size;
while (ptr < end) {
uint32_t cmd = *(uint32_t *) ptr;
ptr += sizeof(uint32_t);
...
case BR_TRANSACTION: {
struct binder_transaction_data *txn =
(struct binder_transaction_data *) ptr;
...
if (func) {
unsigned rdata[256/4];
struct binder_io msg;
struct binder_io reply;
int res;
bio_init(&reply, rdata, sizeof(rdata), 4);
bio_init_from_txn(&msg, txn);
//µ÷ÓÃsvcmgr_handlerÈ¥´¦Àí
res = func(bs, txn, &msg, &reply);
if (txn->flags & TF_ONE_WAY) {
binder_free_buffer(bs, txn->data.ptr.buffer);
} else {
//·µ»Ø×¢²áµÄ½á¹û¸øbinderÇý¶¯
binder_send_reply(bs, &reply,
txn->data.ptr.buffer, res);
}
}
break;
}
}
|
ÕâÆäÖÐÓÐÈý¸ö½á¹¹Ìåbinder_ioÖ÷Òª´æ´¢Êý¾Ý´«Ê䣬¶¨ÒåÈçÏÂ:
struct binder_io
{
char *data; /* pointer to read/write from */
binder_size_t *offs; /* array of offsets */
size_t data_avail; /* bytes available in data
buffer */
size_t offs_avail; /* entries available in offsets
array */ char *data0; /* start of data buffer */
binder_size_t *offs0; /* start of offsets buffer
*/
uint32_t flags;
uint32_t unused;
}; |
binder_parseÖÐÏÈͨ¹ýbio_initÈ¥³õʼ»¯reply£¬È»ºóͨ¹ýbio_init_from_txnÈ¥³õʼ»¯msg£¬¾ÍÊÇÊý¾Ý¶ÔÆëµÄ¹ý³Ì¼°flagÉèÖã¬ÕâÀï²»ÔÙϸÊö
ÎÒÃÇÖØµã¹Ø×¢func,Ò²¾ÍÊÇsvcmgr_handler£¬ÏÈÀ´»Ø¹ËÇ°ÃæÊý¾ÝÄÇÕÅͼ

@writeTransactionData|center
½ÓÏÂÀ´ÔÙÀ´¿´svvmgr_handlerµÄʵÏÖ
uint16_t svcmgr_id[]
= {
'a','n','d','r','o', 'i','d','.','o','s','.',
'I','S','e', 'r','v','i', 'c','e','M', 'a','n','a','g','e','r'
};
...
int svcmgr_handler(struct binder_state *bs,
struct binder_transaction_data *txn,
struct binder_io *msg,
struct binder_io *reply)
{
struct svcinfo *si;
uint16_t *s;
size_t len;
uint32_t handle;
uint32_t strict_policy;
int allow_isolated;
...
strict_policy = bio_get_uint32(msg);
s = bio_get_string16(msg, &len);
...
//svcmgr_idУÑé,ÊÇ·ñΪ¡°android.os.IServiceManager¡±
if ((len != (sizeof(svcmgr_id) / 2)) ||
memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {
fprintf(stderr,"invalid id %s\n",
str8(s, len));
return -1;
}
...
switch(txn->code) {
...
//ö¾ÙÖµ¶ÔÓ¦ADD_SERVICE_TRANSACTION
case SVC_MGR_ADD_SERVICE:
s = bio_get_string16(msg, &len);
if (s == NULL) {
return -1;
}
//È¡³öbinder_ÒýÓöÔÏóµÄ¾ä±úÖµ
handle = bio_get_ref(msg);
allow_isolated = bio_get_uint32(msg) ? 1 : 0;
dumpsys_priority = bio_get_uint32(msg);
if (do_add_service(bs, s, len, handle,
txn->sender_euid, allow_isolated, dumpsys_priority,
txn->sender_pid))
return -1;
break;
}
...
bio_put_uint32(reply, 0);
return 0;
}
|
´ÓmsgÖÐÈ¡³ö¶ÔÓ¦µÄServiceµÄhandle¡¢name£¬È»ºóµ÷ÓÃdo_add__serviceÈ¥Ö´ÐкóÐøµÄ²Ù×÷
¿´do_add_service֮ǰÎÒÃÇÏÈÀ´¿´Ò»¸ö½á¹¹Ìåsvcinfo
struct svcinfo
{
//Ö¸ÏòÏÂÒ»¸öÒýÓÃ
struct svcinfo *next;
//¾ä±úÖµ
uint32_t handle;
//ËÀÍö´úÀí֪ͨ
struct binder_death death;
int allow_isolated;
uint32_t dumpsys_priority;
size_t len;
//·þÎñÃû³Æ
uint16_t name[0];
}; |
ÔÚServiceManagerÖÐÿһ¸ö·þÎñ¶ÔÓ¦Ò»¸ösvcinfo½á¹¹Ìå
½ÓÏÂÀ´ÎÒÃÇ¿´do_add_serviceµÄʵÏÖ
int do_add_service
(struct binder_state *bs, const uint16_t *s,
size_t len, uint32_t handle, uid_t uid, int
allow_isolated,
uint32_t dumpsys_priority, pid_t spid) {
//´æ´¢Òª×¢²áµÄ·þÎñÐÅÏ¢
struct svcinfo *si;
...
//¼ì²éȨÏÞ
if (!svc_can_register(s, len, spid, uid)) {
ALOGE("add_service('%s',%x) uid=%d - PERMISSION
DENIED\n",
str8(s, len), handle, uid);
return -1;
}
/ÏÈÈ¥ÕÒÕâ¸ö·þÎñ
si = find_svc(s, len);
if (si) {
if (si->handle) {
...
svcinfo_death(bs, si);
}
si->handle = handle;
} else {
//×¢²á·þÎñ
si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));
...
si->handle = handle;
si->len = len;
memcpy(si->name, s, (len + 1) * sizeof(uint16_t));
si->name[len] = '\0';
si->death.func = (void*) svcinfo_death;
si->death.ptr = si;
si->allow_isolated = allow_isolated;
si->dumpsys_priority = dumpsys_priority;
//°ó¶¨µ½svclistÖÐ
si->next = svclist;
svclist = si;
} //Ôö¼ÓÒýÓ㬱ÜÃâ±»Ïú»Ù
binder_acquire(bs, handle);
//°ó¶¨ËÀÍö֪ͨ
binder_link_to_death (bs, handle, &si->death);
return 0;
} |
ÕâÀïÏȼì²éServiceÊÇ·ñÓÐ×¢²áȨÏÞ(²»Í¬°æ±¾Äں˼ӹ̵÷Óò»Í¬£¬¸ÐÐËȤ¿ÉÒԲ鿴selinux)£¬È»ºóÏÈÈ¥³¢ÊÔ²éÕÒÕâ¸ö·þÎñ´æÔÚ²»£¬Èç¹û²»´æÔھͷÖÅäÒ»¸öеÄstruct
svcinfo£¬²¢½«Æä¹Òµ½svclistÖУ¬Óɴ˿ɼûÔÚservice_managerÖÐÊÇά»¤ÕâÒ»¸öËùÓÐService×é¼þÐÅÏ¢µÄsvclistµÄ
»Øµ½binder_parseÖÐ,½ÓÏÂÀ´»áµ÷ÓÃbinder_send_replyÏòBinderÇý¶¯·¢ËÍÒ»¸öBC_REPLY
void binder_send_reply (struct binder_state *bs,
struct binder_io *reply,
binder_uintptr_t buffer_to_free,
int status)
{
//ÄäÃû½á¹¹Ìå
struct {
uint32_t cmd_free;
binder_uintptr_t buffer;
uint32_t cmd_reply;
struct binder_transaction_data txn;
} __attribute__((packed)) data; data.cmd_free = BC_FREE_BUFFER;
data.buffer = buffer_to_free;
data.cmd_reply = BC_REPLY;
data.txn.target.ptr = 0;
data.txn.cookie = 0;
data.txn.code = 0;
if (status) {
//ͨÐÅÖвúÉúÁË´íÎó
data.txn.flags = TF_STATUS_CODE;
data.txn.data_size = sizeof(int);
data.txn.offsets_size = 0;
data.txn.data.ptr.buffer = (uintptr_t)&status;
data.txn.data.ptr.offsets = 0;
} else {
//³É¹¦´¦ÀíµÄÒ»´ÎͨÐÅÇëÇó
data.txn.flags = 0;
data.txn.data_size = reply->data - reply->data0;
data.txn.offsets_size = ((char*) reply->offs)
- ((char*) reply->offs0);
data.txn.data.ptr.buffer = (uintptr_t)reply->data0;
data.txn.data.ptr.offsets = (uintptr_t)reply->offs0;
}
//ÏòBinderÇý¶¯Ð´ÈëÊý¾Ý
binder_write(bs, &data, sizeof(data));
} |
ÕâÀï»á½«½ø³ÌͨÐŽá¹ûдÈëµ½ÄäÃûstruct dataÖУ¬È»ºóµ÷ÓÃbinder_writeÈ¥ÏòÄÚºËдÈëBC_FREE_BUFFER\BC_REPLYÃüÁîÐÒé
int binder_write (struct
binder_state *bs, void *data, size_t len)
{
struct binder_write_read bwr;
int res; bwr.write_size = len;
bwr.write_consumed = 0;
bwr.write_buffer = (uintptr_t) data;
bwr.read_size = 0;
bwr.read_consumed = 0;
bwr.read_buffer = 0;
res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
if (res < 0) {
fprintf (stderr,"binder_write: ioctl failed
(%s)\n",
strerror(errno));
}
return res;
} |
binder_writeʵ¼ÊÉÏ»¹ÊÇͨ¹ýIO¿ØÖÆÃüÁîдÈëÒ»¸öbinder_write_read½á¹¹Ì壬עÒâÕâ¸ö½á¹¹ÌåÊäÈ뻺³åÇøÊÇûÓÐÊý¾ÝµÄ£¬Ò²¾ÍÊÇ˵²»ÐèÒª´¦Àí·µ»ØÐÒé
ÂÔ¹ý¸÷ÖÖµ÷ÓÃÎÒÃÇÀ´¿´ÄÚºËÖÐbinder_thread_write¶ÔÓÚBC_FREE_BUFFER\BC_REPLYµÄ´¦Àí
platform/drivers/staging/android/binder.c
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)
{
uint32_t cmd;
void __user *buffer = (void __user *) (uintptr_t)binder_buffer;
void __user *ptr = buffer + *consumed;
void __user *end = buffer + size; while (ptr < end && thread-> return_error
== BR_OK) {
if (get_user(cmd, (uint32_t __user *)ptr))
return -EFAULT;
ptr += sizeof(uint32_t);
...
switch (cmd) {
...
case BC_TRANSACTION:
case BC_REPLY: {
struct binder_transaction_data tr; if (copy_from_user(&tr, ptr, sizeof(tr)))
return -EFAULT;
ptr += sizeof(tr);
binder_transaction(proc, thread, &tr, cmd
== BC_REPLY);
break;
}
...
} |
BC_FREE_BUFFERÖ÷ÒªÊÇ×öһЩ×ÊÔ´ÊͷŵIJÙ×÷£¬¸ÐÐËȤ¿ÉÒÔ×Ô¼º¿´ÕâÀï²»ÔÙϸ¿´
ÖØµã¿´BC_REPLY,²é¿´binder_transactionµÄ´¦Àí
static void binder_transaction(struct
binder_proc *proc,
struct binder_thread *thread,
struct binder_transaction_data *tr, int reply)
{
...
struct binder_transaction *t;
struct binder_work *tcomplete;
binder_size_t *offp, *off_end;
binder_size_t off_min;
struct binder_proc *target_proc;
struct binder_thread *target_thread = NULL;
struct binder_node *target_node = NULL;
struct list_head *target_list;
wait_queue_head_t *target_wait;
struct binder_transaction *in_reply_to = NULL;
struct binder_transaction_log_entry *e;
uint32_t return_error;
...
if (reply) {
//ѰÕÒÇëÇóͨÐŵÄthread
//´Ó֮ǰµÄthreadÖÐÈ¡³öͨÐŵÄbinder_transaction_data
in_reply_to = thread->transaction_stack;
if (in_reply_to == NULL) {
...
return_error = BR_FAILED_REPLY;
goto err_empty_call_stack;
}
//»Ö¸´Ïß³ÌÓÅÏȼ¶
binder_set_nice(in_reply_to->saved_priority);
if (in_reply_to->to_thread != thread) {
...
return_error = BR_FAILED_REPLY;
in_reply_to = NULL;
goto err_bad_call_stack;
}
thread->transaction_stack = in_reply_to->to_parent;
target_thread = in_reply_to->from;
if (target_thread == NULL) {
return_error = BR_DEAD_REPLY;
goto err_dead_binder;
}
if (target_thread->transaction_stack != in_reply_to)
{
...
return_error = BR_FAILED_REPLY;
in_reply_to = NULL;
target_thread = NULL;
goto err_dead_binder;
}
//Ä¿±ê½ø³Ì
target_proc = target_thread->proc;
}else{
...
}
//ÓпÕÏÐÏ߳̾ÍÊÇÓÿռäÏ̵߳ĵȴý¶ÓÁУ¬·ñÔòʹÓýø³ÌµÄ
if (target_thread) {
...
target_list = &target_thread->todo;
target_wait = &target_thread->wait;
} else {
...
}
...
//´´½¨binder_transaction½á¹¹Ì壬BINDER_WORK_TRANSACTION
t = kzalloc(sizeof(*t), GFP_KERNEL);
...
//´´½¨binder_work½á¹¹Ìå,BINDER_STAT_TRANSACTION_COMPLETE
tcomplete = kzalloc(sizeof(*tcomplete), GFP_KERNEL);
...
//·ÖÅäÊÂÎñtµÄÒª½øÈëÄǸöÕ»
if (reply) {
BUG_ON(t->buffer->async_transaction !=
0);
//½«ÊÂÎñµ¯³ötodoÕ»
binder_pop_transaction(target_thread, in_reply_to);
} else if (!(t->flags & TF_ONE_WAY))
{
...
}else{
...
}
//½«binder_transaction_dataÖ¸ÕëtµÄÀàÐÍÐÞ¸ÄΪBINDER_WORK_TRANSACTION
t->work.type = BINDER_WORK_TRANSACTION;
//Ìí¼Óµ½target_list¶ÓÁÐβ²¿
list_add_tail(&t->work.entry, target_list);
//½«binder_workÖ¸Õëtcomplete.typeÖÃΪBINDER_WORK_TRANSACTION_COMPLETE
tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;
list_add_tail(&tcomplete->entry, &thread->todo);
//ÕâÀïÓÐÁ½¸öÖ´ÐзÖÖ§
//1.´¦ÀíÀàÐÍΪBINDER_WORK_TRANSACTIONµÄbinder_transaction_data
//2.´¦ÀíÀàÐÍΪBINDER_WORK_TRANSACTION_COMPLETEµÄbinder_work
if (target_wait)
wake_up_interruptible(target_wait);
return;
...
}
|
ÕâÀï¸úÖ»°®È¥Äĵ÷Óò»Í¬µÄµØ·½ÔÚÓÚ×ßµÄÊÇif·ÖÖ§£¬ÐèÒª²éÕÒµ½Ö®Ç°Í¨ÐŵÄÄ¿±êÏ̼߳°½ø³Ì£¬È»ºó½«ÉÏ´ÎͨÐŵÄbinder_transactionµ¯Õ»£¬È»ºó»ØÏë֮ǰͨÐŵĽø³Ì·¢ËÍÒ»¸ötypeΪBINDER_WORK_TRANSACTIONµÄbinder_work£¬Ö®Ç°ÄǸö½ø³Ì¶ÔÓ¦µÄbinder_thread_read´¦ÀíÈçÏÂ:
static int binder_thread_read(struct
binder_proc *proc,
struct binder_thread *thread,
binder_uintptr_t binder_buffer, size_t size,
binder_size_t *consumed, int non_block)
{
void __user *buffer = (void __user *)(uintptr_t)binder_buffer;
void __user *ptr = buffer + *consumed;
void __user *end = buffer + size; int ret = 0;
...
//Ï̻߳½ÐÑ
while (1) {
uint32_t cmd;
struct binder_transaction_data tr;
struct binder_work *w;
struct binder_transaction *t = NULL;
//¼ì²é¹¤×÷¶ÓÁУ¬²¢½«´ý´¦ÀíÏֵ¸øw
if (!list_empty(&thread->todo)) {
w = list_first_entry(&thread->todo, struct
binder_work,
entry);
} else if (!list_empty(&proc->todo) &&
wait_for_proc_work) {
w = list_first_entry(&proc->todo, struct
binder_work,
entry);
} else {
...
}
...
switch (w->type) {
case BINDER_WORK_TRANSACTION: {
t = container_of(w, struct binder_transaction,
work);
} break;
...
}
//·µ»ØÐÒéµÄ´¦Àí£¬ÏÖÔÚtarget_nodeÖ¸ÏòµÄÊÇbinder_context_mgr_node
if (t->buffer->target_node) {
...
}else{
tr.target.ptr = 0;
tr.cookie = 0;
cmd = BR_REPLY;
}
//BinderÇý¶¯³ÌÐò·ÖÅ䏸½ø³ÌµÄÄں˻º³åÇøÍ¬Ê±£¬Ó³ÉäÁËÓû§µÄÄں˵ØÖ·¡¢Óû§¿Õ¼äµØÖ·
tr.data_size = t->buffer->data_size;
tr.offsets_size = t->buffer->offsets_size;
tr.data.ptr.buffer = (binder_uintptr_t)(
(uintptr_t)t->buffer->data +
proc->user_buffer_offset);
//Ö±½Ó²Ù×÷offsets
tr.data.ptr.offsets = tr.data.ptr.buffer +
ALIGN(t->buffer->data_size,
sizeof(void *)); //Ìṩһ¸ö·µ»ØÐÒéÊý¾ÝµÄ»º³åÇø
if (put_user(cmd, (uint32_t __user *)ptr))
return -EFAULT;
ptr += sizeof(uint32_t);
if (copy_to_user(ptr, &tr, sizeof(tr)))
return -EFAULT;
ptr += sizeof(tr);
...
//cmd = BR_TRANSACTION && ²»ÊÇÕýÔÚ´¦ÀíÒ첽ͨÐÅÇëÇó
//¾ÍÐèÒªµÈ´ý¸Ãͬ²½½ø³ÌͨÐÅÍêÒÔºóÔÙ½øÐÐÏÂÒ»²½µÄ²Ù×÷
if (cmd == BR_TRANSACTION && !(t->flags
& TF_ONE_WAY)) {
...
} else {
t->buffer->transaction = NULL;
kfree(t);
binder_stats_deleted(BINDER_STAT_TRANSACTION);
}
break;
}
...
} |
ÕâÀï¾Í»á·â×°Ò»¸öBR_REPLY·µ»ØÐÒ飬Ȼºó·µ»Øµ½IPCThreadState::waitForResponseÖÐ
½ÓÏÂÀ´¿´IPCThreadState::waitForResponse¶ÔÓÚBR_REPLYµÄ´¦Àí
status_t IPCThreadState::waitForResponse(Parcel
*reply, status_t *acquireResult)
{
uint32_t cmd;
...
while (1) {
...
cmd = (uint32_t)mIn.readInt32();
...
switch (cmd) {
case BR_REPLY:
{
binder_transaction_data tr;
err = mIn.read(&tr, sizeof(tr));
...
if (reply) {
if ((tr.flags & TF_STATUS_CODE) == 0) {
//ÖØÖÃParcel¶ÔÏóÄÚ²¿Êý¾Ý»º³åÇø£¬²¢Ö¸¶¨Êͷź¯ÊýΪfreeBuffer
reply->ipcSetDataReference(
reinterpret_cast
<const uint8_t*>(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast
<const binder_size_t*>(tr.data.ptr.offsets),
tr.offsets_size/sizeof(binder_size_t),
freeBuffer, this);
} else {
...
} else {
...
}
}
goto finish;
...
}
}
...
}
|
ʵ¼ÊÉÏ»áµ÷ÓÃreply->ipcSetDataReferenceÈ¥ÖØÖÃÊý¾Ý»º³åÇø£¬ÕâÀï²»ÔÙϸÊö£¬Õû¸öService×¢²á¾Í´óÖÂÍê³ÉÁË£¬ºóÐø»¹ÓÐBinderÏß³ÌµÄÆô¶¯¸ÐÐËȤ¿ÉÒÔ×ÔÐв鿴
ServiceManager²éÕÒ·þÎñ

@ServiceµÄ²éÕÒÁ÷³Ì|center
ÍêÕûµÄͨÐÅÁ÷³Ì

@ÍêÕûµÄͨÐÅÁ÷³Ì
|