Äú¿ÉÒÔ¾èÖú£¬Ö§³ÖÎÒÃǵĹ«ÒæÊÂÒµ¡£

1Ôª 10Ôª 50Ôª





ÈÏÖ¤Â룺  ÑéÖ¤Âë,¿´²»Çå³þ?Çëµã»÷Ë¢ÐÂÑéÖ¤Âë ±ØÌî



  ÇóÖª ÎÄÕ ÎÄ¿â Lib ÊÓÆµ iPerson ¿Î³Ì ÈÏÖ¤ ×Éѯ ¹¤¾ß ½²×ù Model Center   Code  
»áÔ±   
   
 
     
   
 ¶©ÔÄ
  ¾èÖú
Android Binder
 
×÷ÕߣºÒ»Ö»ÅÖWaÅ£
  6952  次浏览      27
2020-12-25 
 
±à¼­ÍƼö:
±¾ÎÄÖ÷Òª½éÉÜÁË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

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

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

 

 
   
6952 ´Îä¯ÀÀ       27
Ïà¹ØÎÄÕÂ

Éî¶È½âÎö£ºÇåÀíÀôúÂë
ÈçºÎ±àд³öÓµ±§±ä»¯µÄ´úÂë
ÖØ¹¹-ʹ´úÂë¸ü¼ò½àÓÅÃÀ
ÍŶÓÏîÄ¿¿ª·¢"±àÂë¹æ·¶"ϵÁÐÎÄÕÂ
Ïà¹ØÎĵµ

ÖØ¹¹-¸ÄÉÆ¼ÈÓдúÂëµÄÉè¼Æ
Èí¼þÖØ¹¹v2
´úÂëÕû½àÖ®µÀ
¸ßÖÊÁ¿±à³Ì¹æ·¶
Ïà¹Ø¿Î³Ì

»ùÓÚHTML5¿Í»§¶Ë¡¢Web¶ËµÄÓ¦Óÿª·¢
HTML 5+CSS ¿ª·¢
ǶÈëʽC¸ßÖÊÁ¿±à³Ì
C++¸ß¼¶±à³Ì
×îл¼Æ»®
DeepSeekÔÚÈí¼þ²âÊÔÓ¦ÓÃʵ¼ù 4-12[ÔÚÏß]
DeepSeek´óÄ£ÐÍÓ¦Óÿª·¢Êµ¼ù 4-19[ÔÚÏß]
UAF¼Ü¹¹ÌåϵÓëʵ¼ù 4-11[±±¾©]
AIÖÇÄÜ»¯Èí¼þ²âÊÔ·½·¨Óëʵ¼ù 5-23[ÉϺ£]
»ùÓÚ UML ºÍEA½øÐзÖÎöÉè¼Æ 4-26[±±¾©]
ÒµÎñ¼Ü¹¹Éè¼ÆÓ뽨ģ 4-18[±±¾©]
 
×îÐÂÎÄÕÂ
Flutter-Ä㻹ÔÚÀÄÓÃStatefulWidgetÂð
ÒÆ¶¯APP°²È«²âÊÔÒªµã
ÉîÈëdz³ö Kotlin Э³Ì
iOS ×é¼þ»¯ ¡ª¡ª ·ÓÉÉè¼ÆË¼Â··ÖÎö
ÒÆ¶¯¶Ë¿çƽ̨¿ª·¢µÄÉî¶È½âÎö
×îпγÌ
Android¸ß¼¶Òƶ¯Ó¦ÓóÌÐò¿ª·¢
AndroidÓ¦Óÿª·¢
Androidϵͳ¿ª·¢
AndroidÓ¦Óø߼¶¿ª·¢
ÒÆ¶¯»¥ÁªÍøÓ¦Óÿª·¢£¨iOS£¬Android£¬HTML5)
³É¹¦°¸Àý
±±¾© iOS¿ª·¢¼¼ÊõÉîÈëÑо¿
ijÆóÒµ Android¸ß¼¶Òƶ¯Ó¦ÓóÌÐò¿ª·¢
ÖÐÌå²Ê Android²úÆ·¼¶²âÊÔ
ÒÆ¶¯Í¨ÐÅ ÒÆ¶¯»¥ÁªÍøÓ¦Óÿª·¢Ô­Àí
ijµçÁ¦ÐÐ android¿ª·¢Æ½Ì¨×î¼Ñ