- 博客(383)
- 收藏
- 关注
原创 Binder 专题5——Binder 服务获取与使用过程分析 C 语言篇
本文分析了Binder机制中客户端获取服务的过程。客户端通过svcmgr_lookup发起远程调用获取服务的handle值,构造binder_io数据后调用binder_call与服务器通信。ServiceManager被唤醒后解析数据,通过binder_parse处理BR_TRANSACTION命令,最终调用svcmgr_handler回调函数完成服务查找。整个过程展示了Binder跨进程通信的核心流程,包括数据封装、远程调用和回调处理。
2026-02-25 17:31:12
557
原创 Binder 专题4——Binder程序示例 C 语言篇
本文介绍了Binder驱动在C语言层的应用实现,主要聚焦应用层与Binder驱动的交互流程。首先阐述了Binder驱动通过open()、mmap()和ioctl()等系统调用提供的接口功能。接着详细说明了使用frameworks/native/cmds/servicemanager下的binder.c进行应用程序开发的方法,包括binder_open、binder_call等关键函数的封装。 重点分析了Server端的实现过程:定义服务函数、编写服务回调函数处理远程调用请求,以及主函数流程(初始化Binde
2026-02-25 16:56:11
210
原创 Binder 专题3——Binder 基本原理
本文介绍了Android Binder框架的基本原理和工作流程。Binder是一个RPC(远程过程调用)框架,通过内核地址空间实现跨进程数据传输。其核心原理包括:1)利用内核共享内存减少数据拷贝次数;2)通过Handle和Code标识目标进程与函数;3)采用标准的打包/解析数据格式。应用层工作流程涉及Binder服务端、客户端和服务管家(ServiceManager)三个角色,包括服务注册、查询和远程调用三个关键步骤。Binder驱动为整个机制提供底层支持,实现了进程间的高效通信。
2026-02-25 15:40:00
564
原创 Binder 专题2——学习 Binder 的预备知识
本文介绍了Linux驱动开发的基础知识,包括如何编写和编译一个简单的内核模块,以及Linux中文件读写的基本原理。主要内容分为三部分: 内核模块开发:通过一个"Hello World"示例演示了内核模块的基本结构,包括初始化函数(hello_init)和退出函数(hello_exit)的编写方法,以及如何将模块编译进内核或生成独立模块文件。 文件系统接口:解释了Linux中"一切皆文件"的设计理念,介绍了open、read、write、ioctl和close等关键文件
2026-02-25 14:43:24
632
原创 Binder 专题1——如何深入掌握 Binder
文章摘要 本文系统介绍了Android Binder框架的学习路径,从基础理论到各层实现。首先阐述了学习Binder的必要性,包括系统服务开发和应用问题排查。然后提出了需要掌握的预备知识,如Linux驱动开发、虚拟内存等。文章详细讲解了Binder的学习步骤:从基本原理理解,到C层封装实现,再到驱动层核心机制分析,最后深入C++和Java层的具体实现。特别强调了Binder在IPC和RPC方面的工作原理,以及常见疑难问题的分类和解决方法,为Android开发者提供了全面的Binder学习指南。
2026-02-25 11:15:45
270
原创 Android 日志系统7——Android 平台日志丢失问题分析
摘要 本文分析了Android平台日志丢失的常见原因及典型案例,主要包括:1)业务日志输出频率过高导致socket处理能力不足;2)整机负载过高导致logd无法获取CPU资源;3)存储异常导致日志无法落盘;4)低内存导致日志进程被杀。同时指出日志打印会带来跨进程通信、内存、CPU、IO等多方面资源消耗,建议在正式版本中规范日志打印,建立故障检测机制,避免影响系统性能。通过典型案例分析和思维导图,为工程师提供了日志丢失问题的系统分析方法。
2026-02-12 15:13:31
1023
原创 Android 日志系统6——logd 读日志过程分析
本文分析了Android logd服务中LogReader的初始化过程。LogReader在main函数中被创建,负责监听/dev/socket/logdr套接字。其初始化过程包括:获取日志套接字描述符、初始化SocketListener父类、设置监听参数。随后启动监听线程,通过poll机制等待客户端连接或命令管道事件。当有新连接时,会触发后续处理流程将日志缓冲区内容写入客户端。整个初始化过程完成了日志读取服务的基础设施搭建,为后续日志读取功能做好准备。
2026-02-12 14:50:53
855
原创 Android 日志系统5——logd 写日志过程分析二
文章摘要: 本文分析了Android日志系统logd中日志写入的详细过程。首先,SocketListener通过onDataAvailable()方法接收应用程序发送的日志数据,包括设置线程名称、获取客户端身份凭证、处理特殊值等步骤。然后,日志数据被写入LogBuffer,该过程包含四个关键步骤:数据校验、使用状态机去重、实际写入操作以及必要时删除旧日志以控制总量。文章详细展示了日志从应用程序通过socket传输到最终存储的完整流程,涉及关键的数据结构和系统调用,如prctl、recvmsg等。
2026-02-12 13:57:36
539
原创 Android 日志系统4——logd 写日志过程分析一
本文摘要: 文章分析了Android logd服务中LogBuffer的初始化过程。LogBuffer是日志系统的核心缓冲区,负责存储和管理所有日志条目。初始化过程包括:1) 创建LastLogTimes列表;2) 初始化读写锁;3) 为每种日志类型(MAIN/RADIO/EVENTS等)初始化lastLoggedElements和droppedElements指针;4) 设置各日志类型的缓冲区大小;5) 处理时间格式变化时的日志时间戳转换。文章详细介绍了LogBuffer的数据结构,包括日志类型枚举、元素
2026-02-12 13:34:03
625
原创 Android 日志系统3——写日志过程分析
本文分析了Android系统中日志写入的客户端接口流程。首先介绍了Java层的Log.java等接口封装,通过JNI调用Native层实现。详细追踪了从Log.d()调用到println_native()的JNI实现过程,核心是通过__android_log_buf_write()函数处理日志信息,最终转换为iovec结构并通过write_to_log函数指针写入。Native层也提供了类似的日志写入方式,整体流程都是建立socket连接后发送数据。文章梳理了日志从应用层到Native层的完整传递路径,揭示
2026-02-11 17:13:18
759
原创 Android 日志系统2——logd 守护进程
文章摘要:本文分析了Android系统中logd守护进程的初始化过程。logd通过system/core/logd/logd.rc定义了两个服务,初始化了三个socket连接和两个内核日志文件接口。在system/core/logd/main.cpp中,程序首先处理reinit参数,然后获取/proc/kmsg和/dev/kmsg文件描述符,用于与内核日志系统通信。最后初始化多个信号量并创建线程,为后续日志处理做好准备。整个初始化过程确保了系统日志服务的可靠运行和日志信息的完整收集。
2026-02-11 16:30:40
852
原创 Android 日志系统1——整体框架
Android日志系统框架概述 Android日志系统包含多种日志类型:main(应用层日志)、radio(无线通信日志)、events(系统诊断日志)、system(系统应用日志)和crash(崩溃日志)。应用层通过Java的android.util.Log或Native的__android_log_print写入日志,内核层使用printk函数记录日志到/proc/kmsg。系统启动时logd进程会创建三个核心线程:LogListener(接收应用日志写入请求)、LogReader(处理logcat读取
2026-02-11 16:13:05
848
原创 Android socketpair 使用
本文介绍了Android中socketpair的基本使用。socketpair是一种匿名套接字对,无需连接即可实现双向通信,适用于两个进程间的直接通信。文章详细说明了socketpair的API参数及使用注意事项,包括全双工通信特性、读写规则等,并提供了同进程和不同进程的两个示例代码。这些示例展示了如何创建socketpair套接字对,以及在不同场景下进行读写操作的方法,为开发者使用socketpair进行进程间通信提供了参考。
2026-02-11 15:06:41
322
原创 Android 中的 Unix Domain Socket
本文摘要: Android系统通过rc文件定义Unix Domain Socket,由init进程在/dev/socket/目录下创建。rc文件中socket命令格式为"socket <name> <type> <perm> [user] [group]",支持stream、dgram、seqpacket三种类型。系统核心组件如logd、zygote等都通过这种方式创建socket。底层实现通过socket()系统调用创建AF_UNIX域socket,
2026-02-11 14:49:50
347
原创 Unix Domain Socket —— TCP 篇
本文介绍了Unix Domain Socket在Android Framework Native层的应用及其TCP相关API。Unix Domain Socket是一种高效的进程间通信(IPC)机制,相比网络socket省去了协议栈开销。文章详细讲解了TCP编程的核心API,包括socket创建、bind绑定、listen监听、accept接受连接、recv/send数据读写等,并提供了服务端和客户端的示例代码。服务端通过socket()创建套接字,bind()绑定地址,listen()监听连接,accep
2026-02-11 14:18:42
1031
原创 Unix Domain Socket —— UDP 篇
Unix Domain Socket UDP 通信摘要 本文介绍了Unix Domain Socket在UDP模式下的进程间通信实现。Unix Domain Socket是一种高效的IPC机制,相比网络Socket避免了协议栈开销,直接进行进程间数据拷贝。文章详细讲解了UDP通信的关键API: 创建Socket:使用socket()函数指定AF_UNIX域和SOCK_DGRAM类型 绑定地址:通过bind()将Socket与sockaddr_un结构体指定的路径绑定 数据传输:使用sendto()和recv
2026-02-11 13:54:52
622
原创 Android 属性系统6——系统源码分析二
本文分析了Android属性服务的启动过程及客户端初始化机制。在init进程中,通过StartPropertyService()创建Socket服务并绑定epoll回调,接收属性设置请求后调用HandlePropertySet()处理。客户端方面,bionic库的__libc_preinit()函数会在程序加载libc.so时尽早执行,完成属性系统的初始化工作。整个流程展示了属性服务基于Socket通信的实现原理,以及系统启动时属性机制的初始化时序。
2026-02-10 16:49:57
522
原创 Android 属性系统5——系统源码分析一
本文分析了Android属性系统的初始化过程,重点解析了property_info文件的生成机制。系统启动时,init进程会创建/dev/__properties__目录,通过LoadPropertyInfoFromFile加载各分区的属性安全上下文文件,使用BuildTrie构建字典树并序列化,最终将序列化数据写入property_info文件。该过程为后续属性加载和使用奠定了基础,确保系统属性能够安全高效地存储和访问。整个架构采用mmap内存映射方式,只有init进程拥有写权限,其他进程通过Proper
2026-02-10 16:32:22
769
原创 Android 属性系统4——属性与 Selinux
本文介绍了在Android O之后如何配置SELinux规则以实现自定义属性的读写权限。主要内容包括: 创建示例程序prop_test,实现读取系统属性ro.build.version.release和读写自定义属性vendor.my.prop.test的功能 配置SELinux相关文件: property.te定义属性类型vendor_mytest_prop property_contexts设置自定义属性的安全上下文 prop_test.te定义可执行文件类型、域转换规则和属性读写权限 file_con
2026-02-10 15:22:23
293
原创 Android 属性系统3——添加系统属性
本文介绍了在Android系统中添加自定义系统属性的三种方法:1) 通过修改/system/build.prop文件,需在device目录下创建system.prop文件并配置BoardConfig.mk;2) 通过修改/vendor/build.prop文件,在device的mk文件中配置PRODUCT_PROPERTY_OVERRIDES变量;3) 通过修改/product/build.prop文件,可在mk文件中配置PRODUCT_PRODUCT_PROPERTIES变量。每种方法都提供了具体实现步骤
2026-02-10 14:43:00
331
原创 Android 属性系统2——属性文件生成过程
本文分析了Android系统中属性文件(如/system/build.prop)的生成过程。通过追踪build/make/tools/buildinfo_common.sh脚本发现,该脚本被Makefile调用,通过echo命令输出系统属性信息。核心函数generate-common-build-props-with-product-vars-set负责收集构建指纹、ID、版本号等关键信息,并将结果重定向到中间文件,最终生成各分区的属性文件。这些属性文件包含了设备品牌、型号、制造商等产品信息,为系统提供了重
2026-02-10 14:15:39
340
原创 Android 属性系统1——简介及作用
摘要 Android属性系统采用key-value形式统一管理系统配置,属性文件以.prop为后缀,由init进程启动时加载。主要属性文件包括/default.prop、/system/build.prop等,加载顺序决定属性覆盖关系。属性分为普通属性、只读属性(ro开头)、网络属性(net开头)、持久化属性(persist开头)以及服务控制属性(ctrl.start/stop)。持久化属性会保存在/data/property/目录下,重启后仍有效。系统通过共享内存机制管理这些属性,支持通过shell命令、
2026-02-10 13:46:27
589
原创 IdleHandler 原理与使用
IdleHandler是Android消息机制中的一种空闲任务处理机制,当Looper没有消息需要处理时,会执行注册的IdleHandler任务。其使用方式是实现IdleHandler接口的queueIdle()方法,并通过MessageQueue的add/remove方法进行注册和注销。源码分析表明,IdleHandler的执行时机是在MessageQueue空闲时(无消息或消息未到触发时间),通过next()方法中的循环处理所有注册的IdleHandler。如果queueIdle()返回false,该H
2026-02-09 17:03:57
761
原创 Handler 同步屏障机制
本文摘要: Handler消息机制中的同步屏障机制详解。文章介绍了三种消息类型(普通消息、异步消息、屏障消息),重点分析了同步屏障的工作原理。通过postSyncBarrier()方法插入屏障消息(target为null的特殊消息),屏障会阻挡后续普通消息,仅允许异步消息通过。在next()方法中,遇到屏障时会跳过同步消息直到找到异步消息。最后可通过removeSyncBarrier()移除屏障。该机制确保了异步消息的优先处理,是Android UI渲染等场景的重要基础。
2026-02-09 16:33:06
891
原创 Android Java Looper 机制
Android Java Looper机制通过无限循环和事件通知实现线程长时间运行。核心流程包括:1)Looper.prepare()初始化线程专属Looper并创建MessageQueue;2)Native层初始化eventfd和epoll监听;3)Looper.loop()进入消息循环处理。其他线程通过Handler发送消息到Looper线程的消息队列,唤醒目标线程处理。该机制实现了Android线程间的高效通信。
2026-02-09 15:31:55
1826
原创 Android Native Looper 机制
本文摘要: Android Native Looper机制通过epoll实现事件循环,核心功能包括休眠等待和事件处理。其实现要点如下: 初始化:Looper::prepare()调用epoll_create创建epoll实例 事件注册:addFd()封装epoll_ctl,将binder_fd/timerfd等注册到epoll 事件循环:pollAll()底层调用epoll_wait实现阻塞等待 回调处理:事件触发后通过event.data.ptr调用注册的回调函数 该机制通过eventfd+epoll实现
2026-02-06 16:08:03
781
原创 Linux timerfd 的基本使用
Linux timerfd 是一种基于文件描述符的定时器接口,支持纳秒级精度和周期性定时。相比传统信号定时器,它具有无信号干扰、支持IO多路复用等优势。核心API包括:timerfd_create()创建定时器、timerfd_settime()配置定时参数、timerfd_gettime()查询状态。定时器超时后会触发文件描述符可读事件,通过read()可获取超时次数。典型应用场景包括将定时事件融入epoll事件循环,实现高精度定时任务。使用时需注意时钟源选择(CLOCK_MONOTONIC推荐)和定时模
2026-02-05 14:43:33
878
原创 Linux IO 多路复用 epoll 机制
Linux IO多路复用epoll机制是一种高效管理多文件描述符(fd)的技术,通过单线程同时监听多个fd的IO事件,避免资源浪费。相比select/poll,epoll解决了fd数量限制、轮询效率低和内核态拷贝开销等问题。其核心包括epoll实例(epfd)、事件注册(epoll_ctl)和事件等待(epoll_wait)三个操作,采用红黑树和就绪链表数据结构实现高效管理。epoll支持水平触发(LT)和边缘触发(ET)两种模式,Android底层主要使用LT模式确保稳定性。该机制适用于支持poll接口的
2026-02-04 16:17:48
1191
原创 Linux eventfd 原理与实践
本文介绍了Linux中的eventfd机制及其应用。eventfd是一种用于进程间或用户态与内核态通信的文件描述符类型,基于64位计数器实现。主要内容包括: eventfd原理:通过内核维护的计数器实现,write递增计数,read读取并清零计数。计数器不为零时触发可读事件。 使用方法: 初始化:使用eventfd()创建,可设置初始值和标志 读写操作:只能处理8字节数据,write累加计数,read获取当前值并清零 事件监听:可通过epoll监控读事件(因一直可写) 典型应用场景: 磁盘异步IO(liba
2026-02-04 13:47:51
575
原创 弱引用 wp 的作用
本文探讨了Android智能指针中弱引用(wp)的作用。通过示例分析循环引用导致的内存泄漏问题:当两个对象互相持有对方的强引用(sp)时,引用计数无法归零造成内存无法释放。解决方案是将其中一个引用改为弱引用(wp),这样在作用域结束时能正确触发析构链,最终使引用计数归零完成内存回收。弱引用的核心价值在于解决循环引用导致的广义"死锁"问题,同时兼顾指针缓存功能,避免阻止资源释放。
2026-02-03 16:33:41
345
原创 Android 平台智能指针使用与分析
本文摘要: Android智能指针机制通过RefBase类及其子类实现自动内存管理。系统提供强引用(sp)和弱引用(wp)两种指针类型,通过引用计数控制对象生命周期。强引用可直接操作对象,而弱引用需先通过promote()升级为强引用。智能指针支持两种模式:OBJECT_LIFETIME_STRONG(默认)和OBJECT_LIFETIME_WEAK,通过extendObjectLifetime()切换。Android12引入sp::make()静态方法,简化了智能指针创建过程,避免裸指针暴露风险。底层实现
2026-02-03 14:43:24
1040
原创 C++进阶指南1——vector基础
本文介绍了C++中vector容器的基本概念和常用操作。vector是一个能自动扩容的动态数组,相比普通数组更加灵活。使用前需包含<vector>头文件并指定命名空间。主要功能包括:创建空vector或指定大小/初始值的vector;通过push_back()添加元素;使用下标或at()访问元素;通过下标或at()修改元素;利用pop_back()、erase()或clear()删除元素。还介绍了size()和capacity()的区别,以及reserve()预分配空间的优化技巧。vector作
2026-01-30 16:49:52
337
原创 JNI 编程指南12—— JNI多线程
本文介绍了JNI环境下多线程编程的核心要点:JNIEnv是线程作用域的变量,不能跨线程传递;局部引用不能跨线程使用。通过示例代码演示了如何在子线程获取JNIEnv,以及使用全局引用跨线程回调Java方法的技术要点。关键点包括:通过JavaVM获取线程专属JNIEnv、使用NewGlobalRef创建全局引用、通过标志位同步线程释放资源。文章提供了完整的Java和C++代码示例,说明了多线程JNI编程的正确实践方法。
2026-01-30 15:30:38
441
原创 JNI 编程指南11—— JNI 调用性能优化
本文介绍了两种优化JNI调用性能的方法:使用时缓存和静态初始化缓存。由于JNI调用比Java方法调用耗时更多,建议减少调用次数并批量处理任务。重点是通过缓存GetMethodID等返回的ID值来避免重复查找,提升性能。使用时缓存通过全局变量保存methodID,仅在首次调用时获取;静态初始化缓存在类加载阶段通过native方法预先获取并缓存ID。两种方法都有效减少了不必要的JNI调用开销,以空间换时间提高执行效率。
2026-01-30 14:29:13
288
原创 JNI 编程指南10——从内存角度看引用类型
本文从内存角度分析了JNI中的三种引用类型:局部引用、全局引用和弱全局引用。Java程序内存分为Java Memory和Native Memory,JNI引用类型是指向JVM中Java对象内存的指针。局部引用存储在Local Reference Table中,生命周期限于当前Native方法调用;全局引用可跨线程使用,需手动释放;弱全局引用可能被GC随时回收,使用时需通过NewLocalRef创建临时强引用避免被回收。文章详细解析了三者的内存管理机制和使用注意事项,并提供了代码示例说明正确使用弱全局引用的方
2026-01-30 13:52:59
599
原创 JNI 编程指南9——异常处理
本文介绍了JNI程序中的异常处理机制。主要分为两类:一是JNIEnv内部函数抛出的异常,通过检查返回值判断异常后直接return,JVM会将异常传递给Java层;二是Native回调Java方法时抛出的异常,可通过Java层try-catch捕获或Native层处理。Native层处理异常时,可使用ExceptionCheck检测异常、ExceptionOccurred获取异常对象,并选择清除异常或抛出新异常给Java层。文章通过具体代码示例演示了这两种异常处理方式的实际应用场景和处理流程。
2026-01-29 17:36:05
313
原创 JNI 编程指南8——Native 访问 Java
本文介绍了在JNI开发中如何访问Java成员变量和方法。主要内容包括:1)通过GetFieldID获取成员变量ID,使用Get/SetObjectField访问和修改成员变量值;2)通过GetMethodID获取方法ID,使用CallVoidMethod调用Java方法;3)静态成员的访问方式与实例成员类似,但需要使用GetStaticFieldID和CallStaticVoidMethod;4)强调了对jclass对象和局部引用的内存管理,需要及时调用DeleteLocalRef释放资源。文章通过具体代码
2026-01-29 16:37:00
293
原创 JNI 编程指南7——数组访问
本文介绍了JNI中数组访问的相关技术,包括基本类型数组、引用类型数组和二维数组的处理方法。在基本类型数组中,通过GetIntArrayElements等函数获取数组指针进行操作;引用类型数组使用GetObjectArrayElement访问元素;二维数组则需要嵌套获取行列数据。文章还列举了关键JNI函数如GetArrayLength、NewObjectArray等的用法说明,并提供了完整的代码示例,展示了如何在JNI层与Java层之间传递和操作各类数组数据。
2026-01-29 15:40:23
745
原创 JNI 编程指南6——字符串处理
本文介绍了JNI中字符串处理的相关函数和方法。主要内容包括:1)JNI字符串处理示例,展示如何将Java字符串转换为C字符串并返回;2)详细解析了GetStringUTFChars、ReleaseStringUTFChars、NewStringUTF等核心函数的功能和参数说明;3)介绍了字符串长度获取、字符数组转换等相关辅助函数;4)特别说明了GetStringCritical/ReleaseStringCritical这对高效但有限制的函数。文章强调在使用这些函数时要注意内存管理、异常处理和编码转换等问题
2026-01-28 17:33:03
476
原创 JNI 编程指南5——JavaVM 详解
本文摘要: JavaVM是描述Java虚拟机的结构体,在Android平台上一个进程只对应一个ART虚拟机和JavaVM对象。文章详细介绍了JavaVM在C/C++中的不同定义方式,以及其核心成员函数如DestroyJavaVM、AttachCurrentThread等。同时提供了两种获取JavaVM的方法:在JNI_OnLoad函数中通过参数直接获取,或通过JNIEnv的GetJavaVM函数间接获取。这些内容为理解JNI编程中JavaVM的使用提供了基础指导。
2026-01-28 16:31:07
295
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