BinderµÄʵÏÖÊDZȽϸ´Ôӵģ¬ÏëÒªÍêȫŪÃ÷°×ÊÇÔõôһ»ØÊ£¬²¢²»ÊÇÒ»¼þÈÝÒ×µÄÊÂÇé¡£
ÕâÀïÃæÇ£Éæµ½ºÃ¼¸¸ö²ã´Î£¬Ã¿Ò»²ã¶¼ÓÐһЩģ¿éºÍ»úÖÆÐèÒªÀí½â¡£Õⲿ·ÖÄÚÈÝÔ¤¼Æ»á·ÖΪÈýƪÎÄÕÂÀ´½²½â¡£±¾ÎÄÊǵÚһƪ£¬Ê×ÏÈ»á¶ÔÕû¸öBinder»úÖÆ×öÒ»¸ö¼Ü¹¹ÐԵĽ²½â£¬È»ºó»á½«´ó²¿·Ö¾«Á¦ÓÃÀ´½²½âBinder»úÖÆÖÐ×îºËÐĵIJ¿·Ö£ºBinderÇý¶¯µÄʵÏÖ¡£
Binder»úÖÆ¼ò½é
BinderÔ´×ÔBe Inc¹«Ë¾¿ª·¢µÄOpenBinder¿ò¼Ü£¬ºóÀ´¸Ã¿ò¼Ü×ªÒÆµÄPalm Inc£¬ÓÉDianne
HackbornÖ÷µ¼¿ª·¢¡£OpenBinderµÄÄں˲¿·ÖÒѾºÏÈëLinux Kernel 3.19¡£
Android BinderÊÇÔÚOpneBinderÉϵĶ¨ÖÆÊµÏÖ¡£ÔÏȵÄOpenBinder¿ò¼ÜÏÖÔÚÒѾ²»ÔÙ¼ÌÐø¿ª·¢£¬¿ÉÒÔ˵AndroidÉϵÄBinderÈÃÔÏȵÄOpneBinderµÃµ½ÁËÖØÉú¡£
BinderÊÇAndroidϵͳÖдóÁ¿Ê¹ÓõÄIPC£¨Inter-process communication£¬½ø³Ì¼äͨѶ£©»úÖÆ¡£ÎÞÂÛÊÇÓ¦ÓóÌÐò¶Ôϵͳ·þÎñµÄÇëÇ󣬻¹ÊÇÓ¦ÓóÌÐò×ÔÉíÌṩ¶ÔÍâ·þÎñ£¬¶¼ÐèҪʹÓõ½Binder¡£
Òò´Ë£¬Binder»úÖÆÔÚAndroidϵͳÖеĵØÎ»·Ç³£ÖØÒª£¬¿ÉÒÔ˵£¬Àí½âBinderÊÇÀí½âAndroidϵͳµÄ¾ø¶Ô±ØÒªÇ°Ìá¡£
ÔÚUnix/Linux»·¾³Ï£¬´«Í³µÄIPC»úÖÆ°üÀ¨£º
1.¹ÜµÀ
2.ÏûÏ¢¶ÓÁÐ
3.¹²ÏíÄÚ´æ
4.ÐźÅÁ¿
5.Socket
ÓÉÓÚÆª·ùËùÏÞ£¬±¾ÎIJ»»á¶ÔÕâЩIPC»úÖÆ×ö½²½â£¬ÓÐÐËȤµÄ¶ÁÕß¿ÉÒÔ²ÎÔÄ¡¶UNIXÍøÂç±à³Ì ¾í2£º½ø³Ì¼äͨÐÅ¡·¡£
AndroidϵͳÖжÔÓÚ´«Í³µÄIPCʹÓýÏÉÙ£¨µ«Ò²ÓÐʹÓã¬ÀýÈ磺ÔÚÇëÇóZygote fork½ø³ÌµÄʱºòʹÓõÄÊÇSocket
IPC£©£¬´ó²¿·Ö³¡¾°ÏÂʹÓõÄIPC¶¼ÊÇBinder¡£
BinderÏà½ÏÓÚ´«Í³IPCÀ´Ëµ¸üÊʺÏÓÚAndroidϵͳ£¬¾ßÌåÔÒòµÄ°üÀ¨ÈçÏÂÈýµã£º
1.Binder±¾ÉíÊÇC/S¼Ü¹¹µÄ£¬ÕâÒ»µã¸ü·ûºÏAndroidϵͳµÄ¼Ü¹¹
2.ÐÔÄÜÉϸüÓÐÓÅÊÆ£º¹ÜµÀ£¬ÏûÏ¢¶ÓÁУ¬SocketµÄͨѶ¶¼ÐèÒªÁ½´ÎÊý¾Ý¿½±´£¬¶øBinderÖ»ÐèÒªÒ»´Î¡£ÒªÖªµÀ£¬¶ÔÓÚϵͳµ×²ãµÄIPCÐÎʽ£¬ÉÙÒ»´ÎÊý¾Ý¿½±´£¬¶ÔÕûÌåÐÔÄܵÄÓ°ÏìÊǷdz£Ö®´óµÄ
3.°²È«ÐÔ¸üºÃ£º´«Í³IPCÐÎʽ£¬ÎÞ·¨µÃµ½¶Ô·½µÄÉí·Ý±êʶ£¨UID/GID)£¬¶øÔÚʹÓÃBinder
IPCʱ£¬ÕâЩÉí·Ý±êʾÊǸúËæµ÷Óùý³Ì¶ø×Ô¶¯´«µÝµÄ¡£Server¶ËºÜÈÝÒ׾ͿÉÒÔÖªµÀClient¶ËµÄÉí·Ý£¬·Ç³£±ãÓÚ×ö°²È«¼ì²é
ÕûÌå¼Ü¹¹
BinderÕûÌå¼Ü¹¹ÈçÏÂËùʾ£º

