从linux进程机制到TopwiseProp的分析
来源:互联网 发布:本科做网络维护 编辑:程序博客网 时间:2024/06/03 21:36
在linux中,如果需要创建一个新的进程,会调用fork()孙数。
我们先来看一段代码:
#include "stdio.h"#include "sys/types.h"#include "unistd.h"int main(){ pid_t p1; pid_t p2; p1=fork();//----(1) p2=fork();//----(2) printf("p1 id is %d , p2 id is %d \n",p1,p2);}
这段代码的输出为:
p1 id is 31763 , p2 id is 31764 p1 id is 0 , p2 id is 31765 p1 id is 0 , p2 id is 0 p1 id is 31763 , p2 id is 0
这里有四个输出,原因是因为有四个进程在跑,其中三个是当前进程的子进程。
这是由于fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,这其中还包括了PC-程序计数器。
一个进程调用fork()函数后,系统先给新的进程分配资源,例如存储数据和代码的空间。然后把原来的进程的所有值都复制到新的新进程中。
关于linux进程机制:
1、进程可以看做程序的一次执行过程。在linux下,每个进程有唯一的PID标识进程。
PID是一个从1到32768的正整数,其中1一般是特殊进程init,其它进程从2开始依次编号。当用完32768后,从2重新开始。
2、linux中有一个叫进程表的结构用来存储当前正在运行的进程。
可以使用“ps aux”命令查看所有正在运行的进程。
3、进程在linux中呈树状结构,init为根节点,其它进程均有父进程,
某进程的父进程就是启动这个进程的进程,这个进程叫做父进程的子进程。
4、fork的作用是复制一个与当前进程一样的进程。新进程的所有数据(变量、环境变量、程序计数器等)
数值都和原进程一致,但是是一个全新的进程,并作为原进程的子进程
我们先来看为什么会有4个进程:
1、从当前进程P来看,执行到(1)时,产生了第一个子进程pid 为 31763, 执行到(2)时,产生了第二个子进程pid 为 31764
2、进程31763:由于子进程继承了父进程的所有数据,包换程序计数器。这样进程31763 会从(2)开始执行,所以进程31763又调用了一次fork(),产生了一个子进程31765
3、进程31764 : 在父进程执行到(2)产生了该进程,所以他紧接着执行后面的输出。不会再产生新的进程。
所以包括父进程在内,共有4个进程。
fork()函数的一个特点是,一次调用,两次返回。一次返回在调用进程中,返回的是新建进程的进程号。另一次返回在子进程中,返回的是0。
这样我们来看输出的结果:
1、在当前进程(父进程)中:调用了两次fork(),返回了两个子进程的id:p1 id is 31763 , p2 id is 31764
2、在子进程31763中:父进程在第一次调用fork()时产生自己,所以此时返回为0,第二次调用fork()即执行(2)时,自己又产生了另一个进程31765,所以有p2=31765。
所以,最终输出为:p1 id is 0 , p2 id is 31765
3、在子进程31764中,由于此时是执行第二个fork()即(2)中,父进程产生了自己,所以p2=0,但是此时p1已经在父进程中被赋值为31763。
所以,最终输出为:p1 id is 31763 , p2 id is 0
4、在子进程31765中:这个进程的父进程是31763,此时在31763进程中第一个fork()是返回0的。于是有p1=0。31763进程在第二个fork()时产生了子进程31765,所以此时的返回值为0。
所以,最终输出为:p1 id is 0 , p2 id is 0
至于这几个进程的执行顺序,则由系统调度来决定,执行顺序是不一定的。
TopwiseProp类
公司为了解决方案公司客户众多,需求各异的情况。没有直接使用build.prop来配置客户需求开关,而是使用了一个TopwiseProp的类。
这个类被放在了idh.code/frameworks/base/core/java/android/os/TopwiseProp.java中。
该文件采用了一个延后加载的方法,即在调用相关方法后,才进行初始化的动作。其中,为了避免多次加载配置文件所带来的性能问题,加入了一个判断:
private static Properties properties = null; if (properties == null) { File oemFile = new File(defSettingPath); FileInputStream stream = null; try { stream = new FileInputStream(oemFile); InputStreamReader in=new InputStreamReader(stream,"utf-8"); BufferedReader br = new BufferedReader(in); properties = new Properties(); properties.load(br); } catch (Exception e) { // TODO: handle exception properties=null; }finally{ if(stream != null){ try { stream.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
这段代码的本意是在properties未被初始化的情况下进行加载文件的操作。
由于TopwiseProp只是一个工具类,所以它本身是在进行调用时加载,因而每个进程调用时(properties == null)都是成立的。从而每个进程都会加载一次配置文件。
但实际结果却发现是,只有第一个进程调用时会加载配置文件,后续的进程调用不会再进行加载操作。从而达到了在一次开机后,该文件加载操作仅会执行一次。
虽然这可能并非设计者的本意,但却达到了超过设计者预期的效果。
从log分析中,我发现第一次调用该类的进程为zygote。
我们知道在进程号为1的init进程在创建完zygote后,把后续创建进程的任务交给了zygote。
这样一来,以后的android进程都是zygote的子进程。
所以后续的进程实际上都会把TopwiseProp实例拷贝一份在自己的进程里。所以才达到了这种一次加载,多进程共同使用结果的效果。
- 从linux进程机制到TopwiseProp的分析
- Linux系统启动分析-从start_kernel到init进程的启动
- 从一道面试题分析Linux进程+IO缓冲区机制
- 从一道面试题分析Linux进程+IO缓冲区机制
- linux从文件到进程的过程
- 从start_kernel到init进程启动 《Linux内核分析》笔记
- 跟踪分析Linux内核的启动过程(从start_kernel到init进程)
- 从Linux的进程调度机制中想到的
- Linux从程序到进程
- Linux从程序到进程
- Linux从程序到进程
- Linux从程序到进程
- Linux从程序到进程
- Linux从程序到进程
- Linux从程序到进程
- Linux从程序到进程
- Linux 进程基础 && 从程序到进程
- 【进阶】从linux到android,进程的方方面面
- 模板template和宏定义define一起的例子
- JZOJ 5050. 【GDOI2017模拟一试4.11】颜色树
- 微信群管理机器人
- java设计模式——适配器模式二
- JQuery选中select组件被选中的值
- 从linux进程机制到TopwiseProp的分析
- C++ windows API获取驱动器根路径和属性(-)
- 获取CheckBoxList当前选择项
- 2017-4-22:实用类总结
- EvenBus 避免跳进大坑
- java基础总结15-面向对象11(抽象类)
- 在线黑科技小工具
- MySQL实验(三) 过程式数据库对象的使用
- java.util.Date和java.sql.Date的区别和相互转化