细读《深入理解 Android 内核设计思想》(三)Binder 机制 [上]

对冗余挑拣重点,对重点深入补充,输出结构清晰的精简版

1.必备知识
设备驱动
文件描述符
页框
2.Binder 概述
3.binder 驱动
binder_open
binder_mmap
binder_ioctl
4.Service Manager
启动
注册与查询
5.最后

必备知识

设备驱动

Linux 把所有的硬件访问都抽象为对文件的读写、设置,这一"抽象"的具体实现就是驱动程序。驱动程序充当硬件和软件之间的枢纽,提供了一套标准化的调用,并将这些调用映射为实际硬件设备相关的操作,对应用程序来说隐藏了设备工作的细节。

Linux 设备分为三类,分别是字符设备、块设备和网络设备:

1.字符设备: 能够像字节流(类似文件)一样被访问的设备。对字符设备进行读/写操作时,实际硬件的 I/O 操作一般也紧接着发生。字符设备驱动程序通常都会实现 open、close、read 和 write 系统调用,比如触摸屏、键盘、串口、LCD、LED 等。
2.块设备: 指通过传输数据块(一般为 512 或 1k)来访问的设备,比如硬盘、SD卡、U盘、光盘等。
3.网络设备: 能够和其他主机交换数据的设备,比如网卡设备、蓝牙设备等。

通过 cat /proc/devices 命令可以查看字符设备和块设备:

Character devices:
  1 mem
  4 ttyS
 10 misc
   ...
Block devices:
  1 ramdisk
  7 loop
  8 sd
   ...

可以看到属于字符设备的 misc 杂项设备,设备号为 10。通过 ls /dev -l 命令可以查看具体的注册设备:

crw-rw-rw- 1 root   root    10,  61 2020-03-16 16:52 ashmem
crw-rw-rw- 1 root   root    10,  58 2020-03-16 16:52 binder
...

其中 Ashmem、Binder 的设备号是 10,都属于 misc 杂项设备,10 是 主设备号,61、58 叫做 从设备号,有了主、从设备号,就可以唯一标识一个设备。

文件描述符

Linux 中一切都可以看作文件,包括普通文件、链接文件、Socket 以及设备驱动等,对其进行相关操作时,都可能会创建对应的文件描述符。文件描述符(file descriptor)是内核为了高效管理已被打开的文件所创建的索引,用于指代被打开的文件,对文件所有 I/O 操作相关的系统调用都需要通过文件描述符。

文件描述符与文件是什么关系呢?下图 Linux 中的三张表可以体现:

  • 进程级别的文件描述符表:内核为每个进程维护一个文件描述符表,该表记录了文件描述符的相关信息,包括文件描述符、指向打开文件表中记录的指针。

  • 系统级别的打开文件表:内核对所有打开文件维护的一个进程共享的打开文件描述表,表中存储了处于打开状态文件的相关信息,包括文件类型、访问权限、文件操作函数(file_operations)等。

  • 系统级别的 i-node 表:i-node 结构体记录了文件相关的信息,包括文件长度,文件所在设备,文件物理位置,创建、修改和更新时间等,“ls -i” 命令可以查看文件 i-node 节点

文件描述符是一种系统资源,可以通过以下命令来查看文件描述符的上限:

#查看所有进程允许打开的最大 fd 数量
126|generic_x86:/ # cat /proc/sys/fs/file-max
174139

#查看所有进程已经打开的 fd 数量以及允许的最大数量
generic_x86:/ # cat /proc/sys/fs/file-nr
11040   0       174139

#查看单个进程允许打开的最大 fd 数量.
generic_x86:/ # ulimit -n
32768

也可以查看某进程当前已使用的 fd :

#查看某进程(进程 id 为 15077)已经打开的 fd
generic_x86:/ # ls -l /proc/15077/fd/
total 0
lrwx------ 1 u0_a136 u0_a136 64 2020-04-15 23:04 0 -> /dev/null
lrwx------ 1 u0_a136 u0_a136 64 2020-04-15 23:04 1 -> /dev/null
lrwx------ 1 u0_a136 u0_a136 64 2020-04-15 23:04 35 -> /dev/binder
lrwx------ 1 u0_a136 u0_a136 64 2020-04-09 01:01 44 -> socket:[780404]
lrwx------ 1 u0_a136 u0_a136 64 2020-04-15 23:04 55 -> /dev/ashmem
lrwx------ 1 u0_a136 u0_a136 64 2020-04-15 23:04 60 -> /dev/ashmem
...

上面这个进程是一个 Android 应用进程,所以能看到 ashmem、binder 等 Android 特有设备文件相关的 fd 。再来看一个实际打开磁盘文件的例子:

     File file = new File(getCacheDir(), "testFdFile");
     FileOutputStream out = new FileOutputStream(file);

执行上面代码后会申请一个对应的 fd:

# ls -l /proc/{pid}/fd/
...
l-wx------ u0_a55   u0_a55  2020-04-16 00:24 995 -> /data/data/com.example.test/cache/testFdFile
...

实际开发中,可能会遇到 fd 资源超过上限导致的 “Too many open files” 之类的问题,一般都是因为没有及时释放掉 fd,比如上面代码中 FileOutputStream 没有关闭,若循环执行超过单个进程允许打开的最大 fd 数量,程序就会出现异常。

页框

页框(Page Frame)是指一块实际的物理内存块,页是指程序的一块内存数据单元。内存数据一定是存储在实际的物理内存上,即页必然对应于一个页框,页数据实际是存储在页框上的。