´ÓͼÖпÉÒÔ¿´³ö£¬BinderµÄʵÏÖ·ÖΪÕâô¼¸²ã£º
1.Framework²ã
2.Java²¿·Ö
3.JNI²¿·Ö
4.C++²¿·Ö
5.Çý¶¯²ã
Çý¶¯²ãλÓÚLinuxÄÚºËÖУ¬ËüÌṩÁË×îµ×²ãµÄÊý¾Ý´«µÝ£¬¶ÔÏó±êʶ£¬Ï̹߳ÜÀí£¬µ÷Óùý³Ì¿ØÖƵȹ¦ÄÜ¡£Çý¶¯²ãÊÇÕû¸öBinder»úÖÆµÄºËÐÄ¡£
Framework²ãÒÔÇý¶¯²ãΪ»ù´¡£¬ÌṩÁËÓ¦Óÿª·¢µÄ»ù´¡ÉèÊ©¡£
Framework²ã¼È°üº¬ÁËC++²¿·ÖµÄʵÏÖ£¬Ò²°üº¬ÁËJava²¿·ÖµÄʵÏÖ¡£ÎªÁËÄܽ«C++µÄʵÏÖ¸´Óõ½Java¶Ë£¬Öмäͨ¹ýJNI½øÐÐÏνӡ£
¿ª·¢Õß¿ÉÒÔÔÚFrameworkÖ®ÉÏÀûÓÃBinderÌṩµÄ»úÖÆÀ´½øÐоßÌåµÄÒµÎñÂß¼¿ª·¢¡£Æäʵ²»½ö½öÊǵÚÈý·½¿ª·¢Õߣ¬AndroidϵͳÖб¾ÉíÒ²°üº¬Á˺ܶàϵͳ·þÎñ¶¼ÊÇ»ùÓÚBinder¿ò¼Ü¿ª·¢µÄ¡£
¼ÈÈ»ÊÇ¡°½ø³Ì¼ä¡±Í¨Ñ¶¾ÍÖÁÉÙÇ£Éæµ½Á½¸ö½ø³Ì£¬Binder¿ò¼ÜÊǵäÐ͵ÄC/S¼Ü¹¹¡£ÔÚÏÂÎÄÖУ¬ÎÒÃǰѷþÎñµÄÇëÇó·½³ÆÖ®ÎªClient£¬·þÎñµÄʵÏÖ·½³ÆÖ®ÎªServer¡£
Client¶ÔÓÚServerµÄÇëÇó»á¾ÓÉBinder¿ò¼ÜÓÉÉÏÖÁÏ´«µÝµ½Äں˵ÄBinderÇý¶¯ÖУ¬ÇëÇóÖаüº¬ÁËClient½«Òªµ÷ÓõÄÃüÁîºÍ²ÎÊý¡£ÇëÇóµ½ÁËBinderÇý¶¯Ö®ºó£¬ÔÚÈ·¶¨ÁË·þÎñµÄÌṩ·½Ö®ºó£¬»áÔÙ´ÓÏÂÖÁÉϽ«ÇëÇ󴫵ݸø¾ßÌåµÄ·þÎñ¡£Õû¸öµ÷Óùý³ÌÈçÏÂͼËùʾ£º
¶ÔÍøÂçÐÒéÓÐËùÁ˽âµÄ¶ÁÕ߻ᷢÏÖ£¬Õâ¸öÊý¾ÝµÄ´«µÝ¹ý³ÌºÍÍøÂçÐÒéÊÇÈç´ËµÄÏàËÆ¡£
³õʶServiceManager
Ç°ÃæÒѾÌáµ½£¬Ê¹ÓÃBinder¿ò¼ÜµÄ¼È°üÀ¨ÏµÍ³·þÎñ£¬Ò²°üÀ¨µÚÈý·½Ó¦Óá£Òò´Ë£¬ÔÚͬһʱ¿Ì£¬ÏµÍ³ÖлáÓдóÁ¿µÄServerͬʱ´æÔÚ¡£ÄÇô£¬ClientÔÚÇëÇóServerµÄʱºò£¬ÊÇÈç¹ûÈ·¶¨ÇëÇó·¢Ë͸øÄÄÒ»¸öServerµÄÄØ£¿
Õâ¸öÎÊÌ⣬¾ÍºÍÎÒÃÇÏÖʵÉú»îÖÐÈçºÎÕÒµ½Ò»¸ö¹«Ë¾/É̳¡£¬ÈçºÎÈ·¶¨Ò»¸öÈË/Ò»Á¾³µÒ»Ñù£¬½â¾öµÄ·½·¨¾ÍÊÇ£ºÃ¿¸öÄ¿±ê¶ÔÏó¶¼ÐèÒªÒ»¸öΨһµÄ±êʶ¡£²¢ÇÒ£¬ÐèÒªÓÐÒ»¸ö×éÖ¯À´¹ÜÀíÕâ¸öΨһµÄ±êʶ¡£
¶øBinder¿ò¼ÜÖиºÔð¹ÜÀíÕâ¸ö±êʶµÄ¾ÍÊÇServiceManager¡£ServiceManager¶ÔÓÚBinder
ServerµÄ¹ÜÀí¾ÍºÃ±È³µ¹ÜËù¶ÔÓÚ³µÅƺÅÂëµÄµÄ¹ÜÀí£¬ÅɳöËù¶ÔÓÚÉí·ÝÖ¤ºÅÂëµÄ¹ÜÀí£ºÃ¿¸ö¹«¿ª¶ÔÍâÌṩ·þÎñµÄServer¶¼ÐèҪע²áµ½ServiceManagerÖУ¨Í¨¹ýaddService£©£¬×¢²áµÄʱºòÐèÒªÖ¸¶¨Ò»¸öΨһµÄid£¨Õâ¸öidÆäʵ¾ÍÊÇÒ»¸ö×Ö·û´®£©¡£
ClientÒª¶ÔServer·¢³öÇëÇ󣬾ͱØÐëÖªµÀ·þÎñ¶ËµÄid¡£ClientÐèÒªÏȸù¾ÝServerµÄidͨ¹ýServerManagerÄõ½ServerµÄ±êʾ£¨Í¨¹ýgetService£©£¬È»ºóͨ¹ýÕâ¸ö±êʾÓëServer½øÐÐͨÐÅ¡£
Õû¸ö¹ý³ÌÈçÏÂͼËùʾ£º

Èç¹ûÉÏÃæÕâЩ½éÉÜÒѾÈÃÄãһͷÎíË®£¬Çë²»Òª¹ý·Öµ£ÐÄ£¬ÏÂÃæ»áÏêϸ½²½âÕâÆäÖеÄϸ½Ú¡£
ÏÂÎÄ»áÒÔ×Ô϶øÉϵķ½Ê½À´½²½âBinder¿ò¼Ü¡£×Ô϶øÉÏδ±ØÊÇ×îºÃµÄ·½·¨£¬Ã¿¸öÈ˵Ä˼¿¼·½Ê½²»Ò»Ñù£¬Èç¹ûÄã¸üϲ»¶×ÔÉ϶øÏµÄÀí½â£¬ÄãÒ²°´ÕâÑùµÄ˳ÐòÀ´ÔĶÁ¡£
¶ÔÓڴ󲿷ÖÈËÀ´Ëµ£¬ÎÒÃÇ¿ÉÄÜÐèÒª·´¸´µÄ²éÔIJÅÄÜÍêÈ«Àí½â¡£
Çý¶¯²ã
Ô´Âë·¾¶£¨Õⲿ·Ö´úÂë²»ÔÚAOSPÖУ¬¶øÊÇλÓÚLinuxÄں˴úÂëÖУ©£º
/kernel/drivers/android/binder.c /kernel/include/uapi/linux/android/binder.h
|
»òÕß
/kernel/drivers/staging/android/binder.c /kernel/drivers/staging/android/uapi/binder.h
|
Binder»úÖÆµÄʵÏÖÖУ¬×îºËÐĵľÍÊÇBinderÇý¶¯¡£ BinderÊÇÒ»¸ömiscellaneousÀàÐ͵ÄÇý¶¯£¬±¾Éí²»¶ÔÓ¦ÈκÎÓ²¼þ£¬ËùÓеIJÙ×÷¶¼ÔÚÈí¼þ²ã¡£
binder_initº¯Êý¸ºÔðBinderÇý¶¯µÄ³õʼ»¯¹¤×÷£¬¸Ãº¯ÊýÖд󲿷ִúÂëÊÇÔÚͨ¹ýdebugfs_create_dirºÍdebugfs_create_fileº¯Êý´´½¨debugfs¶ÔÓ¦µÄÎļþ¡£
Èç¹ûÄÚºËÔÚ±àÒëʱ´ò¿ªÁËdebugfs£¬Ôòͨ¹ýadb shellÁ¬ÉÏÉ豸֮ºó£¬¿ÉÒÔÔÚÉ豸µÄÕâ¸ö·¾¶ÕÒµ½debugfs¶ÔÓ¦µÄÎļþ£º/sys/kernel/debug¡£BinderÇý¶¯Öд´½¨µÄdebugÎļþÈçÏÂËùʾ£º
# ls -l /sys/kernel/debug/binder/ total 0 -r--r--r-- 1 root root 0 1970-01-01 00:00 failed_transaction_log drwxr-xr-x 2 root root 0 1970-05-09 01:19 proc -r--r--r-- 1 root root 0 1970-01-01 00:00 state -r--r--r-- 1 root root 0 1970-01-01 00:00 stats -r--r--r-- 1 root root 0 1970-01-01 00:00 transaction_log -r--r--r-- 1 root root 0 1970-01-01 00:00 transactions
|
ÕâЩÎļþÆäʵ¶¼ÔÚÄÚ´æÖеģ¬ÊµÊ±µÄ·´Ó¦Á˵±Ç°BinderµÄʹÓÃÇé¿ö£¬ÔÚʵ¼ÊµÄ¿ª·¢¹ý³ÌÖУ¬ÕâЩÐÅÏ¢¿ÉÒÔ°ïæ·ÖÎöÎÊÌâ¡£ÀýÈ磬¿ÉÒÔͨ¹ý²é¿´/sys/kernel/debug/binder/procĿ¼À´È·¶¨ÄÄЩ½ø³ÌÕýÔÚʹÓÃBinder£¬Í¨¹ý²é¿´transaction_logºÍtransactionsÎļþÀ´È·¶¨BinderͨÐŵÄÊý¾Ý¡£
binder_initº¯ÊýÖÐ×îÖ÷ÒªµÄ¹¤×÷ÆäʵÏÂÃæÕâÐУº
static struct miscdevice binder_miscdev = { .minor = MISC_DYNAMIC_MINOR, .name = "binder", .fops = &binder_fops };
|
¸ÃÐдúÂëÕæÕýÏòÄÚºËÖÐ×¢²áÁËBinderÉ豸¡£binder_miscdevµÄ¶¨ÒåÈçÏ£º
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, };
|
ÕâÀïÖ¸¶¨ÁËBinderÉ豸µÄÃû³ÆÊÇ¡°binder¡±¡£ÕâÑù£¬ÔÚÓû§¿Õ¼ä±ã¿ÉÒÔͨ¹ý¶Ô/dev/binderÎļþ½øÐвÙ×÷À´Ê¹ÓÃBinder¡£
binder_miscdevͬʱҲָ¶¨Á˸ÃÉ豸µÄfops¡£fopsÊÇÁíÍâÒ»¸ö½á¹¹Ì壬Õâ¸ö½á¹¹Öаüº¬ÁËһϵÁеĺ¯ÊýÖ¸Õ룬Æä¶¨ÒåÈçÏ£º
static int binder_open(struct inode *nodp, struct file *filp) { struct binder_proc *proc;
// ´´½¨½ø³Ì¶ÔÓ¦µÄbinder_proc¶ÔÏó
proc = kzalloc(sizeof(*proc), GFP_KERNEL);
if (proc == NULL)
return -ENOMEM;
get_task_struct(current);
proc->tsk = current;
// ³õʼ»¯binder_proc
INIT_LIST_HEAD(&proc->todo);
init_waitqueue_head(&proc->wait);
proc->default_priority = task_nice(current);
// Ëø±£»¤
binder_lock(__func__);
binder_stats_created(BINDER_STAT_PROC);
// Ìí¼Óµ½È«¾ÖÁбíbinder_procsÖÐ
hlist_add_head(&proc->proc_node, &binder_procs);
proc->pid = current->group_leader->pid;
INIT_LIST_HEAD(&proc->delivered_death);
filp->private_data = proc;
binder_unlock(__func__);
return 0;
} |
ÕâÀï³ýÁËownerÖ®Í⣬ÿһ¸ö×ֶζ¼ÊÇÒ»¸öº¯ÊýÖ¸Õ룬ÕâЩº¯ÊýÖ¸Õë¶ÔÓ¦ÁËÓû§¿Õ¼äÔÚʹÓÃBinderÉ豸ʱµÄ²Ù×÷¡£ÀýÈ磺binder_poll¶ÔÓ¦ÁËpollϵͳµ÷ÓõĴ¦Àí£¬binder_mmap¶ÔÓ¦ÁËmmapϵͳµ÷ÓõĴ¦Àí£¬ÆäËûÀàͬ¡£
ÕâÆäÖУ¬ÓÐÈý¸öº¯ÊýÓÈÎªÖØÒª£¬ËüÃÇÊÇ£ºbinder_open£¬binder_mmapºÍbinder_ioctl¡£
ÕâÊÇÒòΪ£¬ÐèҪʹÓÃBinderµÄ½ø³Ì£¬¼¸ºõ×ÜÊÇÏÈͨ¹ýbinder_open´ò¿ªBinderÉ豸£¬È»ºóͨ¹ýbinder_mmap½øÐÐÄÚ´æÓ³Éä¡£
ÔÚÕâÖ®ºó£¬Í¨¹ýbinder_ioctlÀ´½øÐÐʵ¼ÊµÄ²Ù×÷¡£Client¶ÔÓÚServer¶ËµÄÇëÇó£¬ÒÔ¼°Server¶ÔÓÚClientÇëÇó½á¹ûµÄ·µ»Ø£¬¶¼ÊÇͨ¹ýioctlÍê³ÉµÄ¡£
ÕâÀïÌáµ½µÄÁ÷³ÌÈçÏÂͼËùʾ£º

