系统应用开发,如今来讲,已经开始脱离系统,单独拿出来开发,系统定制接口,已提供给应用调用,用来加强功能。java
原生的桌面,拨号,设置,已经无法作出差别化优点,所以都费尽心机,来进行应用深度开发。linux
对于以前维护系统应用模块的人来说,修修补补,真的没有什么成长。天天的工做来讲,没有很深的技术壁垒,很容易被别人攻陷。算法
好比设置,好比联系人,在小的改动,修改故障的时候,没有很是高的要求,作过应用开发的,均可以过来参合一脚,改改问题。而让一个应用开发得去修改系统接口,估计改的心累,而且犹豫不决。windows
技术壁垒,也即是本身的竞争优点。只有顽强的技术能力,并锲而不舍的学习,扩充本身的深度,广度,那么你的位置则牢不可破,不会轻易被替代。网络
这节,小编从自身的角度,讲讲系统应用开发,该如何向Framework进军,进行学习,掌握更加核心的技术。数据结构
这里有人会说,我作应用风生水起,也游刃有余,不比大家作系统Framework的差,何须把系统应用开发的贬的一文不值。这里要说一下,文中没有这个意思,你的应用作的有声有色,赚的盆满钵满,这里确定有其因素。好比它的性能,它的界面绚丽,百变主题。或者它有智能识别,等等。这些都叫作差别化产品,有其亮点,特点,才能杀出重围。架构
而系统应用开发,我这里偏向于手机整机开发中的OEM厂商,主要作出系统,可以保证功能正常,不会花费大量人力精力去作应用深度开发,系统重构的。这里主要会以追求速度,同时知足客户的硬件要求,好比多个霍尔器件,多个温度传感器,多个皮套功能,等等,但不多去大量改动应用架构,以避免影响最终量产。框架
以上,就是特指的这个应用开发人员。随后,我来说讲,Framework须要掌握哪些知识呢?数据结构和算法
熟悉个人人都知道,我特喜欢把这个放在第一位,缘由很简单,它确实支撑了我随后的全部知识根基,让我可以从容不迫的,将一个个系统拆解出来。编辑器
咱们就拿安卓来说,启动过程
跟linux一模一样,因此很容易迁移过来,同时,差别化的init进程,完成初始任务,建立安卓世界的孵化器,既然这里要进入安卓世界,而安卓世界的基础语言是java,那么就须要一个Java虚拟机,因而孵化器就要构造一个虚拟机,用来解析执行Java编译出来的字节流。而孵化器自己是由c cpp语言实现,因而Java虚拟机就是由c cpp语言写出来的,linux操做系统也是c(还有一些汇编)写出来的,因而Java虚拟机运行的Java语言,就须要跟c cpp打交道,因而就有了JNI。
孵化器作了几件事情:
1.完成Java虚拟机的构造
2.完成JNI对接Java与c的桥梁
3.加载公共的共享库
4.等待别人给它发消息,建立新进程
在这期间,孵化器要作一件事情,即是建立system_server ,这个进程要作什么呢?咱们建立了一个能够运行Java的虚拟机,这时咱们就要提供一堆系统接口,用来协助应用开发,好比请求网络啦,好比建立界面啦,好比定位啦,获取存储卡啦,等等支持,方便用户开发功能。一个平台的好坏,每每取决于它的功能是否强大,是否有丰富的技术文档,以及开发调试工具。
因此就有了一堆线程,好比AMS,WMS,PMS,BT,WIFI,这些均可以在/proc/{ system_server_pid}/ tast找到记录。
有了这些线程,那么咱们就能够轻松的去实现不少功能啦。这时咱们就要配套的开发工具,好比AS编辑器,能够编辑,编译出来APK,安装到手机运行。
关于操做系统,须要掌握的知识点为:
1.进程,线程概念
2.互斥,死锁机制与原理,如何避免死锁
3.内存管理机制,虚拟内存
4.静态库与动态库的区别
5.进程之间的内存屏障,如何通讯(IPC)
6.binder的通讯优点
这里先想到这些,注意不是要完成懂全部机制,要的是总体理解便可。以下问题,请思考下,看是否可以答上来。
若是我写了一个应用,名字叫作,com.codegg.home 在主activity里面,加载一个布局,layout_main. xml,布局里面写入了一个TextView,那么我想调试这个TextView,要在com.codegg.home这个进程下断点,仍是在system_server进程下断点呢?若是是想调试ActivityThread. java的话?应该在哪一个进程下断点呢?
以上答案,都是com.codegg.home下断点,缘由是这两个当前的运行进程,都是在com.codegg.home里,因此要调试的话,要在com.codegg.home进程下断点。
那么咱们再来思考下,我如今要去追应用的启动过程,start Activity的流程,要在哪一个地方下断点呢?
咱们知道这个流程,最终核心的都在Activity manager server里面,而它是在system server进程里面,以一个线程的状态存在,因而咱们要调试,就要在system server上面下断点了。
搞清楚了system server后,以咱们熟悉的AMS WMS PMS 举例。这些服务线程,完成应用的请求任务,将结果返回给应用。好比查看当前运行的全部Activity,就是应用发起请求,从操做系统那里,先找到server manager,这个手里拿到一堆服务的句柄,也能够说令牌,你只能经过这个找到它。
当server manager一看你有权限,就帮你把对应的AMS的句柄给你,这个句柄操做系统也认识,对应到system server的AMS引用上,也就是你经过这个句柄,调用它的方法,操做系统就会将你的请求,传递到system server中去,同时操做系统知道这个句柄是AMS的第20号(这个20号表明查询当前运行的全部Activity的方法),而后就唤醒system server,同时从binder线程池,这个线程跟AMS同样,是个线程,从线程池拿出一个,调用AMS的20号方法。
调用完成后,从操做系统层面,把数据交给调用的应用,实现数据传输。这里面定义的传递数据格式是包裹,也就是序列化数据。
好了,这块就说这么多,主要是说下进程通讯,以及binder这种通讯的简单逻辑。这里说下,为何要通讯。
由于操做系统设计,管理的软件单元是进程,进程间自己不联系,彼此看不见。一个进程想跟另外一个说话,他两都认识的人是操做系统。由于他们是由操做系统管理的。操做系统经过从硬盘将程序装载进入内存,同时给每个分配了进程号,因而他们就都在系统里面有了标记,同时每一个都起了名字,一个叫我就喜欢吃,一个叫我就喜欢喝。喜欢喝的一我的孤单,他不认识喜欢吃的,他就问操做系统,有没有人喜欢吃的,操做系统一查,说有啊,而后把喜欢吃的的进程号给他,他就能够找到喜欢吃的了。
而后操做系统给他了一辆车,让他把想给喜欢吃的的东西,装在车上寄过去。这个车子是操做系统提供的,这个车子就是通讯方式。好比汽车,飞机,步行。
因而进程间的通讯方式就是,从操做系统找到目标,而后拿到通讯方式,用操做系统给的通讯工具,进行通讯。
这块完成了,咱们再来说一个内容:
文件=文件头+文件内容
咱们发现,这里MP3格式,OGG格式,都属于一个文件的格式声明,这个咱们能够用HEX工具打开MP3文件,能够看到刚开始的位置,这块属于描述后面的内容该如何解析,好比文件名字,文件大小,文件格式,系统根据这个描述,尝试用对应的解码器解码,解码完成后进行播放。
这里解码器如何解码,就是算法。而文件头,就是描述这个文件的数据结构。
因而,咱们就知道
程序=数据结构+算法
好比我要写个贪吃蛇,如何描述蛇的状态,长度,当前轨迹,这些都是须要表征出来,而后围绕着这个描述内容,进行操做,这块就属于算法。
完成的程序,运行起来,就是进程。因此进程是一个存在于内存的东西,操做系统用一个表格记录进程数据,好比进程号,父类进程,进程打开的文件句柄,进程当前状态,进程的上下文(上下文是保存当前CPU的寄存器,保存现场用的,由于寄存器是只有一份,当一个进程被打断时候,另个进程运行,那么以前的就要把它当前的寄存器存下来,防止被别人盖掉,等到下次本身运行的时候,再恢复回来,保证本身运行正常),程序是存在硬盘或者其余存储设备,掉电不会丢失,而进程是内存的,因此掉电就再也不了。
**程序如何加载,系统如何识别的呢?**这就又回到开头的地方,数据结构加算法,也叫文件头和文件内容。源码通过编译连接,变成一个文件,咱们亲切的叫它可执行文件。那么咱们来讲说它。
咱们常见的两种可执行文件,windows上面称为PE格式,linux称为ELF,二者都是从COFF格式演化来的,这块参考《连接器与加载器》,喜欢感兴趣,能够下载阅读此书。
那么有了格式描述,操做系统就知道如何解析它了,而后把对应的代码段,数据段,堆栈区域配置好,将代码装载进入内存中,而后将下一条执行位置,也就是PC寄存器,指向这个可执行文件配置的text 入口,这个就是程序的入口点,这个咱们去写的main方法,能够简单理解成入口,实际状况是在这个前面,系统加入了一些代码,为运行此程序作准备,准备OK才会真正调用到main方法,这段代码叫建立此进程的环境,好比参数,堆栈初始化。
聊到这里,咱们从别的纬度,再来看看。
数字电路的与或非逻辑电路,开启了新世界的大门。咱们用断点,通电,表示两个状态。咱们不能说,好像有电,好像没电,因此,计算机的世界,定义了二进制,由于是非能够界定,孰是孰非很差界定。
因而,在咱们的电路板上,规定了0-0.6V,表明了没电,4.4-5V,表明了有电,中间的数值,表明了器件的错误,不稳定性。
因而没电用0表示,有电用1表示,实际世界就是两个区间电压。
CPU在石英晶振的推进下,执行一条条指令。指令是什么呢?就是一串串数字,每一串表明一个具体含义。
因此,CPU可以执行多少条指令,是考量它是否强大的一个重要参数,另外一个是它执行一天指令的时间,也叫指令周期,越短越好。也就是两个CPU同时作一个加法,谁用时短谁就强。
CPU拿到一条指令,就会在石英晶振的推进下,将这条指令执行完,而后将PC寄存器加1,读取下一条指令。
咱们常常遇到的非法指令,就是由于CPU拿到了一个不认识的数据串,致使异常。好比它的指令集里面,有加法,有减法,你给他说你给我翻个跟头(非法指令),他骂了一句去你的吧,老子不会(异常报错)。通常这种状况是指令不识别,好比你用了新的arm指令,又在旧的arm板子运行这个程序,就会挂掉,提示非法指令。
刚开始的操做系统,嵌入式的操做系统,是没有作内存保护,就是程序段能够跳到数据段执行,固然如今加入了内存管理单元,会将数据段内存描述成可读可写不可执行,若是PC(程序寄存器)指向了这个地方,去读取执行的时候,就会报非法访问。
若是没有保护,你去读取数据段的数据,做为指令执行,出现指令异常就太正常了。
好了,今天就给你们介绍这么多,有什么想方法或者建议欢迎留言评论。
以为文章还不错喜欢的点个赞给个喜欢鼓励下呗~