- 博客(317)
- 收藏
- 关注
原创 属性服务端的启动以及通信架构
PropertyServiceThreadhandle_property_set_fd、PROP_MSG_SETPROP 和 PROP_MSG_SETPROP2persist_write_thread总结
2026-01-06 23:11:05
388
原创 Property Service源码分析
这个主要是初始化系统属性区域,加载内核和设备树的属性配置,并设置默认的启动属性。它是 Android 启动过程中非常关键的一部分,用于确保系统属性在启动时被正确加载和管理。这些属性会影响系统配置、启动行为、安全策略等各个方面:加载并初始化了以下属性相关内容:selinux 回调创建 创建序列化的属性信息 属性共享内存初始化 加载序列化属性信息的默认路径文件 处理来自内核设备树的参数 处理来自命令行的属性 处理来自boot 的属性 导出内核
2026-01-06 22:24:20
208
原创 Android 系统 Init 进程的初步介绍
硬件启动 → Boot ROM → Boot Loader。加载内核 → 初始化硬件、进程调度、驱动。启动用户空间 → Init → 系统服务与守护进程。启动 Java 框架 → Zygote → 系统服务(System Server)。启动应用层 → Launcher → 用户交互。
2026-01-05 23:02:03
546
原创 Android属性系统之代码操作属性
编译报错了,意思是不允许domain主域访问property_type类型的资源,除了-system_property_type, 和-product_property_pype,或者-vendor_property_type。没有对这个 vendor.my.work.time 属性设置相关标签,无法访问 vendor 的东西。从结果上看还是有几个问题的,没有设置属性,停止和开启服务的权限。日志上看,设置属性,停止,开启服务都成功了。从这里也可以看到,属性的值也成功设置上去了。原因也是没有权限的访问规则。
2026-01-04 11:56:40
397
原创 Android属性系统之属性文件
就是build.prop, default.prop, xxx.prop等,以prop结尾的这些文件称为属性文件。这些build.prop属性文件是按不同分区来划分,可能位于不同的分区镜像之中。
2026-01-03 11:56:47
145
原创 Android属性系统之属性技术原理
属性的存储,存在/dev/__properties__目录下,里面有许多的安全上下文件的文件,存放着具有相同安全上下文的属性,里面以树型结构算法的方式存放key与value。5. 属性文件从哪里来?从源码中编译出来的:如/system/build.prop vendor/build.prop default.prop等。对set而言,属性服务还需要对客户端的selinux权限进行判断。/property_info: 作用,存放每个属性的selinux信息。这个与属性信息文件/dev/
2026-01-03 11:49:01
304
原创 Android属性系统之属性基础
为什么需要persist这种属性:属性是共享内存,会掉电丢失,除非是编译自动生成的。ro.kernel.xxx:这个属性来自uboot以及内核参数传递至安卓系统中。persist.xx.xx.xx表示永久化,启动后不丢失,但是可以写。init.svc.xxx: 由init启动的一些服务进程的属性。文件中的属性(默认属性)。而persist开头的属性会保存在。安卓系统的属性名称格式:xx.xx.xx.xx 有点像域名。ro.xxx.xx均是只读的属性,不能set.因为永久化的本质就是文件存储。
2026-01-03 11:25:49
151
原创 SElinux策略文件配置
上面导入的是build/make/target/board/emulator_x86_64/BoardConfig.mk,于是需要在这个文件中配置sepolicy所在的路径,这样系统可以将其加入编译到selinux_policy。因为切换进程域的时候,如果是由shell指令去切换,将切换成对应的sedemo_dt这个域,sedemo_dt_exec是类型。经过前面的一大堆理论的学习,我们知道,还需要编写相关的规则文件,才能通过 SElinux 的检测。切换,上下文标签已经是我们定义的了。
2025-12-13 01:17:12
468
原创 Selinux权限的检测
当主体要真正去访问客体资源的时候,会去触发安全的认证的检测过程,比如说它有对应的权限,放行,如果没对应的权限,就访问失败,问题是,由谁来监控权限的合法性工作?,这个监控是谁来做的,其实也是安全服务SecurityServer来处理,需要由linux内核LSM的支持, 翻译过来是Linux Secrity Module的简称, 它是内核的一个子系统,有一个概念前提大家要了解:所有定义的标签和规则,最终都会被写入到linux内核中。涉及策略规则的编译过程。
2025-12-12 22:47:23
257
原创 Selinux Context上下文
那么问题来了,现在所有的标签都已经准备好了,有file_contexts, genfs_contexts,service_contexts,seapp_contexts,property_contexts,也清楚 我们需要对每个客体所需要的标签是在对应的context_file文件中进行标签的定义,但这只是定义性的。在安卓系统中,一般是通过一些SecurityServer进程,如init进程(但不仅仅只有它), 它可以将上下文标签中的定义,给对应的文件打上标签(上图中也包含了打标签的过程)。
2025-12-12 22:43:06
379
原创 SELinux理论基础
APK->JNI->底层驱动(app操作设备驱点,read, write),可能会遇到权限问题,打开不了,不能读,不能写等问题, 但是在以前早期的版本,可能对节点chmod a+x /dev/xxx 进行权限的设置,就能访问了。但是:开机启动中,根据rc文件提供的启动信息, 会启动一些后台进程,可以在进程对应的rc文件中配置让进程开机启动,但是有可能跑不起来, 如果没有配置selinux相关的策略的话,这是因为app运行的时候,检测安全环境。SELinux (MAC) - 像严格管理的军事图书馆。
2025-12-12 22:39:20
643
原创 SELinux 介绍
SEAndroid 是 SELinux(Security-Enhanced Linux) 在 Android 系统中的实现,SELinux 是一个强制访问控制(MAC)系统,SEAndroid 将其引入以加强 Android 的安全性,主要通过限制应用和系统组件的权限范围,减少安全漏洞被利用的可能性。报错意思是:/vendor 分区在运行的 Android 系统中是只读的,重新挂载 /vendor 为可读写即可。这段代码,看起来应该是没啥难度,对 dev 文件下面的 sedemo_dev 进行写入一句话。
2025-12-12 22:26:56
265
原创 aosp系统中构建编译添加安卓app
通过 AOSP 构建的 APK 通常会被视为系统应用,具有系统应用的权限,甚至是特权。如果你在 AOSP 中使用 Android.mk 编译了 App 并将其放置在系统的分区中(如 /system/app 或 /system/priv-app),该 App 就会被当作系统应用。如果你不希望它成为系统应用,可以通过其他方式安装该 APK,例如通过 adb install 安装到用户空间。
2025-12-06 14:00:27
889
原创 Android 编译脚本 mk & bp
在android 的高版本,13,14,谷歌其实是比较推荐我们使用bp 文件来进行编译,但是旧版本的业务还是存在的,所以需要两者都掌握。Android.mk 中除了编译库文件外,还可以编译可执行文件。静态库使用 include $(BUILD_STATIC_LIBRARY),动态库使用 include $(BUILD_SHARED_LIBRARY)。Android.mk 文件是 Android 构建系统中定义编译规则的配置文件,主要用于描述哪些源文件需要编译,以及如何编译它们。定义可执行文件模块。
2025-12-06 12:36:53
941
原创 Android镜像、分区及其烧录
boot.img-> boot 分区:启动镜像,包含内核和启动引导程序。system.img -> system 分区:系统镜像,包含 Android 系统的核心组件和系统应用。vendor.img-> vendor 分区:供应商镜像,包含设备厂商提供的硬件相关库和驱动。recovery.img -> recovery 分区:恢复镜像,提供系统恢复功能,允许重置和更新系统。userdata.img-> userdata 分区:用户数据镜像,包含用户的应用和数据文件。
2025-12-05 23:33:40
1549
原创 android 有哪些常用的编译命令?
什么是模块的名称:android.mk或android.bp文件中要编译出来的对象的名称C++库:静态库libxxx.a 动态库libxxx.soJava库:***.jarC++可执行程序:JAVA app:编译模块的两种方式:make 模块名mmm 模块名所在的路径。
2025-12-05 22:39:57
273
原创 AOSP 源码阅读工具 ---vim (vim 也能很有趣)
建立索引 ctags -R查看某个文件 find . -name "PackageManagerService.java"跳转 ctrl + ]返回 ctrl + t查看文件 ctrl + f回到前一个文件 shift + : 输入bp列出当前文件所在的目录 F9当然啦,有人会说可以通过vscode 的ssh 连接到源码的服务器,但是vscode 本身建立索引就慢,再加上网络,那就更慢了,有时候搜索某个函数,需要等一小时以上(工作中深有体会)。。。。Android studio 同理。
2025-12-05 22:10:10
317
原创 电脑环境要求 && 源码下载 && 编译
总的来说,在 repo sync -c --no-tags --prune -j 4 命令中,使用 -c 和 --no-tags 选项可以减少需要同步的内容,从而减少要占用的本地代码空间,也可以减少一些同步时间。通俗理解是,Mem 消耗完之后,swap 能帮你硬抗,不至于终端闪退,没有调整之前,swap 是2G, 个人测试,发现,一共需要50G 左右才能满足 aosp 的编译。然后make -j12 进入编译,会进入较长时间的等待,我的电脑花了两个多小时,出现下面的输出代表编译成功了。
2025-11-30 18:34:32
1023
原创 Android 系统常识 && 和Linux 的比较
本文对比了Android与Linux操作系统的异同。两者虽然基于相同的Linux内核,但在架构设计上存在显著差异:Linux采用模块化设计,强调通用性;Android则针对移动设备优化,增加了硬件抽象层和运行时环境。在应用层方面,Linux依赖系统调用和glibc,而Android基于Java/ART虚拟机运行应用。文件系统方面,Android采用分区挂载和沙盒机制,而Linux支持多种文件系统。安全机制上,Android在Linux基础上增加了应用沙盒和权限管理。应用场景方面,Linux适用于服务器/嵌入
2025-11-30 17:47:43
1085
原创 第三章_布莱叶盲文与二进制
这里你可能会想:为什么不直接用三进制、十进制?电路简单:两种状态更容易识别和稳定。容错性高:噪声环境下,区分“有/无”比区分更多层次更可靠。组合能力强:别看只有 0 和 1,但一旦组合,就能表示几乎无限的内容。换句话说,二进制就是最低成本、最高效率的方案。第三章通过布莱叶盲文的故事,让我们直观理解了二进制编码的思想。两种状态就能表示信息。通过组合,可以无限扩展。这就是计算机的底层逻辑。**读完这章我的感受:**复杂的世界往往可以用最简单的方式来描述。
2025-08-30 17:21:13
210
原创 第二章_编码与组合
摘要: 莫尔斯电码用简单的“点”和“划”两个符号,通过组合与指数规律(如2个符号表达4种信息)实现复杂编码。分隔符号(停顿)赋予结构意义,解决信息混乱问题。本章揭示:1. 简单符号通过组合可表达无限信息;2. 数学是编码基础;3. 结构决定信息有效性。编码的本质是以有限表达无限,展现基础符号的强大潜力。(148字)
2025-08-30 17:14:12
388
原创 第一章_之亲密友
《编码》第一章从人类原始沟通方式入手,揭示信息传递的本质是"信号+约定"。通过手电筒闪灯等简单例子,说明复杂信息可由基本符号组合表达。关键在于状态区分和规则建立,这与计算机0/1状态的原理相通。本章虽未直接讨论二进制,却为理解计算机编码奠定了思维基础——简单规则能创造无限可能,这正是从原始沟通到数字世界的演化逻辑。
2025-08-26 22:03:48
227
原创 内核-mmap
ARM 架构支持一级页表映射,也就是说 MMU 根据 CPU 发来的虚拟地址可以找到第 1 个页表,从第 1 个页表里就可以知道这个虚拟地址对应的物理地址。一级页表里地址映射的最小单位是 1M。ARM 架构还支持二级页表映射,也就是说 MMU 根据 CPU 发来的虚拟地址先找到第 1 个页表,从第 1 个页表里就可以知道第 2 级页表在哪里;再取出第 2级页表,从第 2 个页表里才能确定这个虚拟地址对应的物理地址。二级页表地址映射的最小单位有 4K、 1K, Linux使用 4K。
2024-08-13 22:53:25
1018
1
原创 中断的线程化处理
内核中有一个struct irq_desc结构体数组,有一个属性是struct irqaction* action,这个结构体中有一个属性irq_handler_t thread_fn,就对应的是request_threaded_irq函数中的thread_fn;内核线程被唤醒后,执行thread_fn函数可能有程序在等待thread_fn函数被执行,调用wake_threads_waitq(desc)来唤醒它。上半部用来处理紧急的事情,下半部用一个内核线程来处理,这个内核线程专用于这个中断。
2024-08-13 22:16:23
1201
原创 内核工作队列
参考内核头文件structstruct0第1个宏是用来定义一个结构体,要指定它的函数。第2个宏用来定义一个结构体,也要指定它的函数。所以delayed,意思就是说要让它运行时,可以指定:某段时间之后再执行。如果要在代码中初始化0。
2024-08-12 23:26:10
1129
原创 中断下半部 tasklet
当发生某一个硬件中断时,内核会调用对应的硬件中断处理函数,处理完之后,会去处理软件中断;从类似soft数组中取出action函数,对于lastlet这种软件中断,对应的函数是tasklet_action,这个函数会从某个队列/链表里取出每一个tasklet结构体,执行里面的函数。可以看到,发生 2 次硬件中断 A 时,它的上半部代码执行了 2 次,但是下半部代码只执行了一次。在第⑦步里,它会去执行中断 A 的下半部,也会去执行中断 B 的下半部。所以,同一个中断的上半部、下半部,在执行时是多对一的关系。
2024-08-12 22:31:18
1056
原创 定时器的使用
这表示内核每秒中会发生 100 次系统滴答中断(tick),这就像人类的心跳一样,这是 Linux 系统的心跳。所谓定时器,就是闹钟,时间到后你就要做某些事。核心在于:在 GPIO 中断中并不立刻记录按键值,而是修改定时器超时时间,10ms 后再处理。按下或松开一个按键,它的 GPIO 电平会反复变化,最后才稳定。如果不处理抖动的话,用户只操作一次按键,中断程序可能会上报多个数据。显然第 1 种方法太耗时,违背“中断要尽快处理”的原则,你的系统会很卡。在内核中使用定时器很简单,涉及这些函数(参考内核源码。
2024-08-11 23:00:19
1085
原创 阻塞与非阻塞
从驱动代码也可以看出来,当 APP 打开某个驱动时,在内核中会有一个struct file 结构体对应这个驱动,这个结构体中有 f_flags,就是打开文件时的标记位;也可以清除这个位表示阻塞。使用 poll 时,可以设置超时时间为 0,这样即使没有数据它也会立刻返回,这就是非阻塞方式。APP 调用open函数时,传入O_NONBLOCK,就表示要使用非阻塞方式;使用 poll 时,如果传入的超时时间不为 0,这种访问方法也是阻塞的。先输出-1,因为没有中断(此时是非阻塞),10次之后是阻塞的。
2024-08-11 18:05:51
558
原创 异步通知机制
写信号处理函数in val;注册信号处理函数// 3注册信号处理函数打开文件把APP的pid告诉驱动程序;读取驱动程序flag并设置FASYNC位为1。
2024-08-11 17:41:55
1134
原创 POLL机制的内核代码详解
即 table->pt->qproc = __pollwait, __pollwait 将在驱动的 poll 函数里用到。当执行完①之后,在⑥或⑦处, pt->_qproc 被设置为 NULL,所以第二次调用驱动程序的 poll 时,不会再次把线程放入某个队列里。是一个宏,它定义于 include/linux/syscalls.h,展开后就有 sys_poll 函数。沿着②③④⑤,你可以看到:驱动程序里的poll_wait会调用__pollwait 函数把线程放入某个队列。,他们对应的内核函数都是。
2024-08-11 12:25:05
875
原创 POLL机制
POLL方式:妈妈要干很多活,但是可以陪小孩睡一会,定个闹钟要浪费点时间,但是可以继续干活。使用休眠-唤醒的方式等待某个事件发生时,有一个缺点: 等待的时间可能很久。使用 poll 机制时,驱动程序的核心就是提供对应的 drv_poll 函数。⑦ 线程从休眠中被唤醒,继续执行 for 循环,再次调用 drv_poll: drv_poll 返回数据状态;什么都不做,5秒超时,调用两次drv_poll函数(打印两次)。⑥ 在休眠过程中,一直没有按下了按键,超时时间到:内核把这个线程唤醒;后,很有可能会休眠。
2024-08-11 12:17:50
1182
原创 休眠-唤醒
值得注意的是,上面 2个红线部分都属于 APP1 的“上下文”,或者这样说:红线所涉及的代码,都是 APP1调用的。但是按键的中断服务程序,不属于 APP1的“上下文”,这是突如其来的,当中断发生时, APP1正在休眠呢。当按下按键,驱动程序中的中断服务程序被调用,它会记录数据,并唤醒APP1。中剩下的代码,把数据复制回用户空间,返回用户空间。在 APP1的“上下文”,也就是在 APP1的执行过程中,它是可以休眠的。驱动中有数据时,图中红线就是APP1 的执行过程,设计用户态、内核态。
2024-08-10 23:39:04
773
原创 修改设备树及上机操作
哎呀,好像不对,需要的是,按下是1,松开是0,重新在驱动文件中设置。我们只需要指定GPIO信息,表示使用哪个GPIO即可。这里没问题,如果不是/boot分区,重新挂载。把编译出来的设备树文件拷贝到/boot目录下。安装驱动,按按键测试,按下是0,松开是1。使用前面编译出来的驱动。测试,按下1,松开0。
2024-08-10 22:20:16
767
原创 编写使用中断的按键驱动程序
而这些基础知识是更复杂的驱动程序的基础要素,以后的复杂驱动程序也就是对硬件操作的封装不同罢了,但是要用到的基础编程是一样的。还是建议从头写按键驱动,特别是如何使用中断。查看原理图确定按键使用的引脚,再在设备树中添加节点,在节点中指定中断信息。对于GPIO 按键,我们并不需要去写驱动程序,使用内核自带的驱动程序。休眠-唤醒、POLL机制、异步通知、定时器、中断的线程化处理。就可以了,然后你需要做的只是修改设备树指定引脚及按键值。
2024-08-10 16:46:08
247
原创 在设备树中指定中断_在代码中获得中断
对于SPI设备节点, SPI总线驱动在处理设备树里的 SPI 子节点时,也会处理其中的中断信息。假设GPIO1有32 个中断源,但是它把其中的16个汇聚起来向GIC发出一个中断,把另外16个汇聚起来向GIC发出另一个中断。如果中断控制器有级联关系,下级的中断控制器还需要表明它的“interrupt-parent”是谁,用了interrupt-parent ” 中的哪一个“ interrupts”。一个外设,它的中断信号接到哪个“中断控制器”的哪个“中断引脚”,这个中断的触发方式是怎样的?
2024-08-10 14:33:32
1043
原创 Linux 中断系统中的重要数据结构
比如GPIO控制器里有第1号中断,UART模块里也有第1号中断,这两个“第1号中断”是不一样的,它们属于不同的“域”──irq_domain。假设irq_desc[A].handle_irq是XXX_gpio_irq_handler(XXX 指厂家),这个函数需要读取芯片的 GPIO控制器,细分发生的是哪一个GPIO中断(假设是 B),再去调用irq_desc[B].handle_irq。对于共享中断,比如GPIO中断B,它的中断来源可能有多个,每个中断源对应一个中断处理函数。
2024-08-08 22:49:19
956
原创 Linux 系统对中断处理的演进
很耗时的中断处理,应该放到线程里去可以使用 work,work queue在中断上半部调用 schedule_work 函数,触发 work 的处理既然是在线程中运行,那对应的函数可以休眠。
2024-08-06 22:42:07
1013
原创 Linux 系统对中断的处理
在 Linux 中:资源分配的单位是进程,调度的单位是线程, 也就是说,在一个进程里,可能有多个线程,这些线程共用打开的文件句柄、全局变量等等。而这些线程,之间是互相独立的,“同时运行”,也就是说:每一个线程,都有自己的栈。可以,但是开销太大:读按键的程序,要把按键通知播放音乐的程序,进程间通信的效率没那么高。从上图可知, CPU内部的寄存器很重要,如果要暂停一个程序,中断一个程序,就需要把这些寄存器的值保存下来:这就称为保存现场。这样,按键的读取及 GUI 显示、音乐的播放,可以分开来,不必混杂在一起。
2024-08-05 22:45:15
1056
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