Ö÷Òª½á¹¹
BinderÇý¶¯Öаüº¬Á˺ܶàµÄ½á¹¹Ì塣ΪÁ˱ãÓÚÏÂÎĽ²½â£¬ÕâÀïÎÒÃÇÏȶÔÕâЩ½á¹¹Ìå×öһЩ½éÉÜ¡£
Çý¶¯ÖеĽṹÌå¿ÉÒÔ·ÖΪÁ½Àࣺ
Ò»ÀàÊÇÓëÓû§¿Õ¼ä¹²Óõģ¬ÕâЩ½á¹¹ÌåÔÚBinderͨÐÅÐÒé¹ý³ÌÖлáÓõ½¡£Òò´Ë£¬ÕâЩ½á¹¹Ì嶨ÒåÔÚbinder.hÖУ¬°üÀ¨£º

ÕâÆäÖУ¬binder_write_readºÍbinder_transaction_dataÕâÁ½¸ö½á¹¹Ìå×îÎªÖØÒª£¬ËüÃÇ´æ´¢ÁËIPCµ÷Óùý³ÌÖеÄÊý¾Ý¡£¹ØÓÚÕâÒ»µã£¬ÎÒÃÇÔÚÏÂÎÄÖлὲ½â¡£
BinderÇý¶¯ÖУ¬»¹ÓÐÒ»Àà½á¹¹ÌåÊǽö½öBinderÇý¶¯ÄÚ²¿ÊµÏÖ¹ý³ÌÖÐÐèÒªµÄ£¬ËüÃǶ¨ÒåÔÚbinder.cÖУ¬°üÀ¨£º

ÕâÀïÐèÒª¶ÁÕß¹Ø×¢µÄ½á¹¹ÌåÒѾÓüӴÖ×öÁ˱ê×¢¡£
BinderÐÒé
BinderÐÒé¿ÉÒÔ·ÖΪ¿ØÖÆÐÒéºÍÇý¶¯ÐÒéÁ½Àà¡£
¿ØÖÆÐÒéÊǽø³Ìͨ¹ýioctl(¡°/dev/binder¡±) ÓëBinderÉ豸½øÐÐͨѶµÄÐÒ飬¸ÃÐÒé°üº¬ÒÔϼ¸ÖÖÃüÁ

BinderµÄÇý¶¯ÐÒéÃèÊöÁ˶ÔÓÚBinderÇý¶¯µÄ¾ßÌåʹÓùý³Ì¡£Çý¶¯ÐÒéÓÖ¿ÉÒÔ·ÖΪÁ½Àࣺ
Ò»ÀàÊÇbinder_driver_command_protocol£¬ÃèÊöÁ˽ø³Ì·¢Ë͸øBinderÇý¶¯µÄÃüÁî
Ò»ÀàÊÇbinder_driver_return_protocol£¬ÃèÊöÁËBinderÇý¶¯·¢Ë͸ø½ø³ÌµÄÃüÁî
binder_driver_command_protocol¹²°üº¬17¸öÃüÁ·Ö±ðÊÇ£º

binder_driver_return_protocol¹²°üº¬18¸öÃüÁ·Ö±ðÊÇ£º

µ¥¶À¿´ÉÏÃæµÄÐÒé¿ÉÄܺÜÄÑÀí½â£¬ÕâÀïÎÒÃÇÒÔÒ»´ÎBinderÇëÇó¹ý³ÌÀ´Ïêϸ¿´Ò»ÏÂBinderÐÒéÊÇÈçºÎͨÐŵģ¬¾Í±È½ÏºÃÀí½âÁË¡£
Õâ·ùͼµÄ˵Ã÷ÈçÏ£º