页框和页一样大,都是内核对内存的分块单位。一个页框可以映射给多个页,也就是说一块实际的物理存储空间可以映射给多个进程的多个虚拟内存空间,这也是 mmap 机制依赖的基础规则。

Binder 概述

不同进程处于不同的内存空间,具有不同的虚拟地址映射规则,所以不能直接通信。 Binder 是 Android 中使用最广泛的 IPC 机制,正因为有了 Binder,Android 系统中形形色色的进程与组件才能真正统一成有机的整体。Binder 通信机制与 TCP/IP 有共通之处,其组成元素可以这样来类比:

  • binder 驱动 -> 路由器
  • Service Manager -> DNS
  • Binder Client -> 客户端
  • Binder Server -> 服务器

Binder 的本质目标就是客户端要与服务器通信,但由于是不同的进程,必须通过 binder 驱动(路由器)把请求正确投递到对方进程中,所以通信的进程需要持有一个唯一的 Binder 标志(IP 地址)。

而 Binder 标志可能是会动态更新的 “IP 地址”,对通信进程来说获取难度较大且可读性差,这就需要一个 Service Manager(DNS)来解决这个问题。但 Service Manager 自身也是一个 Binder Server(服务器),怎么找到它的 "IP 地址"呢?Binder 机制对此做了特别规定:Service Manager 在 Binder 通信过程中的唯一标志永远是 0。

binder 驱动

binder 驱动运行在内核态,向上层提供 /dev/binder 设备节点,并不对应真实的硬件设备。binder 驱动的注册逻辑在 Binder.c 中:

//drivers/staging/android/Binder.c
static init __init binder_init(void){
   
    ...
    ret = misc_register(&binder_miscdev); //注册为 misc 驱动
}

binder_miscdev 即 Binder 设备描述如下:

static struct miscdevice binder_miscdev = {
   
    .minor = MISC_DYNAMIC_MINOR, //自动分配次设备号
    .name = "binder", //驱动名称
    .fops = &binder_fops //binder 驱动支持的文件操作
}

binder_fops 为 Binder 设备支持的操作函数,如下:

static const struct file_operations binder_fops = {
   
    .owner = THIS_MODULE,
    .poll = binder_poll,
    .unlocked_ioctl = binder_ioctl,
    .mmap = binder_mmap,
    .open = binder_open,
    .flush = binder_flush,
    .release = binder_release,
};

与 Ashmem 设备类似,最关键的是 binder_open()、binder_mmap()、binder_ioctl(),下面分别介绍这三个函数。

binder_open

用户应用程序通过 Binder 通信时,需先调用 binder_open() 方法打开 binder 驱动,binder_open() 中主要做了两个工作,对应的分为两部分来看:

//binder.c
static int 
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Firefly-RK3399的Android10中的pdf_20211123_1657.7z a4_portrait_rgbb.pdf a5_portrait_rgbb.pdf a5_portrait_rgbb_1_6_printscaling_default.pdf a5_portrait_rgbb_1_6_printscaling_none.pdf aacDecoder.pdf aacEncoder.pdf about_blank.pdf Android_malloc_debug.pdf annotation_highlight_long_content.pdf annotation_highlight_rollover_ap.pdf annotation_highlight_square_with_ap.pdf annotation_ink_multiple.pdf annotation_stamp_with_ap.pdf annotiter.pdf barcode_test.pdf BHUSA2014-capstone.pdf black.pdf bookmarks.pdf bookmarks_circular.pdf brotli-comparison-study-2015-09-22.pdf bug_113.pdf bug_213.pdf bug_216.pdf bug_298.pdf bug_325_a.pdf bug_325_b.pdf bug_343.pdf bug_344.pdf bug_355.pdf bug_360.pdf bug_451265.pdf bug_451830.pdf bug_452455.pdf bug_454695.pdf bug_455199.pdf bug_459580.pdf bug_481363.pdf bug_487928.pdf bug_507316.pdf bug_544880.pdf bug_547706.pdf bug_551248.pdf bug_551460.pdf bug_552046.pdf bug_554151.pdf bug_555784.pdf bug_557223.pdf bug_57.pdf bug_572871.pdf bug_583.pdf bug_601362.pdf bug_602650.pdf bug_603518.pdf bug_620428.pdf bug_631912.pdf bug_634394.pdf bug_634716.pdf bug_644.pdf bug_650.pdf bug_664284.pdf bug_679649.pdf bug_680376.pdf bug_707673.pdf bug_709793.pdf bug_713197.pdf bug_717.pdf bug_750568.pdf bug_757705.pdf bug_765384.pdf bug_779.pdf bug_781804.pdf bug_782596.pdf bug_921.pdf bug_xrefv4_loop.pdf CameraITS.pdf camera_engine_rkisp_user_manual_v2.2.pdf camera_hal3_user_manual_v2.3.pdf checkerboard.pdf circular_viewer_ref.pdf combobox_form.pdf control_characters.pdf default-values-ip.pdf DngNoiseModel.pdf Drm_Vendor_Modules_v1.pdf dynamic_list_box_allow_multiple_selection.pdf dynamic_password_field_background_fill.pdf dynamic_table_color_and_width.pdf EASLibrary3_5.pdf EAS_API_Reference.pdf EAS_Library_Integration_Guide.pdf Efuse process explain .pdf email_recommended.pdf embedded_attachments.pdf embedded_images.pdf encrypted.pdf feature_linearized_loading.pdf fieldsmanagement.pdf first.pdf hello_world.pdf ic_brightness_medium_24dp.pdf ic_radio_button_check
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值