1. binder_ioctl
static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
首先调用binder_get_thread从该proc的thread红黑树找到对应该线程的binder_thread结构体。
thread = binder_get_thread(proc);
binder_get_thread的内部实现是根据current宏在binder_proc中的threads红黑树找到描述当前请求线程的binder_thread结构体.
如果没有找到,则为当前调用线程创建一个binder_thread结构体。
这属于binder driver主动将当前线程设置为BINDER_LOOPER_STATE_NEED_RETURN,后面会需要用户空间返回。
处理各种ioctl控制命令码
binder.h中定义如下7种命令码
#defineBINDER_WRITE_READ_IOWR('b', 1, struct binder_write_read)
#defineBINDER_SET_IDLE_TIMEOUT_IOW('b', 3, __s64)
#defineBINDER_SET_MAX_THREADS_IOW('b', 5, __u32)
#defineBINDER_SET_IDLE_PRIORITY_IOW('b', 6, __s32)
#defineBINDER_SET_CONTEXT_MGR_IOW('b', 7, __s32)
#defineBINDER_THREAD_EXIT_IOW('b', 8, __s32)
#defineBINDER_VERSION_IOWR('b', 9, struct binder_version)
因为ioctl的cmd是32位,有一定的格式。利用_IOWR,_IOW等宏辅助生成32位cmd数字。具体可以百度之,属于linux driver的标准实现。
比如:
#define BINDER_WRITE_READ _IOWR(‘b’, 1, struct binder_write_read)
- _IOWR : 表示用于双向传输
- ‘b’ : driver type, binder
- 1: 用于区别各种命令,1 代表的时BINDER_WRITE_READ
- struct binder_write_read:指定要传递数据的类型。可以根据指定的类型,得到所需要传递数据的大小。
2. 主要分析ioctl 控制命令码BINDER_WRITE_READ的处理过程
case BINDER_WRITE_READ:
ret = binder_ioctl_write_read(filp, cmd, arg, thread);
参数分别为:
- flip:当前调用进程第一次访问binder设备时创建的struct file,每次系统调用binder_ioctl时,都会将该struct传递过来 . (内核根据用户空间传过来的fd,找到在内核中对应的file。)
- cmd:ioctl 控制命令,当前为BINDER_WRITE_READ
- arg:用户空间传递下来的数据 binder_read_write 的地址
- thread:表示为当前调用线程在binder driver 中记录的的binder_thread结构体
2.1 分析binder_ioctl_write_read
首先需要根据传送下来的地址(参数arg),将数据binder_write_read 从用户空间拷贝到内核空间。copy_from_user 。
void __user *ubuf = (void __user *)arg;
struct binder_write_read bwr;
…
if (copy_from_user(&bwr, ubuf, sizeof(bwr))) {
binder_write_read 数据结构体如下,主要用户描述通信过程所传输的数据的size,已经消耗的size,真正数据的地址.
/*
* On 64-bit platforms where user code may run in 32-bits the driver must
* translate the buffer (and local binder) addresses appropriately.
*/
struct binder_write_read {
binder_size_t write_size; /* bytes to write */
binder_size_t write_consumed; /* bytes consumed by driver */
binder_uintptr_t write_buffer;
binder_size_t read_size; /* bytes to read */
binder_size_t read_consumed; /* bytes consumed by driver */
binder_uintptr_t read_buffer;
};
- write_xx表示从用户空间传输到binder驱动程序的数据,如果write_xx不为0,表示用户空间有数据需要传递给binder 驱动程序处理。
- read_xx表示binder驱动程序返回给用户空间的数据。如果read_size 不为0,表示用户空间需要等待驱动