BinderÊÇC/S¼Ü¹¹µÄ£¬Í¨ÐŹý³ÌÇ£Éæµ½£ºClient£¬ServerÒÔ¼°BinderÇý¶¯Èý¸ö½ÇÉ«
Client¶ÔÓÚServerµÄÇëÇóÒÔ¼°Server¶ÔÓÚClient»Ø¸´¶¼ÐèҪͨ¹ýBinderÇý¶¯À´ÖÐתÊý¾Ý
BC_XXXÃüÁîÊǽø³Ì·¢Ë͸øÇý¶¯µÄÃüÁî
BR_XXXÃüÁîÊÇÇý¶¯·¢Ë͸ø½ø³ÌµÄÃüÁî
Õû¸öͨÐŹý³ÌÓÉBinderÇý¶¯¿ØÖÆ
ÕâÀïÔÙ²¹³ä˵Ã÷һϣ¬Í¨¹ýÉÏÃæµÄBinderÐÒéµÄ˵Ã÷ÖÐÎÒÃÇ¿´µ½£¬BinderÐÒéµÄͨÐŹý³ÌÖУ¬²»½ö½öÊÇ·¢ËÍÇëÇóºÍ½ÓÊÜÊý¾ÝÕâЩÃüÁͬʱ°üÀ¨Á˶ÔÓÚÒýÓüÆÊýµÄ¹ÜÀíºÍ¶ÔÓÚËÀÍö֪ͨµÄ¹ÜÀí£¨¸æÖªÒ»·½£¬Í¨Ñ¶µÄÁíÍâÒ»·½ÒѾËÀÍö£©µÈ¹¦ÄÜ¡£
ÕâЩ¹¦ÄܵÄͨÐŹý³ÌºÍÉÏÃæÕâ·ùͼÊÇÀàËÆµÄ£ºÒ»·½·¢ËÍBC_XXX£¬È»ºóÓÉÇý¶¯¿ØÖÆÍ¨ÐŹý³Ì£¬½Ó×Å·¢ËͶÔÓ¦µÄBR_XXXÃüÁî¸øÍ¨ÐŵÄÁíÍâÒ»·½¡£ÒòΪÕâÖÖÏàËÆÐÔ£¬¶ÔÓÚÕâЩÄÚÈݾͲ»ÔÙ׸ÊöÁË¡£
ÔÚÓÐÁËÉÏÃæÕâЩ±³¾°ÖªÊ¶½éÉÜÖ®ºó£¬ÎÒÃǾͿÉÒÔ½øÈëµ½BinderÇý¶¯µÄÄÚ²¿ÊµÏÖÖÐÀ´Ò»Ì½¾¿¾¹ÁË¡£
PS£ºÉÏÃæ½éÉܵÄÕâЩ½á¹¹ÌåºÍÐÒ飬ÒòΪÄÚÈݽ϶࣬³õ´Î¿´Íê¼Ç²»×¡ÊǺÜÕý³£µÄ£¬ÔÚÏÂÎÄÏêϸ½²½âµÄʱºò£¬»Ø¹ýÍ·À´¶ÔÕÕÕâЩ±í¸ñÀ´Àí½âÊDZȽÏÓаïÖúµÄ¡£
´ò¿ªBinderÉ豸
Èκνø³ÌÔÚʹÓÃBinder֮ǰ£¬¶¼ÐèÒªÏÈͨ¹ýopen("/dev/binder")´ò¿ªBinderÉ豸¡£ÉÏÎÄÒѾÌáµ½£¬Óû§¿Õ¼äµÄopenϵͳµ÷ÓöÔÓ¦ÁËÇý¶¯ÖеÄbinder_openº¯Êý¡£ÔÚÕâ¸öº¯Êý£¬BinderÇý¶¯»áΪµ÷ÓõĽø³Ì×öһЩ³õʼ»¯¹¤×÷¡£binder_openº¯Êý´úÂëÈçÏÂËùʾ£º
static int binder_open(struct inode *nodp, struct file *filp) { struct binder_proc *proc;
// ´´½¨½ø³Ì¶ÔÓ¦µÄbinder_proc¶ÔÏó
proc = kzalloc(sizeof(*proc), GFP_KERNEL);
if (proc == NULL)
return -ENOMEM;
get_task_struct(current);
proc->tsk = current;
// ³õʼ»¯binder_proc
INIT_LIST_HEAD(&proc->todo);
init_waitqueue_head(&proc->wait);
proc->default_priority = task_nice(current);
// Ëø±£»¤
binder_lock(__func__);
binder_stats_created(BINDER_STAT_PROC);
// Ìí¼Óµ½È«¾ÖÁбíbinder_procsÖÐ
hlist_add_head(&proc->proc_node, &binder_procs);
proc->pid = current->group_leader->pid;
INIT_LIST_HEAD(&proc->delivered_death);
filp->private_data = proc;
binder_unlock(__func__);
return 0;
} |
ÔÚBinderÇý¶¯ÖУ¬Í¨¹ýbinder_procs¼Ç¼ÁËËùÓÐʹÓÃBinderµÄ½ø³Ì¡£Ã¿¸ö³õ´Î´ò¿ªBinderÉ豸µÄ½ø³Ì¶¼»á±»Ìí¼Óµ½Õâ¸öÁбíÖеġ£
ÁíÍ⣬Çë¶ÁÕ߻عËÒ»ÏÂÉÏÎĽéÉܵÄBinderÇý¶¯Öеö¹Ø¼ü½á¹¹Ì壺
1.binder_proc
2.binder_node
3.binder_thread
4.binder_ref
5.binder_buffer
ÔÚʵÏÖ¹ý³ÌÖУ¬ÎªÁ˱ãÓÚ²éÕÒ£¬ÕâЩ½á¹¹Ì廥ÏàÖ®¼ä¶¼ÁôÓÐ×ֶδ洢¹ØÁªµÄ½á¹¹¡£
ÏÂÃæÕâ·ùͼÃèÊöÁËÕâÀï˵µ½µÄÕâЩÄÚÈÝ£º

ÄÚ´æÓ³É䣨mmap£©
ÔÚ´ò¿ªBinderÉ豸֮ºó£¬½ø³Ì»¹»áͨ¹ýmmap½øÐÐÄÚ´æÓ³Éä¡£mmapµÄ×÷ÓÃÓÐÈçÏÂÁ½¸ö£º
ÉêÇëÒ»¿éÄÚ´æ¿Õ¼ä£¬ÓÃÀ´½ÓÊÕBinderͨÐŹý³ÌÖеÄÊý¾Ý
¶ÔÕâ¿éÄÚ´æ½øÐеØÖ·Ó³É䣬ÒԱ㽫À´·ÃÎÊ
binder_mmapº¯Êý¶ÔÓ¦ÁËmmapϵͳµ÷ÓõĴ¦Àí£¬Õâ¸öº¯ÊýÒ²ÊÇBinderÇý¶¯µÄ¾«»ªËùÔÚ£¨ÕâÀï˵µÄbinder_mmapº¯ÊýÒ²°üÀ¨ÆäÄÚ²¿µ÷ÓõÄbinder_update_page_rangeº¯Êý£¬¼ûÏÂÎÄ£©¡£
ǰÎÄÎÒÃÇ˵µ½£¬Ê¹ÓÃBinder»úÖÆ£¬Êý¾ÝÖ»ÐèÒª¾ÀúÒ»´Î¿½±´¾Í¿ÉÒÔÁË£¬ÆäÔÀí¾ÍÔÚÕâ¸öº¯ÊýÖС£
binder_mmapÕâ¸öº¯ÊýÖУ¬»áÉêÇëÒ»¿éÎïÀíÄڴ棬ȻºóÔÚÓû§¿Õ¼äºÍÄں˿ռäͬʱ¶ÔÓ¦µ½Õâ¿éÄÚ´æÉÏ¡£ÔÚÕâÖ®ºó£¬µ±ÓÐClientÒª·¢ËÍÊý¾Ý¸øServerµÄʱºò£¬Ö»ÐèÒ»´Î£¬½«Client·¢Ë͹ýÀ´µÄÊý¾Ý¿½±´µ½Server¶ËµÄÄں˿ռäÖ¸¶¨µÄÄÚ´æµØÖ·¼´¿É£¬ÓÉÓÚÕâ¸öÄÚ´æµØÖ·ÔÚ·þÎñ¶ËÒѾͬʱӳÉäµ½Óû§¿Õ¼ä£¬Òò´ËÎÞÐèÔÙ×öÒ»´Î¸´ÖÆ£¬Server¼´¿ÉÖ±½Ó·ÃÎÊ£¬Õû¸ö¹ý³ÌÈçÏÂͼËùʾ£º

