由于簡(jiǎn)書對(duì)文章有最大長(zhǎng)度限制,這部分內(nèi)容拆解為三篇,分別為:
Binder驅(qū)動(dòng)之設(shè)備控制binder_ioctl -- 一
Binder驅(qū)動(dòng)之設(shè)備控制binder_ioctl -- 二
Binder驅(qū)動(dòng)之設(shè)備控制binder_ioctl -- 三
概述
ioctl是Linux中常見的系統(tǒng)調(diào)用,它用于對(duì)底層設(shè)備的一些特性進(jìn)行控制的用戶態(tài)接口,應(yīng)用程序在調(diào)用ioctl進(jìn)行設(shè)備控制時(shí),最后會(huì)調(diào)用到設(shè)備注冊(cè)struct file_operations結(jié)構(gòu)體對(duì)象時(shí)的unlocked_ioctl或者compat_ioctl兩個(gè)鉤子上,具體是調(diào)用哪個(gè)鉤子判斷標(biāo)準(zhǔn)如下:
-
compat_ioctl: 32位的應(yīng)用運(yùn)行在64位的內(nèi)核上,這個(gè)鉤子被調(diào)用。 -
unlocked_ioctl: 64位的應(yīng)用運(yùn)行在64位的內(nèi)核或者32位的應(yīng)用運(yùn)行在32位的內(nèi)核上,則調(diào)用這個(gè)鉤子。
Binder做為Android中進(jìn)程間高效通信的核心組件,其底層是以misc設(shè)備驅(qū)動(dòng)的形式實(shí)現(xiàn)的,但它本身并沒(méi)有實(shí)現(xiàn)read,write操作,所有的控制都是通過(guò)ioctl操作來(lái)實(shí)現(xiàn)。在Binder驅(qū)動(dòng)的struct file_operations定義中可見,它的compat_ioctl和unlocked_ioctl兩個(gè)鉤子的的實(shí)現(xiàn)都是對(duì)應(yīng)到binder_ioctl上的。
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,
};
接下來(lái),我們來(lái)先看看binder_ioctl的實(shí)現(xiàn)有關(guān)的結(jié)構(gòu)體。
相關(guān)數(shù)據(jù)結(jié)構(gòu)
2.1 struct binder_thread
struct binder_thread {
struct binder_proc *proc; /*該thread相關(guān)聯(lián)的binder_proc*/
struct rb_node rb_node; /*用于鏈入proc的threads紅黑樹*/
int pid;
int looper; /* 狀態(tài)標(biāo)識(shí)位,用于表示當(dāng)前線程所處的狀態(tài),具體包括以下幾種狀態(tài):
* enum {
* BINDER_LOOPER_STATE_REGISTERED = 0x01, /*進(jìn)程的非主線程進(jìn)入Binder循環(huán)狀態(tài)*/
* BINDER_LOOPER_STATE_ENTERED = 0x02, /*進(jìn)程的主線程進(jìn)入Binder循環(huán)狀態(tài)*/
* BINDER_LOOPER_STATE_EXITED = 0x04, /*線程退出Binder循環(huán)狀態(tài)*/
* BINDER_LOOPER_STATE_INVALID = 0x08, /*線程處在一個(gè)無(wú)效的狀態(tài),表示出錯(cuò)*/
* BINDER_LOOPER_STATE_WAITING = 0x10, /*線程的todo隊(duì)列為空,進(jìn)入等待請(qǐng)求的狀態(tài)*/
* BINDER_LOOPER_STATE_NEED_RETURN = 0x20 /*線程是否需要返回?cái)?shù)據(jù)給進(jìn)程的用戶態(tài)*/
* };
*/
struct binder_transaction *transaction_stack; /*該線程的事務(wù)棧。通過(guò)struct binder_transaction的
* from_parent和to_parent分別鏈入客戶端和服務(wù)端線程的
* transaction_stack事務(wù)棧中(即本字段)。詳見2.7 */
struct list_head todo; /*binder_work隊(duì)列,管理本線程所有待處理的binder_work*/
uint32_t return_error; /* Write failed, return error code in read buf */
uint32_t return_error2; /* Write failed, return error code in read
* buffer. Used when **sending a reply to a dead process** that */
* we are also waiting on 。發(fā)送reply時(shí)發(fā)生錯(cuò)誤,該錯(cuò)誤碼用于返回給發(fā)送進(jìn)程 */
wait_queue_head_t wait; /*binder線程空閑時(shí),用于等待隊(duì)列相關(guān)的結(jié)構(gòu),是Linux內(nèi)核的一個(gè)數(shù)據(jù)結(jié)構(gòu)*/
struct binder_stats stats; /*統(tǒng)計(jì)有關(guān)的結(jié)構(gòu)*/
};
2.2 struct binder_proc中的相關(guān)成員
struct binder_proc{
...
struct rb_root threads; /*管理thread的紅黑樹根節(jié)點(diǎn),以線程的id為序*/
struct rb_root nodes; /*管理binder_node的紅黑樹根節(jié)點(diǎn),以binder_node中的ptr大小為序*/
struct rb_root refs_by_desc; /*管理binder_ref的紅黑樹根節(jié)點(diǎn),以binder_ref中的desc大小為序*/
struct rb_root refs_by_node; /*管理binder_ref的紅黑樹根節(jié)點(diǎn),以binder_ref對(duì)應(yīng)的binder_node的地址為序*/
...
int max_threads; /*最大線程數(shù)*/
...
};
2.3 用于用戶態(tài)向內(nèi)核態(tài)傳輸數(shù)據(jù)的結(jié)構(gòu)體 —— struct binder_write_read
struct binder_write_read {
/* process ----> kernel */
binder_size_t write_size; /* bytes to write, 進(jìn)程用戶態(tài)地址空間傳遞到內(nèi)核數(shù)據(jù)的大小*/
binder_size_t write_consumed; /* bytes consumed by driver 進(jìn)程用戶態(tài)地址空間傳遞到內(nèi)核數(shù)據(jù)中已經(jīng)被內(nèi)核態(tài)處理的大小*/
binder_uintptr_t write_buffer; /*進(jìn)程用戶態(tài)地址空間傳遞到內(nèi)核數(shù)據(jù)的起始地址*/
/* kernel ----> process */
binder_size_t read_size; /* bytes to read, 總共可供給驅(qū)動(dòng)寫入的字節(jié)數(shù),read_buffer可供內(nèi)核使用的大小*/
binder_size_t read_consumed; /* bytes consumed by driver, 內(nèi)核Binder驅(qū)動(dòng)發(fā)送給用戶態(tài)進(jìn)程的字節(jié)數(shù)*/
binder_uintptr_t read_buffer; /*內(nèi)核驅(qū)動(dòng)發(fā)送給進(jìn)程數(shù)據(jù)buffer的起始地址*/
};
2.4 Binder C/S通信架構(gòu)中,C端的驅(qū)動(dòng)層表示 —— struct binder_ref
struct binder_ref {
/* Lookups needed: */
/* node + proc => ref (transaction) */
/* desc + proc => ref (transaction, inc/dec ref) */
/* node => refs + procs (proc exit) */
int debug_id; /*每個(gè)binder_ref的唯一標(biāo)識(shí)符,主要用于debug*/
struct rb_node rb_node_desc; /*用來(lái)鏈入proc->refs_by_desc紅黑樹中,該紅黑樹以desc域?yàn)樾蚪M織的*/
struct rb_node rb_node_node; /*用來(lái)鏈入proc->refs_by_node紅黑樹中, 該紅黑樹以該binder_ref所對(duì)應(yīng)的binder_node的地址為序組織的*/
struct hlist_node node_entry; /*用來(lái)鏈入binder_node的refs哈希鏈表中。*/
struct binder_proc *proc; /*指向該binder_ref中所屬的binder_proc*/
struct binder_node *node; /*指向該binder_ref所對(duì)應(yīng)(引用)的binder_node*/
uint32_t desc; /*binder_ref的描述符。用來(lái)返回給進(jìn)程用戶態(tài)地址空間,標(biāo)識(shí)所對(duì)應(yīng)的binder_ref*/
int strong; /*強(qiáng)引用計(jì)數(shù)*/
int weak; /*弱引用計(jì)數(shù)*/
struct binder_ref_death *death; /*Binder“死亡訃告”相關(guān)的一個(gè)結(jié)構(gòu)體,詳見:2.8*/
};
2.5 Binder C/S通信架構(gòu)中,S端的驅(qū)動(dòng)層表示 —— struct binder_node
struct binder_node {
int debug_id;
struct binder_work work;
union {
struct rb_node rb_node; /*用來(lái)鏈入proc的nodes紅黑樹,該紅黑樹以binder_node的ptr的大小為序*/
struct hlist_node dead_node;
};
struct binder_proc *proc;
struct hlist_head refs; /*所有引用這個(gè)binder_node的binder_ref通過(guò)它的node_entry加入這個(gè)哈希鏈表中,
* 這樣binder_node通過(guò)查看這個(gè)哈希鏈表就知道有哪些binder_ref在引用它*/
int internal_strong_refs; /*binder_ref的強(qiáng)引用計(jì)數(shù),即有多少個(gè)binder_ref強(qiáng)引用這個(gè)binder_node*/
int local_weak_refs; /*BBinder弱引用計(jì)數(shù)*/
int local_strong_refs; /*binder_buffer.target_node及BBinder的強(qiáng)引用計(jì)數(shù)*/
binder_uintptr_t ptr; /*對(duì)應(yīng)BBinder基類RefBase中mRef成員的的地址,它是一個(gè)引用計(jì)數(shù)器,類型為weakref_impl*/
binder_uintptr_t cookie; /*對(duì)應(yīng)BBinder的地址*/**
unsigned has_strong_ref:1; /*標(biāo)識(shí)是否已經(jīng)增加了用戶態(tài)對(duì)應(yīng)binder service(BBinder)對(duì)象的強(qiáng)引用計(jì)數(shù)*/
unsigned pending_strong_ref:1; /*標(biāo)識(shí)是否有未處理的BR_ACQUIRE命令,在執(zhí)行BR_ACQUIRE請(qǐng)求命令前設(shè)為1,在BC_ACQUIRE_DONE中設(shè)為0*/
unsigned has_weak_ref:1; /*標(biāo)識(shí)是否已經(jīng)增加了用戶態(tài)對(duì)應(yīng)binder service(BBinder)對(duì)象的弱引用計(jì)數(shù)*/
unsigned pending_weak_ref:1; /*標(biāo)識(shí)是否有未處理的BR_INCREFS命令,在執(zhí)行BR_INCREFS請(qǐng)求命令前設(shè)為1,在BC_INCREFS_DONE中設(shè)為0*/
unsigned has_async_transaction:1; /*標(biāo)識(shí)是否有異步事務(wù)要處理。異步事務(wù)的含義是:客戶端發(fā)送了帶有TF_ONE_WAY標(biāo)識(shí)的請(qǐng)求。*/
unsigned accept_fds:1; /*是否接受文件描述符*/
unsigned min_priority:8;
struct list_head async_todo; /*異步事務(wù)待處理鏈表*/
};
2.6 用于Binder用戶態(tài)向內(nèi)核驅(qū)動(dòng)傳輸事務(wù)數(shù)據(jù) —— struct binder_transaction_data
struct binder_transaction_data {
/* The first two are only used for bcTRANSACTION and brTRANSACTION,
* identifying the target and contents of the transaction.
*/
union {
/* target descriptor of command transaction */
__u32 handle;
/* target descriptor of return transaction */
binder_uintptr_t ptr;
} target;
binder_uintptr_t cookie; /* target object cookie */
__u32 code; /* transaction command */
/* General information about the transaction. */
__u32 flags; /*標(biāo)志位,如:TF_ONE_WAY*/
pid_t sender_pid; /*發(fā)送者進(jìn)程id*/
uid_t sender_euid; /*發(fā)送者有效用戶id*/
binder_size_t data_size; /* number of bytes of data */
binder_size_t offsets_size; /* number of bytes of offsets */
/* If this transaction is inline, the data immediately
* follows here; otherwise, it ends with a pointer to
* the data buffer.
*/
union { /*存放事務(wù)的數(shù)據(jù)部分,如果是inline,則數(shù)據(jù)直接放在buf數(shù)組中;
* 如果不是,則放在ptr結(jié)構(gòu)體中的buffer和offsets的指針中。一般情況都是通過(guò)ptr結(jié)構(gòu)體*/
struct {
/* transaction data */
binder_uintptr_t buffer;
/* offsets from buffer to flat_binder_object structs */
binder_uintptr_t offsets;
} ptr;
__u8 buf[8]; /*inline數(shù)據(jù)直接放在這個(gè)buf中, 在4.0.9的內(nèi)核中,這個(gè)字段沒(méi)有看見使用的地方*/
} data;
};
2.7 用于Binder內(nèi)核態(tài)驅(qū)動(dòng)表示Binder通信事務(wù)數(shù)據(jù)結(jié)構(gòu) —— struct binder_transaction
struct binder_transaction {
int debug_id;
struct binder_work work; /*用于鏈入線程/進(jìn)程todo隊(duì)列的成員*/
struct binder_thread *from; /*事務(wù)發(fā)起線程thread的地址,如果是binder server回復(fù)給client,該域?yàn)镹ULL*/
struct binder_transaction ***from_parent**; /* 用于鏈入事務(wù)發(fā)起線程的事務(wù)棧中,
* 加入的時(shí)機(jī)是binder_transaction_data傳入驅(qū)動(dòng)并被binder_transaction處理的時(shí)候*/
struct binder_proc *to_proc; /*目標(biāo)線程的proc地址*/
struct binder_thread *to_thread; /*事務(wù)目標(biāo)線程thread的地址*/
struct binder_transaction *to_parent; /* 用于鏈入目標(biāo)線程的事務(wù)棧中,
* 加入的時(shí)機(jī)是目標(biāo)線程在調(diào)用binder_thread_read處理thread->todo隊(duì)列
* 類型為BINDER_WORK_TRANACTION的binder_work時(shí)*/
unsigned need_reply:1;
/* unsigned is_dead:1; */ /* not used at the moment */
struct binder_buffer *buffer; /*存儲(chǔ)數(shù)據(jù)的地方*/
unsigned int code; /*一個(gè)binder調(diào)用所對(duì)應(yīng)的代號(hào)*/
unsigned int flags;
long priority; /*請(qǐng)求/回復(fù) 線程的優(yōu)先級(jí)*/
long saved_priority; /*存儲(chǔ)線程優(yōu)先級(jí)備份,當(dāng)需要修改一個(gè)線程的優(yōu)先級(jí)時(shí),先將它當(dāng)前值放在該變量中,以便于稍后恢復(fù)。*/
kuid_t sender_euid;
};
進(jìn)程用戶態(tài)傳輸進(jìn)來(lái)的struct binder_transaction_data到內(nèi)核態(tài)后,會(huì)轉(zhuǎn)化成相應(yīng)的struct binder_transaction。該數(shù)據(jù)結(jié)構(gòu)主要用于承載Binder請(qǐng)求和回復(fù)通信中的數(shù)據(jù)。
2.8 用于注冊(cè)Binder service死亡通知的數(shù)據(jù)結(jié)構(gòu) —— binder_ref_death
struct binder_ref_death {
struct binder_work work; /*binder service死亡時(shí),通過(guò)該work的entry域鏈入thread或者proc的todo隊(duì)列*/
binder_uintptr_t cookie; /*binder service死亡時(shí),要通知的BpBinder對(duì)象的地址*/
};
3. 設(shè)備驅(qū)動(dòng)控制 --- binder_ioctl
Binder驅(qū)動(dòng)沒(méi)有提供read/write操作,所有數(shù)據(jù)傳輸、控制都是通過(guò)binder_ioctl進(jìn)行,因此該部分是Binder驅(qū)動(dòng)的核心內(nèi)容,承載了Binder數(shù)據(jù)傳輸部分的主要業(yè)務(wù)。
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);
void __user *ubuf = (void __user *)arg;
/*pr_info("binder_ioctl: %d:%d %x %lx\n",
proc->pid, current->pid, cmd, arg);*/
trace_binder_ioctl(cmd, arg);
/* 如果binder_stop_on_user_error < 2 則直接返回0;
* 否則,調(diào)用_wait_event_interruptible進(jìn)入可中斷的掛起狀態(tài),接著讓出處理器,
* 直到被wake_up且條件(binder_stop_on_user_error < 2)為真時(shí)才返回
*/
ret = wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
if (ret)
goto err_unlocked;
/*獲取binder_main_lock鎖*/
binder_lock(__func__);
/*在proc->threads紅黑樹中查找thread,該紅黑樹以pid為序,具體詳見3.1*/
thread = **binder_get_thread**(proc);
if (thread == NULL) {
ret = -ENOMEM;
goto err;
}
/*根據(jù)不同的命令,調(diào)用不同的處理函數(shù)進(jìn)行處理*/
switch (cmd) {
case BINDER_WRITE_READ:
/*讀寫命令,數(shù)據(jù)傳輸,binder IPC通信的核心邏輯,詳見3.2*/
ret = **binder_ioctl_write_read**(filp, cmd, arg, thread);
if (ret)
goto err;
break;
case BINDER_SET_MAX_THREADS:
/*設(shè)置最大線程數(shù),直接將值設(shè)置到proc結(jié)構(gòu)的max_threads域中。*/
if (copy_from_user(&**proc->max_threads**, ubuf, sizeof(proc->max_threads))) {
ret = -EINVAL;
goto err;
}
break;
case BINDER_SET_CONTEXT_MGR:
/*設(shè)置Context manager,即將自己設(shè)置為ServiceManager,詳見3.3*/
ret = binder_ioctl_set_ctx_mgr(filp);
if (ret)
goto err;
break;
case BINDER_THREAD_EXIT:
/*binder線程退出命令,釋放相關(guān)資源,詳見3.4*/
binder_debug(BINDER_DEBUG_THREADS, "%d:%d exit\n",
proc->pid, thread->pid);
binder_free_thread(proc, thread);
thread = NULL;
break;
case BINDER_VERSION: {
/*獲取binder驅(qū)動(dòng)版本號(hào),在kernel4.4版本中,32位該值為7,64位版本該值為8*/
struct binder_version __user *ver = ubuf;
if (size != sizeof(struct binder_version)) {
ret = -EINVAL;
goto err;
}
/*將版本號(hào)信息寫入用戶態(tài)地址空間struct binder_version的protocol_version中*/
if (put_user(BINDER_CURRENT_PROTOCOL_VERSION,
&ver->protocol_version)) {
ret = -EINVAL;
goto err;
}
break;
}
default:
ret = -EINVAL;
goto err;
}
ret = 0;
err:
if (thread)
thread->looper &= ~BINDER_LOOPER_STATE_NEED_RETURN;
binder_unlock(__func__); /*釋放binder_main_lock鎖*/
wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
if (ret && ret != -ERESTARTSYS)
pr_info("%d:%d ioctl %x %lx returned %d\n", proc->pid, current->pid, cmd, arg, ret);
err_unlocked:
trace_binder_ioctl_done(ret);
return ret;
}
-
_IOC_SIZE讀取參數(shù)命令的大小。在32位的體系架構(gòu)中,參數(shù)
cmd由四個(gè)域組成:- 讀寫屬性域(
direction: read/write), 區(qū)分是讀取命令,還是寫入命令。bit30~bit31,占2bit??捎煤?code>_IOC_DIR讀取。 - 數(shù)據(jù)大小域(
size : size of argument), 表示ioctl中arg變量所指內(nèi)存區(qū)域占用內(nèi)存大小。bit16~bit29,占14bit??捎煤?code>_IOC_SIZE讀取 。 - 魔數(shù)域 (
type:usually related to the major number),又叫“幻數(shù)”區(qū),用來(lái)區(qū)分不同的設(shè)備驅(qū)動(dòng),當(dāng)傳入的值與自身的值不一致時(shí)則不進(jìn)行進(jìn)一步處理,是用于防止誤使用的一種狀態(tài)標(biāo)識(shí)位。一般用字母A~Z或者a~z表示。bit8~bit15,占8bit??捎煤?code>_IOC_TYPE讀取。 - 序號(hào)數(shù)或者基數(shù)(
command):用于區(qū)分各種命令。bit0~bit7,占8bit??捎煤?code>_IOC_NR讀取。
- 讀寫屬性域(
-
binder_stop_on_user_error, 該變量是一個(gè)全局靜態(tài)變量, 它的值通過(guò)模塊參數(shù)stop_on_user_error控制,當(dāng)系統(tǒng)出現(xiàn)問(wèn)題時(shí),可以通過(guò)將該值設(shè)置為一個(gè)大于或等于2的值,來(lái)暫停binder,來(lái)進(jìn)行debug。模塊參數(shù)的設(shè)置可以在模塊插入時(shí)以參數(shù)傳遞的形式設(shè)定,如insmod xxx.ko arg=xxxx形式;如果權(quán)限設(shè)置允許的話,也可以通過(guò)sysfs來(lái)動(dòng)態(tài)設(shè)置(如echo 3 > /sys/module/binder/parameters/stop_no_user_error)。相關(guān)代碼如下:
static int binder_stop_on_user_error;
/*定義模塊參數(shù)`stop_on_user_error`的設(shè)置函數(shù)*/
static int binder_set_stop_on_user_error(const char *val,
struct kernel_param *kp)
{
int ret;
ret = param_set_int(val, kp);/*將sysfs中/sys/module/binder/parameters/stop_on_user_error讀入binder_stop_on_user_error*/
if (binder_stop_on_user_error < 2)
wake_up(&binder_user_error_wait);
return ret;
}
module_param_call(stop_on_user_error/*模塊參數(shù)名字,所在路徑為:/sys/module/binder/parameters/stop_on_user_error*/,
binder_set_stop_on_user_error /*模塊參數(shù)`stop_on_user_error`的set函數(shù)*/,
param_get_int/*模塊參數(shù)`stop_on_user_error`的讀取函數(shù)*/,
&binder_stop_on_user_error/*模塊參數(shù)對(duì)應(yīng)的變量地址*/,
S_IWUSR | S_IRUGO /*在sysfs中的權(quán)限設(shè)置*/);
-
module_param_call該宏用于定義一個(gè)內(nèi)核模塊參數(shù),它的定義為module_param_call(name, set, get, arg, perm),其中:-
name:內(nèi)核模塊參數(shù)的名字,也是在sysfs中顯示的名字; -
set:是該內(nèi)核模塊參數(shù)設(shè)定的回調(diào)函數(shù),當(dāng)在插入模式時(shí)傳遞參數(shù)或者通過(guò)sysfs設(shè)定內(nèi)核模塊參數(shù)時(shí),該函數(shù)會(huì)被調(diào)用; -
get: 是該內(nèi)核模塊參數(shù)讀取的回調(diào)函數(shù); -
arg:內(nèi)核模塊參數(shù)的地址; -
perm:該內(nèi)核模塊參數(shù)的權(quán)限設(shè)置,可以在sysfs中看到。
-
對(duì)于基本的數(shù)據(jù)類型的讀取和設(shè)定回調(diào)函數(shù),內(nèi)核已經(jīng)預(yù)先做了定義,一般形式為:param_get_xxx和param_set_xxx,xxx是int, short等??梢詤⒖家幌逻@篇博客,Linux內(nèi)核模塊的編寫方法和技巧。
- 額外提一下sysfs,它是Linux2.6開始提供的一種虛擬文件系統(tǒng),設(shè)計(jì)該文件系統(tǒng)的目的是把原本在procfs關(guān)于設(shè)備的部分獨(dú)立出來(lái),以“設(shè)備層次結(jié)構(gòu)架構(gòu)(device tree)”的形式呈現(xiàn)。它可以把設(shè)備和驅(qū)動(dòng)程序的信息從內(nèi)核輸出到用戶空間,也可以對(duì)設(shè)備和驅(qū)動(dòng)程序做設(shè)置。具體詳見sysfs簡(jiǎn)介。
3.1 查找thread --- binder_get_thread
static struct binder_thread *binder_get_thread(struct binder_proc *proc)
{
struct binder_thread *thread = NULL;
struct rb_node *parent = NULL;
struct rb_node **p = &proc->threads.rb_node; /*獲取紅黑樹根節(jié)點(diǎn)*/
/*查找pid等于當(dāng)前線程id的thread,該紅黑樹以pid大小為序組織*/
while (*p) {
parent = *p;
thread = rb_entry(parent, struct binder_thread, rb_node);
/*current->pid 是當(dāng)前運(yùn)行線程的id,不是進(jìn)程的id*/
if (current->pid < thread->pid)
p = &(*p)->rb_left;
else if (current->pid > thread->pid)
p = &(*p)->rb_right;
else
break;
}
if (*p == NULL) {
/*如果沒(méi)有找到,則新創(chuàng)建一個(gè)*/
thread = kzalloc(sizeof(*thread), GFP_KERNEL);
if (thread == NULL)
return NULL;
/*更新thread創(chuàng)建統(tǒng)計(jì)計(jì)數(shù)*/
binder_stats_created(BINDER_STAT_THREAD);
/*初始化相關(guān)數(shù)據(jù)成員*/
thread->proc = proc;
thread->pid = current->pid; /*獲取線程id*/
init_waitqueue_head(&thread->wait); /*初始化等待隊(duì)列*/
INIT_LIST_HEAD(&thread->todo); /*初始化待處理隊(duì)列*/
rb_link_node(&thread->rb_node, parent, p); /*加入到proc的threads紅黑樹中*/
rb_insert_color(&thread->rb_node, &proc->threads);
thread->looper |= BINDER_LOOPER_STATE_NEED_RETURN;
thread->return_error = BR_OK;
thread->return_error2 = BR_OK;
}
return thread;
}