Õâ·ùͼµÄ˵Ã÷ÈçÏ£º
ServerÔÚÆô¶¯Ö®ºó£¬µ÷ÓöÔ/dev/binderÉ豸µ÷ÓÃmmap
ÄÚºËÖеÄbinder_mmapº¯Êý½øÐжÔÓ¦µÄ´¦Àí£ºÉêÇëÒ»¿éÎïÀíÄڴ棬ȻºóÔÚÓû§¿Õ¼äºÍÄں˿ռäͬʱ½øÐÐÓ³Éä
Clientͨ¹ýBINDER_WRITE_READÃüÁî·¢ËÍÇëÇó£¬Õâ¸öÇëÇó½«Ïȵ½Çý¶¯ÖУ¬Í¬Ê±ÐèÒª½«Êý¾Ý´ÓClient½ø³ÌµÄÓû§¿Õ¼ä¿½±´µ½Äں˿ռä
Çý¶¯Í¨¹ýBR_TRANSACTION֪ͨServerÓÐÈË·¢³öÇëÇó£¬Server½øÐд¦Àí¡£ÓÉÓÚÕâ¿éÄÚ´æÒ²ÔÚÓû§¿Õ¼ä½øÐÐÁËÓ³É䣬Òò´ËServer½ø³ÌµÄ´úÂë¿ÉÒÔÖ±½Ó·ÃÎÊ
Á˽âÔÀíÖ®ºó£¬ÎÒÃÇÔÙÀ´¿´Ò»ÏÂBinderÇý¶¯µÄÏà¹ØÔ´Âë¡£Õâ¶Î´úÂëÓÐÁ½¸öº¯Êý£º
binder_mmapº¯Êý¶ÔÓ¦ÁËmmapµÄϵͳµ÷ÓõĴ¦Àí
binder_update_page_rangeº¯ÊýÕæÕýʵÏÖÁËÄÚ´æ·ÖÅäºÍµØÖ·Ó³Éä
static int binder_mmap(struct file *filp, struct vm_area_struct *vma) { int ret;
struct vm_struct *area;
struct binder_proc *proc = filp->private_data;
const char *failure_string;
struct binder_buffer *buffer;
...
// ÔÚÄں˿ռä»ñȡһ¿éµØÖ··¶Î§
area = get_vm_area(vma->vm_end - vma->vm_start,
VM_IOREMAP);
if (area == NULL) {
ret = -ENOMEM;
failure_string = "get_vm_area";
goto err_get_vm_area_failed;
}
proc->buffer = area->addr;
// ¼Ç¼Äں˿ռäÓëÓû§¿Õ¼äµÄµØÖ·Æ«ÒÆ
proc->user_buffer_offset = vma->vm_start
- (uintptr_t)proc->buffer;
mutex_unlock(&binder_mmap_lock);
...
proc->pages = kzalloc(sizeof(proc->pages[0])
* ((vma->vm_end - vma->vm_start) / PAGE_SIZE),
GFP_KERNEL);
if (proc->pages == NULL) {
ret = -ENOMEM;
failure_string = "alloc page array";
goto err_alloc_pages_failed;
}
proc->buffer_size = vma->vm_end - vma->vm_start;
vma->vm_ops = &binder_vm_ops;
vma->vm_private_data = proc;
/* binder_update_page_range assumes preemption
is disabled */
preempt_disable();
// ͨ¹ýÏÂÃæÕâ¸öº¯ÊýÕæÕýÍê³ÉÄÚ´æµÄÉêÇëºÍµØÖ·µÄÓ³Éä
// ³õ´ÎʹÓã¬ÏÈÉêÇëÒ»¸öPAGE_SIZE´óСµÄÄÚ´æ
ret = binder_update_page_range(proc, 1, proc->buffer,
proc->buffer + PAGE_SIZE, vma);
...
}
static int binder_update_page_range(struct binder_proc
*proc, int allocate,
void *start, void *end,
struct vm_area_struct *vma)
{
void *page_addr;
unsigned long user_page_addr;
struct vm_struct tmp_area;
struct page **page;
struct mm_struct *mm;
...
for (page_addr = start; page_addr < end;
page_addr += PAGE_SIZE) {
int ret;
struct page **page_array_ptr;
page = &proc->pages[(page_addr - proc->buffer)
/ PAGE_SIZE];
BUG_ON(*page);
// ÕæÕý½øÐÐÄÚ´æµÄ·ÖÅä
*page = alloc_page(GFP_KERNEL | __GFP_HIGHMEM
| __GFP_ZERO);
if (*page == NULL) {
pr_err("%d: binder_alloc_buf failed for page
at %p\n",
proc->pid, page_addr);
goto err_alloc_page_failed;
}
tmp_area.addr = page_addr;
tmp_area.size = PAGE_SIZE + PAGE_SIZE /* guard
page? */;
page_array_ptr = page;
// ÔÚÄÚºË¿Õ¼ä½øÐÐÄÚ´æÓ³Éä
ret = map_vm_area(&tmp_area, PAGE_KERNEL,
&page_array_ptr);
if (ret) {
pr_err("%d: binder_alloc_buf failed to map
page at %p in kernel\n",
proc->pid, page_addr);
goto err_map_kernel_failed;
}
user_page_addr =
(uintptr_t)page_addr + proc->user_buffer_offset;
// ÔÚÓû§¿Õ¼ä½øÐÐÄÚ´æÓ³Éä
ret = vm_insert_page(vma, user_page_addr, page[0]);
if (ret) {
pr_err("%d: binder_alloc_buf failed to map
page at %lx in userspace\n",
proc->pid, user_page_addr);
goto err_vm_insert_page_failed;
}
/* vm_insert_page does not seem to increment the
refcount */
}
if (mm) {
up_write(&mm->mmap_sem);
mmput(mm);
}
preempt_disable();
return 0;
...
|
ÔÚ¿ª·¢¹ý³ÌÖУ¬ÎÒÃÇ¿ÉÒÔͨ¹ýprocfs¿´µ½½ø³ÌÓ³ÉäµÄÕâ¿éÄÚ´æ¿Õ¼ä£º
½«AndroidÉ豸Á¬½Óµ½µçÄÔÉÏÖ®ºó£¬Í¨¹ýadb shell½øÈëµ½ÖÕ¶Ë
È»ºóÑ¡ÔñÒ»¸öʹÓÃÁËBinderµÄ½ø³Ì£¬ÀýÈçsystem_server£¨ÕâÊÇϵͳÖÐÒ»¸ö·Ç³£ÖØÒªµÄ½ø³Ì£¬ÏÂÒ»ÕÂÎÒÃÇ»áרÃŽ²½â£©£¬Í¨¹ý
ps | grep system_serverÀ´È·¶¨½ø³ÌºÅ£¬ÀýÈçÊÇ1889
ͨ¹ý cat /proc/[pid]/maps | grep "/dev/binder"
¹ýÂ˳öÕâ¿éÄÚ´æµÄµØÖ·
ÔÚÎÒµÄNexus 6PÉÏ£¬¿ØÖÆÌ¨Êä³öÈçÏ£º
angler:/ # ps | grep system_server system 1889 526 2353404 140016 SyS_epoll_ 72972eeaf4 S system_server angler:/ # cat /proc/1889/maps | grep "/dev/binder" 7294761000-729485f000 r--p 00000000 00:0c 12593
|
PS£ºgrepÊÇͨ¹ýͨÅä·û½øÐÐÆ¥Åä¹ýÂ˵ÄÃüÁ¡°|¡±ÊÇUnixÉϵĹܵÀÃüÁî¡£¼´½«Ç°Ò»¸öÃüÁîµÄÊä³ö¸øÏÂÒ»¸öÃüÁî×÷ΪÊäÈë¡£Èç¹ûÕâÀïÎÒÃDz»¼Ó¡°
| grep xxx¡±£¬ÄÇô½«¿´µ½Ç°Ò»¸öÃüÁîµÄÍêÕûÊä³ö¡£
ÄÚ´æµÄ¹ÜÀí
ÉÏÎÄÖУ¬ÎÒÃÇ¿´µ½binder_mmapµÄʱºò£¬»áÉêÇëÒ»¸öPAGE_SIZE(ͨ³£ÊÇ4K)µÄÄÚ´æ¡£¶øÊµ¼ÊʹÓùý³ÌÖУ¬Ò»¸öPAGE_SIZEµÄ´óСͨ³£ÊDz»¹»µÄ¡£
ÔÚÇý¶¯ÖУ¬»á¸ù¾Ýʵ¼ÊµÄʹÓÃÇé¿ö½øÐÐÄÚ´æµÄ·ÖÅä¡£ÓÐÄÚ´æµÄ·ÖÅ䣬µ±È»Ò²ÐèÒªÄÚ´æµÄÊÍ·Å¡£ÕâÀïÎÒÃǾÍÀ´¿´¿´BinderÇý¶¯ÖÐÊÇÈçºÎ½øÐÐÄÚ´æµÄ¹ÜÀíµÄ¡£
Ê×ÏÈ£¬ÎÒÃÇ»¹ÊÇ´ÓÒ»´ÎIPCÇëÇó˵Æð¡£
µ±Ò»¸öClientÏëÒª¶ÔServer·¢³öÇëÇóʱ£¬ËüÊ×ÏȽ«ÇëÇó·¢Ë͵½BinderÉ豸ÉÏ£¬ÓÉBinderÇý¶¯¸ù¾ÝÇëÇóµÄÐÅÏ¢ÕÒµ½¶ÔÓ¦µÄÄ¿±ê½Úµã£¬È»ºó½«ÇëÇóÊý¾Ý´«µÝ¹ýÈ¥¡£
½ø³Ìͨ¹ýioctlϵͳµ÷ÓÃÀ´·¢³öÇëÇó£ºioctl(mProcess->mDriverFD, BINDER_WRITE_READ,
&bwr)
PS£ºÕâÐдúÂëÀ´×ÔÓÚFramework²ãµÄIPCThreadStateÀà¡£ÔÚºóÎÄÖУ¬ÎÒÃǽ«¿´µ½£¬IPCThreadStateÀàרߺÔðÓëÇý¶¯½øÐÐͨÐÅ¡£
ÕâÀïµÄmProcess->mDriverFD¶ÔÓ¦ÁË´ò¿ªBinderÉ豸ʱµÄfd¡£BINDER_WRITE_READ¶ÔÓ¦Á˾ßÌåÒª×öµÄ²Ù×÷Â룬Õâ¸ö²Ù×÷Â뽫ÓÉBinderÇý¶¯½âÎö¡£bwr´æ´¢ÁËÇëÇóÊý¾Ý£¬ÆäÀàÐÍÊÇbinder_write_read¡£
binder_write_readÆäʵÊÇÒ»¸öÏà¶ÔÍâ²ãµÄÊý¾Ý½á¹¹£¬ÆäÄÚ²¿»á°üº¬Ò»¸öbinder_transaction_data½á¹¹µÄÊý¾Ý¡£binder_transaction_data°üº¬ÁË·¢³öÇëÇóÕߵıêʶ£¬ÇëÇóµÄÄ¿±ê¶ÔÏóÒÔ¼°ÇëÇóËùÐèÒªµÄ²ÎÊý¡£ËüÃǵĹØÏµÈçÏÂͼËùʾ£º

binder_ioctlº¯Êý¶ÔÓ¦ÁËioctlϵͳµ÷ÓõĴ¦Àí¡£Õâ¸öº¯ÊýµÄÂß¼±È½Ï¼òµ¥£¬¾ÍÊǸù¾ÝioctlµÄÃüÁîÀ´È·¶¨½øÒ»²½´¦ÀíµÄÂß¼£¬¾ßÌåÈçÏÂ:
Èç¹ûÃüÁîÊÇBINDER_WRITE_READ£¬²¢ÇÒ
Èç¹û bwr.write_size > 0£¬Ôòµ÷ÓÃbinder_thread_write
Èç¹û bwr.read_size > 0£¬Ôòµ÷ÓÃbinder_thread_read
Èç¹ûÃüÁîÊÇBINDER_SET_MAX_THREADS£¬ÔòÉèÖýø³ÌµÄmax_threads£¬¼´½ø³ÌÖ§³ÖµÄ×î´óÏß³ÌÊý
Èç¹ûÃüÁîÊÇBINDER_SET_CONTEXT_MGR£¬ÔòÉèÖõ±Ç°½ø³ÌΪServiceManager£¬¼ûÏÂÎÄ
Èç¹ûÃüÁîÊÇBINDER_THREAD_EXIT£¬Ôòµ÷ÓÃbinder_free_thread£¬ÊÍ·Åbinder_thread
Èç¹ûÃüÁîÊÇBINDER_VERSION£¬Ôò·µ»Øµ±Ç°µÄBinder°æ±¾ºÅ
ÕâÆäÖУ¬×î¹Ø¼üµÄ¾ÍÊÇbinder_thread_write·½·¨¡£µ±ClientÇëÇóServerµÄʱºò£¬±ã»á·¢ËÍÒ»¸öBINDER_WRITE_READÃüÁͬʱ¿ò¼Ü»á½«½«Êµ¼ÊµÄÊý¾Ý°ü×°ºÃ¡£´Ëʱ£¬binder_transaction_dataÖеÄcode½«ÊÇBC_TRANSACTION£¬Óɴ˱ã»áµ÷Óõ½binder_transaction·½·¨£¬Õâ¸ö·½·¨ÊǶÔÒ»´ÎBinderÊÂÎñµÄ´¦Àí£¬ÕâÆäÖлáµ÷ÓÃbinder_alloc_bufº¯ÊýΪ´Ë´ÎÊÂÎñÉêÇëÒ»¸ö»º´æ¡£ÕâÀïÌáµ½µ½µ÷ÓùØÏµÈçÏ£º

binder_update_page_rangeÕâ¸öº¯ÊýÔÚÉÏÎÄÖУ¬ÎÒÃÇÒѾ¿´µ½¹ýÁË¡£Æä×÷ÓþÍÊÇ£º½øÐÐÄÚ´æ·ÖÅä²¢ÇÒÍê³ÉÄÚ´æµÄÓ³Éä¡£¶øbinder_alloc_bufº¯Êý£¬ÕýÈçÆäÃû³ÆÄÇÑùµÄ£ºÍê³É»º´æµÄ·ÖÅä¡£
ÔÚÇý¶¯ÖУ¬Í¨¹ýbinder_buffer½á¹¹ÌåÃèÊö»º´æ¡£Ò»´ÎBinderÊÂÎñ¾Í»á¶ÔÓ¦Ò»¸öbinder_buffer£¬Æä½á¹¹ÈçÏÂËùʾ£º
struct binder_buffer { struct list_head entry; struct rb_node rb_node;
unsigned free:1;
unsigned allow_user_free:1;
unsigned async_transaction:1;
unsigned debug_id:29;
struct binder_transaction *transaction;
struct binder_node *target_node;
size_t data_size;
size_t offsets_size;
uint8_t data[0];
}; |
¶øÔÚbinder_proc£¨ÃèÊöÁËʹÓÃBinderµÄ½ø³Ì£©ÖУ¬°üº¬Á˼¸¸ö×Ö¶ÎÓÃÀ´¹ÜÀí½ø³ÌÔÚBinder
IPC¹ý³ÌÖлº´æ£¬ÈçÏ£º
struct binder_proc { ... struct list_head buffers; // ½ø³ÌÓµÓеÄbufferÁбí struct rb_root free_buffers; // ¿ÕÏÐbufferÁбí struct rb_root allocated_buffers; // ÒÑʹÓõÄbufferÁбí size_t free_async_space; // Ê£ÓàµÄÒì²½µ÷ÓõĿռä
size_t buffer_size; // »º´æµÄÉÏÏÞ
...
}; |
½ø³ÌÔÚmmapʱ£¬»áÉ趨֧³ÖµÄ×Ü»º´æ´óСµÄÉÏÏÞ£¨ÏÂÎĻὲµ½£©¡£¶ø½ø³Ìÿµ±ÊÕµ½BC_TRANSACTION£¬¾Í»áÅжÏÒÑʹÓûº´æ¼Ó±¾´ÎÉêÇëµÄºÍÓÐûÓг¬¹ýÉÏÏÞ¡£Èç¹ûûÓУ¬¾Í¿¼ÂǽøÐÐÄÚ´æµÄ·ÖÅä¡£
½ø³ÌµÄ¿ÕÏлº´æ¼Ç¼ÔÚbinder_procµÄfree_buffersÖУ¬ÕâÊÇÒ»¸öÒÔºìºÚÊ÷ÐÎʽ´æ´¢µÄ½á¹¹¡£Ã¿´Î³¢ÊÔ·ÖÅ仺´æµÄʱºò£¬»á´ÓÕâÀïÃæ°´´óС˳Ðò½øÐвéÕÒ£¬ÕÒµ½×î½Ó½üÐèÒªµÄÒ»¿é»º´æ¡£²éÕÒµÄÂß¼ÈçÏ£º
while (n) { buffer = rb_entry(n, struct binder_buffer, rb_node); BUG_ON(!buffer->free); buffer_size = binder_buffer_size(proc, buffer);
if (size < buffer_size) {
best_fit = n;
n = n->rb_left;
} else if (size > buffer_size)
n = n->rb_right;
else {
best_fit = n;
break;
}
} |
ÕÒµ½Ö®ºó£¬»¹ÐèÒª¶Ôbinder_procÖеÄ×ֶνøÐÐÏàÓ¦µÄ¸üУº
rb_erase(best_fit, &proc->free_buffers); buffer->free = 0; binder_insert_allocated_buffer(proc, buffer); if (buffer_size != size) { struct binder_buffer *new_buffer = (void *)buffer->data + size; list_add(&new_buffer->entry, &buffer->entry); new_buffer->free = 1; binder_insert_free_buffer(proc, new_buffer); } binder_debug(BINDER_DEBUG_BUFFER_ALLOC, "%d: binder_alloc_buf size %zd got %p\n", proc->pid, size, buffer); buffer->data_size = data_size; buffer->offsets_size = offsets_size; buffer->async_transaction = is_async; if (is_async) { proc->free_async_space -= size + sizeof(struct binder_buffer); binder_debug(BINDER_DEBUG_BUFFER_ALLOC_ASYNC, "%d: binder_alloc_buf size %zd async free %zd\n", proc->pid, size, proc->free_async_space); }
|
ÏÂÃæÎÒÃÇÔÙÀ´¿´¿´ÄÚ´æµÄÊÍ·Å¡£
BC_FREE_BUFFERÃüÁîÊÇ֪ͨÇý¶¯½øÐÐÄÚ´æµÄÊÍ·Å£¬binder_free_bufº¯ÊýÊÇÕæÕýʵÏÖµÄÂß¼£¬Õâ¸öº¯ÊýÓëbinder_alloc_bufÊǸպöÔÓ¦µÄ¡£ÔÚÕâ¸öº¯ÊýÖУ¬Ëù×öµÄÊÂÇé°üÀ¨£º
ÖØÐ¼ÆËã½ø³ÌµÄ¿ÕÏлº´æ´óС
ͨ¹ýbinder_update_page_rangeÊÍ·ÅÄÚ´æ
¸üÐÂbinder_procµÄbuffers£¬free_buffers£¬allocated_buffers×Ö¶Î
BinderÖеġ°ÃæÏò¶ÔÏó¡±
Binder»úÖÆµ»¯Á˽ø³ÌµÄ±ß½ç£¬Ê¹µÃ¿çÔ½½ø³ÌÒ²Äܹ»µ÷Óõ½Ö¸¶¨·þÎñµÄ·½·¨£¬ÆäÔÒòÊÇÒòΪBinder»úÖÆÔڵײ㴦ÀíÁËÔÚ½ø³Ì¼äµÄ¡°¶ÔÏó¡±´«µÝ¡£
ÔÚBinderÇý¶¯ÖУ¬²¢²»ÊÇÕæµÄ½«¶ÔÏóÔÚ½ø³Ì¼äÀ´»ØÐòÁл¯£¬¶øÊÇͨ¹ýÌØ¶¨µÄ±êʶÀ´½øÐжÔÏóµÄ´«µÝ¡£BinderÇý¶¯ÖУ¬Í¨¹ýflat_binder_objectÀ´ÃèÊöÐèÒª¿çÔ½½ø³Ì´«µÝµÄ¶ÔÏ󡣯䶍ÒåÈçÏ£º
struct flat_binder_object { __u32 type; __u32 flags;
union {
binder_uintptr_t binder; /* local object */
__u32 handle; /* remote object */
};
binder_uintptr_t cookie;
}; |
ÕâÆäÖУ¬typeÓÐÈçÏÂ5ÖÖÀàÐÍ¡£
enum { BINDER_TYPE_BINDER = B_PACK_CHARS('s', 'b', '*', B_TYPE_LARGE), BINDER_TYPE_WEAK_BINDER = B_PACK_CHARS('w', 'b', '*', B_TYPE_LARGE), BINDER_TYPE_HANDLE = B_PACK_CHARS('s', 'h', '*', B_TYPE_LARGE), BINDER_TYPE_WEAK_HANDLE = B_PACK_CHARS('w', 'h', '*', B_TYPE_LARGE), BINDER_TYPE_FD = B_PACK_CHARS('f', 'd', '*', B_TYPE_LARGE), };
|
µ±¶ÔÏ󴫵ݵ½BinderÇý¶¯ÖеÄʱºò£¬ÓÉÇý¶¯À´½øÐзÒëºÍ½âÊÍ£¬È»ºó´«µÝµ½½ÓÊյĽø³Ì¡£
ÀýÈçµ±Server°ÑBinderʵÌå´«µÝ¸øClientʱ£¬ÔÚ·¢ËÍÊý¾ÝÁ÷ÖУ¬flat_binder_objectÖеÄtypeÊÇBINDER_TYPE_BINDER£¬Í¬Ê±binder×Ö¶ÎÖ¸ÏòServer½ø³ÌÓû§¿Õ¼äµØÖ·¡£µ«Õâ¸öµØÖ·¶ÔÓÚClient½ø³ÌÊÇûÓÐÒâÒåµÄ£¨LinuxÖУ¬Ã¿¸ö½ø³ÌµÄµØÖ·¿Õ¼äÊÇ»¥Ïà¸ôÀëµÄ£©£¬Çý¶¯±ØÐë¶ÔÊý¾ÝÁ÷ÖеÄflat_binder_object×öÏàÓ¦µÄ·Ò룺½«type¸Ã³ÉBINDER_TYPE_HANDLE£»ÎªÕâ¸öBinderÔÚ½ÓÊÕ½ø³ÌÖд´½¨Î»ÓÚÄÚºËÖеÄÒýÓò¢½«ÒýÓúÅÌîÈëhandleÖС£¶ÔÓÚ·¢ÉúÊý¾ÝÁ÷ÖÐÒýÓÃÀàÐ͵ÄBinderÒ²Òª×öͬÑùת»»¡£¾¹ý´¦Àíºó½ÓÊÕ½ø³Ì´ÓÊý¾ÝÁ÷ÖÐÈ¡µÃµÄBinderÒýÓòÅÊÇÓÐЧµÄ£¬²Å¿ÉÒÔ½«ÆäÌîÈëÊý¾Ý°übinder_transaction_dataµÄtarget.handleÓò£¬ÏòBinderʵÌå·¢ËÍÇëÇó¡£
ÓÉÓÚÿ¸öÇëÇóºÍÇëÇóµÄ·µ»Ø¶¼»á¾ÀúÄں˵ķÒ룬Òò´ËÕâ¸ö¹ý³Ì´Ó½ø³ÌµÄ½Ç¶ÈÀ´¿´ÊÇÍêȫ͸Ã÷µÄ¡£½ø³ÌÍêÈ«²»ÓøÐÖªÕâ¸ö¹ý³Ì£¬¾ÍºÃÏñ¶ÔÏóÕæµÄÔÚ½ø³Ì¼äÀ´»Ø´«µÝÒ»Ñù¡£
Çý¶¯²ãµÄÏ̹߳ÜÀí
ÉÏÎĶà´ÎÌáµ½£¬Binder±¾ÉíÊÇC/S¼Ü¹¹¡£ÓÉServerÌṩ·þÎñ£¬±»ClientʹÓ᣼ÈÈ»ÊÇC/S¼Ü¹¹£¬¾Í¿ÉÄÜ´æÔÚ¶à¸öClient»áͬʱ·ÃÎÊServerµÄÇé¿ö¡£
ÔÚÕâÖÖÇé¿öÏ£¬Èç¹ûServerÖ»ÓÐÒ»¸öÏ̴߳¦ÀíÏìÓ¦£¬¾Í»áµ¼Ö¿ͻ§¶ËµÄÇëÇó¿ÉÄÜÐèÒªÅŶӶøµ¼ÖÂÏìÓ¦¹ýÂýµÄÏÖÏó·¢Éú¡£½â¾öÕâ¸öÎÊÌâµÄ·½·¨¾ÍÊÇÒýÈë¶àÏ̡߳£
Binder»úÖÆµÄÉè¼Æ´Ó×îµ×²ã¨CÇý¶¯²ã£¬¾Í¿¼Âǵ½Á˶ÔÓÚ¶àÏ̵߳ÄÖ§³Ö¡£¾ßÌåÄÚÈÝÈçÏ£º
ʹÓÃBinderµÄ½ø³ÌÔÚÆô¶¯Ö®ºó£¬Í¨¹ýBINDER_SET_MAX_THREADS¸æÖªÇý¶¯ÆäÖ§³ÖµÄ×î´óÏß³ÌÊýÁ¿
Çý¶¯»á¶ÔÏ߳̽øÐйÜÀí¡£ÔÚbinder_proc½á¹¹ÖУ¬ÕâЩ×ֶμǼÁ˽ø³ÌÖÐÏ̵߳ÄÐÅÏ¢£ºmax_threads£¬requested_threads£¬requested_threads_started£¬ready_threads
binder_thread½á¹¹¶ÔÓ¦ÁËBinder½ø³ÌÖеÄÏß³Ì
Çý¶¯Í¨¹ýBR_SPAWN_LOOPERÃüÁî¸æÖª½ø³ÌÐèÒª´´½¨Ò»¸öеÄÏß³Ì
½ø³Ìͨ¹ýBC_ENTER_LOOPERÃüÁî¸æÖªÇý¶¯ÆäÖ÷Ïß³ÌÒѾready
½ø³Ìͨ¹ýBC_REGISTER_LOOPERÃüÁî¸æÖªÇý¶¯Æä×ÓỊ̈߳¨·ÇÖ÷Ị̈߳©ÒѾready
½ø³Ìͨ¹ýBC_EXIT_LOOPERÃüÁî¸æÖªÇý¶¯ÆäÏ߳̽«ÒªÍ˳ö
ÔÚÏß³ÌÍ˳öÖ®ºó£¬Í¨¹ýBINDER_THREAD_EXIT¸æÖªBinderÇý¶¯¡£Çý¶¯½«¶ÔÓ¦µÄbinder_thread¶ÔÏóÏú»Ù
ÔÙÁÄServiceManager
ÉÏÎÄÒѾ˵¹ý£¬Ã¿Ò»¸öBinder ServerÔÚÇý¶¯ÖлáÓÐÒ»¸öbinder_node½øÐжÔÓ¦¡£Í¬Ê±£¬BinderÇý¶¯»á¸ºÔðÔÚ½ø³Ì¼ä´«µÝ·þÎñ¶ÔÏ󣬲¢¸ºÔðµ×²ãµÄת»»¡£ÁíÍ⣬ÎÒÃÇÒ²Ìáµ½£¬Ã¿Ò»¸öBinder·þÎñ¶¼ÐèÒªÓÐÒ»¸öΨһµÄÃû³Æ¡£ÓÉServiceManagerÀ´¹ÜÀíÕâЩ·þÎñµÄ×¢²áºÍ²éÕÒ¡£
¶øÊµ¼ÊÉÏ£¬ÎªÁ˱ãÓÚʹÓã¬ServiceManager±¾ÉíҲʵÏÖΪһ¸öServer¶ÔÏó¡£Èκνø³ÌÔÚʹÓÃServiceManagerµÄʱºò£¬¶¼ÐèÒªÏÈÄõ½Ö¸ÏòËüµÄ±êʶ¡£È»ºóͨ¹ýÕâ¸ö±êʶÀ´Ê¹ÓÃServiceManager¡£
ÕâËÆºõÐγÉÁËÒ»¸ö»¥Ïàì¶ÜµÄÏÖÏó£º
ͨ¹ýServiceManagerÎÒÃDzÅÄÜÄõ½ServerµÄ±êʶ
ServiceManager±¾ÉíÒ²ÊÇÒ»¸öServer
½â¾öÕâ¸öì¶ÜµÄ°ì·¨ÆäʵҲºÜ¼òµ¥£ºBinder»úÖÆÎªServiceManagerÔ¤ÁôÁËÒ»¸öÌØÊâµÄλÖá£Õâ¸öλÖÃÊÇÔ¤Ïȶ¨ºÃµÄ£¬ÈκÎÏëҪʹÓÃServiceManagerµÄ½ø³ÌֻҪͨ¹ýÕâ¸öÌØ¶¨µÄλÖþͿÉÒÔ·ÃÎʵ½ServiceManagerÁË£¨¶ø²»ÓÃÔÙͨ¹ýServiceManagerµÄ½Ó¿Ú£©¡£
ÔÚBinderÇý¶¯ÖУ¬ÓÐÒ»¸öÈ«¾ÖµÄ±äÁ¿£º
static struct binder_node *binder_context_mgr_node;
|
Õâ¸ö±äÁ¿Ö¸ÏòµÄ¾ÍÊÇServiceManager¡£
µ±Óнø³Ìͨ¹ýioctl²¢Ö¸¶¨ÃüÁîΪBINDER_SET_CONTEXT_MGRµÄʱºò£¬Çý¶¯±»È϶¨Õâ¸ö½ø³ÌÊÇServiceManager£¬binder_ioctlº¯ÊýÖжÔÓ¦µÄ´¦ÀíÈçÏ£º
case BINDER_SET_CONTEXT_MGR: if (binder_context_mgr_node != NULL) { pr_err("BINDER_SET_CONTEXT_MGR already set\n"); ret = -EBUSY; goto err; } ret = security_binder_set_context_mgr(proc->tsk); if (ret < 0) goto err; if (uid_valid(binder_context_mgr_uid)) { if (!uid_eq(binder_context_mgr_uid, current->cred->euid)) { pr_err("BINDER_SET_CONTEXT_MGR bad uid %d != %d\n", from_kuid(&init_user_ns, current->cred->euid), from_kuid(&init_user_ns, binder_context_mgr_uid)); ret = -EPERM; goto err; } } else binder_context_mgr_uid = current->cred->euid; binder_context_mgr_node = binder_new_node(proc, 0, 0); if (binder_context_mgr_node == NULL) { ret = -ENOMEM; goto err; } binder_context_mgr_node->local_weak_refs++; binder_context_mgr_node->local_strong_refs++; binder_context_mgr_node->has_strong_ref = 1; binder_context_mgr_node->has_weak_ref = 1; break;
|
ServiceManagerÓ¦µ±ÒªÏÈÓÚËùÓÐBinder Server֮ǰÆô¶¯¡£ÔÚËüÆô¶¯Íê³É²¢¸æÖªBinderÇý¶¯Ö®ºó£¬Çý¶¯±ãÉ趨ºÃÁËÕâ¸öÌØ¶¨µÄ½Úµã¡£
ÔÚÕâÖ®ºó£¬µ±ÓÐÆäËûÄ£¿éÏëҪʹÓÃServerManagerµÄʱºò£¬Ö»Òª½«ÇëÇóÖ¸ÏòServiceManagerËùÔÚµÄλÖü´¿É¡£
ÔÚBinderÇý¶¯ÖУ¬Í¨¹ýhandle = 0Õâ¸öλÖÃÀ´·ÃÎÊServiceManager¡£ÀýÈ磬binder_transactionÖУ¬ÅжÏÈç¹ûtarget.handlerΪ0£¬ÔòÈÏΪÕâ¸öÇëÇóÊÇ·¢Ë͸øServiceManagerµÄ£¬Ïà¹Ø´úÂëÈçÏ£º
½áÊøÓï
±¾ÆªÎÄÕÂÖУ¬ÎÒÃǶÔBinder»úÖÆ×öÁËÕûÌå¼Ü¹¹ºÍ·Ö²ãµÄ½éÉÜ£¬Ò²Ïêϸ½²½âÁËBinder»úÖÆÖеÄÇý¶¯Ä£¿é¡£¶ÔÓÚÇý¶¯Ö®ÉϵÄÄ£¿é£¬»áÔÚ½ñºóµÄÎÄÕÂÖн²½â¡£
|