基于android2.3.5系统:开天辟地Android启动机制[二]

基于android2.3.5系统:开天辟地Android启动机制[一] 在android的系统中init程序是第一个运行的程序,这是一个守护进程,而具体的代码在android2.3.5的源码中,位于system/core/init/init.c文档中,这个是main函数的入口,也是android启动机制的入口。 阅读详情

***************************************************************************************************************************
作者:EasyWave                                                                                 时间:2012.07.29

类别:Android系统源码分析                                                            声明:转载,请保留链接

注意:如有错误,欢迎指正。这些是我学习的日志文章......

***************************************************************************************************************************

     在我的博文基于goldfish和android2.3.5学习之:开天辟地Android启动机制[一]中,介绍了整个android系统的启动机制,这次将更深入的详细分析android的uevent的机制以及如何android是如何透过内核传递过来的数据通过uevent建立设备节点以及一些hotplug事件。在Andorid2.3.5源码system/core/init.c函数中ueventd_main()函数。详细的代码如下:

    if (!strcmp(basename(argv[0]), "ueventd"))	//得到运行程序ueventd.rc的全路径名下的ueventd
        return ueventd_main(argc, argv);	//如果可以找到ueventd.rc,则执行ueventd_main函数
这里有个函数不得不说,这个函数就是basename函数,这个函数的主要作用就是得到ueventd.rc文件所在路径下的文件名,即ueventd。这个函数的具体的代码如下:

#include <sys/cdefs.h>
#include <errno.h>
#include <libgen.h>
#include <stdlib.h>
#include <string.h>
#include <sys/param.h>

char* basename(const char*  path)
{
    static char*  bname = NULL;
    int           ret;

    if (bname == NULL) {
        bname = (char *)malloc(MAXPATHLEN);
        if (bname == NULL)
            return(NULL);
    }
    ret = basename_r(path, bname, MAXPATHLEN);
    return (ret < 0) ? NULL : bname;
}
上面这个最终是调用basename_r函数来解析 ueventd.rc所在的路径下的ueventd的文件名。这个函数式在bionic/libc/bionic/basename.c中。具体的实现函数却是在basename_r函数中,这个函数也是在bionic/libc/bionic/basename_r.c中来实现的,具体的代码如下:

#include <libgen.h>
#include <errno.h>
#include <string.h>
#include <sys/param.h>

int basename_r(const char* path, char*  buffer, size_t  bufflen)//返回路径中文件名的安全函数
{
    const char *endp, *startp;
    int         len, result;
    char        temp[2];

    /* Empty or NULL string gets treated as "." */
    if (path == NULL || *path == '\0') {
        startp  = ".";
        len     = 1;
        goto Exit;
    }

    /* Strip trailing slashes */
    endp = path + strlen(path) - 1;
    while (endp > path && *endp == '/')
        endp--;

    /* All slashes becomes "/" */
    if (endp == path && *endp == '/') {
        startp = "/";
        len    = 1;
        goto Exit;
    }

    /* Find the start of the base */
    startp = endp;
    while (startp > path && *(startp - 1) != '/')
        startp--;

    len = endp - startp +1;

Exit:
    result = len;
    if (buffer == NULL) {
        return result;
    }
    if (len > (int)bufflen-1) {
        len    = (int)bufflen-1;
        result = -1;
        errno  = ERANGE;
    }

    if (len >= 0) {
        memcpy( buffer, startp, len );
        buffer[len] = 0;
    }
    return result;
}
透过上面的basename_r函数我们可以看出来主要是将目录路径"/"一个一个找出来并且丢弃,最终找到ueventd与strcmp(basename(argv[0]), "ueventd")进行比较,如果找到文件,则进入ueventd_main(argc, argv);进行uevent事件的主循环的处理中。在android2.3.5源码中system/core/rootdir/中ueventd.rc文件如下:

/dev/null                 0666   root       root
/dev/zero                 0666   root       root
/dev/full                 0666   root       root
/dev/ptmx                 0666   root       root
/dev/tty                  0666   root       root
/dev/random               0666   root       root
/dev/urandom              0666   root       root
/dev/ashmem               0666   root       root
/dev/binder               0666   root       root

# logger should be world writable (for logging) but not readable
/dev/log/*                0662   root       log

# the msm hw3d client device node is world writable/readable.
/dev/msm_hw3dc            0666   root       root

# gpu driver for adreno200 is globally accessible
/dev/kgsl                 0666   root       root

# these should not be world writable
/dev/diag                 0660   radio      radio
/dev/diag_arm9            0660   radio      radio
/dev/android_adb          0660   adb        adb
/dev/android_adb_enable   0660   adb        adb
/dev/ttyMSM0              0600   bluetooth  bluetooth
/dev/ttyHS0               0600   bluetooth  bluetooth
/dev/uinput               0660   system     bluetooth
/dev/alarm                0664   system     radio
/dev/tty0                 0660   root       system
/dev/graphics/*           0660   root       graphics
/dev/msm_hw3dm            0660   system     graphics
/dev/input/*              0660   root       input
/dev/eac                  0660   root       audio
/dev/cam                  0660   root       camera
/dev/pmem                 0660   system     graphics
/dev/pmem_adsp*           0660   system     audio
/dev/pmem_camera*         0660   system     camera
/dev/oncrpc/*             0660   root       system
/dev/adsp/*               0660   system     audio
/dev/snd/*                0660   system     audio
/dev/mt9t013              0660   system     system
/dev/msm_camera/*         0660   system     system
/dev/akm8976_daemon       0640   compass    system
/dev/akm8976_aot          0640   compass    system
/dev/akm8973_daemon       0640   compass    system
/dev/akm8973_aot          0640   compass    system
/dev/bma150               0640   compass    system
/dev/cm3602               0640   compass    system
/dev/akm8976_pffd         0640   compass    system
/dev/lightsensor          0640   system     system
/dev/msm_pcm_out*         0660   system     audio
/dev/msm_pcm_in*          0660   system     audio
/dev/msm_pcm_ctl*         0660   system     audio
/dev/msm_snd*             0660   system     audio
/dev/msm_mp3*             0660   system     audio
/dev/audience_a1026*      0660   system     audio
/dev/tpa2018d1*           0660   system     audio
/dev/msm_audpre           0660   system     audio
/dev/msm_audio_ctl        0660   system     audio
/dev/htc-acoustic         0660   system     audio
/dev/vdec                 0660   system     audio
/dev/q6venc               0660   system     audio
/dev/snd/dsp              0660   system     audio
/dev/snd/dsp1             0660   system     audio
/dev/snd/mixer            0660   system     audio
/dev/smd0                 0640   radio      radio
/dev/qemu_trace           0666   system     system
/dev/qmi                  0640   radio      radio
/dev/qmi0                 0640   radio      radio
/dev/qmi1                 0640   radio      radio
/dev/qmi2                 0640   radio      radio
/dev/bus/usb/*            0660   root       usb
/dev/usb_accessory        0660   root       usb

# CDMA radio interface MUX
/dev/ts0710mux*           0640   radio      radio
/dev/ppp                  0660   radio      vpn
/dev/tun                  0640   vpn        vpn

# sysfs properties
/sys/devices/virtual/input/input*   enable      0660  root   input
/sys/devices/virtual/input/input*   poll_delay  0660  root   input
/sys/devices/virtual/usb_composite/*   enable      0664  root   system

而ueventd_main的代码见下面,现在更深入的来分析下这个函数。这个函数式在system/core/init/ueventd.c

int ueventd_main(int argc, char **argv)
{
    struct pollfd ufd;
    int nr;
    char tmp[32];

    open_devnull_stdio(); //打开/dev/__null,并且重定向stdin、stdout、stderr
    log_init(); //打开log文件

    INFO("starting ueventd\n");

    get_hardware_name(hardware, &revision); //透过/proc/cpuinfo得到当前项目的hardware以及revision

    ueventd_parse_config_file("/ueventd.rc"); //解析ueventd.rc文件

    snprintf(tmp, sizeof(tmp), "/ueventd.%s.rc", hardware);
    ueventd_parse_config_file(tmp); //解析ueventd.xxxxxx.rc文件,比如:goldfish为ueventd.goldfish.rc文件

    device_init();

    ufd.events = POLLIN;
    ufd.fd = get_device_fd();

    while(1) {
        ufd.revents = 0;
        nr = poll(&ufd, 1, -1);
        if (nr <= 0)
            continue;
        if (ufd.revents == POLLIN)
               handle_device_fd();
    }
}

首先来分析下open_devnull_stdio();这个函数,这个主要是打开/dev/__null__,同时将stdin,stdout,stderr进行重定向,具体的代码如下:

void open_devnull_stdio(void)
{
    int fd;
    static const char *name = "/dev/__null__";
    if (mknod(name, S_IFCHR | 0600, (1 << 8) | 3) == 0) { //设置节点属性,S_IFCHR:也就是说这是一个字符设备。0600是文件的属性。
        fd = open(name, O_RDWR); //打开/dev/__null__设备
        unlink(name); //删除一个文件的目录项并减少它的链接数
        if (fd >= 0) {  //打开成功
            dup2(fd, 0); //重定向stdin
            dup2(fd, 1); //重定向stdout
            dup2(fd, 2); //重定向stderr
            if (fd > 2) { //关闭文件并且返回成功
                close(fd);
            }
            return;
        }
    }
    //否则返回失败
    exit(1);
}
而log_init();主要是建立一个msg的log文件以记录上面的操作的记录文件。其函数代码如下[这个函数就不深究了,很容易看得懂。相信大家都应该还记得这个命令:cat /proc/kmsg,你自己可以在开发板上打下这个命令,看看会出现什么信息出来。。代码如下:

void log_init(void)
{
    static const char *name = "/dev/__kmsg__";
    if (mknod(name, S_IFCHR | 0600, (1 << 8) | 11) == 0) {
        log_fd = open(name, O_WRONLY);
        fcntl(log_fd, F_SETFD, FD_CLOEXEC); //给文件强制加锁,设置文件为FD_CLOEXEC,这标志大家可以到网络搜索具体的意思,主要跟exec()函数有关的。
        unlink(name);
    }
}
同时这个函数需要说下,这个函数就是get_hardware_name(hardware, &revision);这个是透过/proc/cpuinfo得到当前硬件的名称和版本,相信做linux和android内核移植和驱动开发的,应该都知道这个命令:cat /proc/cpuinfo 吧,这个可以在自己的开发板上去测试下,看看会出现什么内容。现在重点分析ueventd_parse_config_file("/ueventd.rc");这个函数。这个函数式ueventd的重点之重,函数代码如下:

int ueventd_parse_config_file(const char *fn)
{
    char *data;
    data = read_file(fn, 0);
    if (!data) return -1;

    parse_config(fn, data);
    DUMP();
    return 0;
}

这里面的read_file(fn,0)主要是读取ueventd.rc的文件大小,并且存储在内存中。而parse_config(fn, data);这个才是重点,这是解析ueventd.rc文件的,这个函数是在system/core/init/ueventd_parser.c中,现在来深入的分析这个函数。

static void parse_config(const char *fn, char *s)
{
    struct parse_state state;
    char *args[UEVENTD_PARSER_MAXARGS];
    int nargs;
    nargs = 0;
    state.filename = fn;
    state.line = 1;
    state.ptr = s;
    state.nexttoken = 0;
    state.parse_line = parse_line_device; //具体的解析device,这是一个回调函数
    for (;;) {
        int token = next_token(&state); //循环查找ueventd.rc中的/dev/null, /dev/zero等
        switch (token) {
        case T_EOF:
            state.parse_line(&state, 0, 0);  //到了ueventd.rc的末尾的话,做最后的解析,并直接返回
            return;
        case T_NEWLINE:     //如果到了换了一行的时候,去做ueventd.rc的解析工作
            if (nargs) {
                state.parse_line(&state, nargs, args);
                nargs = 0;
            }
            break;
        case T_TEXT: //如果正在解析本行的数据,详细见ueventd.rc文件
            if (nargs < UEVENTD_PARSER_MAXARGS) {
                args[nargs++] = state.text;
            }
            break;
        }
    }
}
这个函数在/dev/的都是只有四个可选参数,而只有在/sys/下的时候多了一个attr的选项,也就是5个选项。具体的解析在 parse_line_device函数中的set_device_permission()有详细的处理。具体的代码如下:

void set_device_permission(int nargs, char **args)
{
    char *name;
    char *attr = 0;
    mode_t perm;
    uid_t uid;
    gid_t gid;
    int prefix = 0;
    char *endptr;
    int ret;
    char *tmp = 0;

    if (nargs == 0)
        return;

    if (args[0][0] == '#')
        return;

    name = args[0]; //就拿ueventd.rc文件中/dev/null     0666   root    root 和 /sys/devices/virtual/input/input*   enable    0660  root   input 来说吧

    if (!strncmp(name,"/sys/", 5) && (nargs == 5)) { //查找/sys/的设备,一般都是有5个参数的。
        INFO("/sys/ rule %s %s\n",args[0],args[1]);
        attr = args[1]; //因此将args[1]赋值给attr
        args++;
        nargs--;
    }

    if (nargs != 4) { //如果参数不对,则直接退出,不解析了,因为出错了。
        ERROR("invalid line ueventd.rc line for '%s'\n", args[0]);
        return;
    }

    /* If path starts with mtd@ lookup the mount number. */
    if (!strncmp(name, "mtd@", 4)) { //查找是否有mtd分区,如果有这mount mtd分区
        int n = mtd_name_to_number(name + 4);
        if (n >= 0)
            asprintf(&tmp, "/dev/mtd/mtd%d", n);
        name = tmp;
    } else { //否则就做常规的设备解析
        int len = strlen(name);
        if (name[len - 1] == '*') {
            prefix = 1;
            // 如果设备中'*'字符,这告诉add_dev_perms有前缀符号,比如:/dev/input/*  也就是这个有可能会有0,1,2,3等多个。
            name[len - 1] = '\0';
        }
    }

    perm = strtol(args[1], &endptr, 8); //将args[1]转换为8进制,比如字符0666转换为真正的整形。
    if (!endptr || *endptr != '\0') {
        ERROR("invalid mode '%s'\n", args[1]);
        free(tmp);
        return;
    }

    ret = get_android_id(args[2]); //得到android_id定义的name,具体见:android_ids表格。
    if (ret < 0) {
        ERROR("invalid uid '%s'\n", args[2]);
        free(tmp);
        return;
    }
    uid = ret; //设置用户id

    ret = get_android_id(args[3]); //得到android_id定义的id,具体见:android_ids表格,下一节会深入分析
    if (ret < 0) {
        ERROR("invalid gid '%s'\n", args[3]);
        free(tmp);
        return;
    }
    gid = ret; //设置group的id

    add_dev_perms(name, attr, perm, uid, gid, prefix); //添加到链表中。
    free(tmp);
}

在add_dev_perms()函数中,主要将/dev和/sys/ 分别添加到不同的链表中,具体的函数的实现如下:

int add_dev_perms(const char *name, const char *attr,
                  mode_t perm, unsigned int uid, unsigned int gid,
                  unsigned short prefix) {
    struct perm_node *node = calloc(1, sizeof(*node));
    if (!node)
        return -ENOMEM;

    node->dp.name = strdup(name);
    if (!node->dp.name)
        return -ENOMEM;

    if (attr) {
        node->dp.attr = strdup(attr);
        if (!node->dp.attr)
            return -ENOMEM;
    }

    node->dp.perm = perm;
    node->dp.uid = uid;
    node->dp.gid = gid;
    node->dp.prefix = prefix;

    if (attr)
        list_add_tail(&sys_perms, &node->plist);
    else
        list_add_tail(&dev_perms, &node->plist);

    return 0;
}

还未完,具体的分析在 《基于android2.3.5学习之:开天辟地Android启动机制[三]》 来分析。。。。



Linux设备模型(六) - Android ueventd浅析 在linux2.6之后,udev取代了devfs,但是在android中却没有udev或者mdev[1],而是由ueventd进程实现了类似功能(管理设备节点权限、创建设备节点)。 阅读详情

相关推荐

Android系统启动系列2 init进程

一 概述 init 进程是 Linux 系统中用户空间的第一个进程,进程号为1.当板子上电,bootloader 启动后,加载并启动 kernel,kernel 启动完后,在用户空间启动 init 进程,然后再通过 init 进程,来解析并读取 init.rc 中的相关配置,从而来启动其他相关进程以及其它操作。 init 进程被赋予了很多重要工作,它启动主要分为两个阶段: 第一阶段 ueventd/watchdogd跳转及环境变量设置 挂载文件系统并创建目录 初始化日志输出、挂载分区设备 启用SELinu

liuwg1226的专栏 2567

Android模拟器学framework和driver之传感器篇1(linux sensor driver)

转自:http://www.2cto.com/kf/201202/118270.html 对于android模拟器开发环境的搭建这里我就不多说了,网上google下一大堆,还有就是android 模拟器的kernel使用的是goldfish的kernel,可以使用git得到源码,然后就可以编译了,大家还是可以参考罗老师的博客。。。         在这里我准备编写一个温度传感器

Skypine_Lee的专栏 725

详解 android 光线传感器 light sensor的使用

调用anroid的光线传感器使用。 实现效果图: MainActivity.Java package hk.ust.cse.comp107x.ligthsensor; import android.content.Context; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.support.v7.a

Android6.0 ueventd

android ueventd

橡果生长记的博客 5340

CVPR2023新作HAT实战:5分钟搞定图像超分辨率重建(附代码)

本文介绍了CVPR2023新作HAT模型在图像超分辨率重建中的实战应用。HAT通过创新的混合注意力机制,显著提升了图像重建质量,能激活更多有效像素并减少伪影。文章提供了从环境配置到模型部署的完整指南,帮助开发者在5分钟内快速实现图像超分辨率重建,并附有代码示例和性能优化技巧。

weixin_29062613的博客 238

PX4无人机-Gazebo仿真实现动态目标追踪的视觉控制方案

本文详细介绍了PX4无人机在Gazebo仿真环境中实现动态目标追踪的视觉控制方案。从PX4与Gazebo仿真环境搭建、动态目标追踪核心技术栈、仿真环境深度定制技巧到追踪算法的优化实践,提供了全面的技术指导和常见问题排查方法,帮助开发者高效实现无人机视觉追踪功能。

weixin_29196315的博客 450

Android ueventd浅析

在linux2.6之后,udev取代了devfs,但是在android中却没有udev或者mdev[1],而是由ueventd进程实现了类似功能(管理设备节点权限、创建设备节点)。 ueventd通过两种方式创建设备节点: 静态,ueventd启动时,根据在sysfs中预定义的uevent信息创建设备节点; 动态,系统运行过程中,当接收到内核uevent事件时(如插入u盘),动态创建设备节点。 1. ueventd启动过程 在init.rc中,当触发条件为“early-init”时ueventd被启

Android系统攻城狮 5187

GAMES101作业3-遇到的各种问题及解决方法

记录在做作业3时遇到的一些坑!以及最后的解决办法。

qq_41835314的博客 6818

Android init 分析

<!-- @page {margin:0.79in} p {margin-bottom:0.08in} a:link {} --> Android init 分析 一、AndroidInit.c执行流程 Android中的内核启动后,kernel会启动第一个用户级别的进程:init,它是一个由内核启动的用户级进程,它的进程号是1,它以一个守护进程的方式

wonview的专栏 3330

PCIE配置和地址空间

来源:https://www.jianshu.com/p/574e9a2cbc4e 每个PCIe设备,有这么一段空间,Host软件可以读取它获得该设备的一些信息,也可以通过它来配置该设备,这段空间就叫做PCIe的配置空间。不同于每个设备的其它空间,PCIe设备的配置空间是协议规定好的,哪个地方放什么内容,都是有定义的。PCI或者PCI-X时代就有配置空间的概念,那时的配置空间如下: 图6.1 整个配置空间就是一系列寄存器的集合,其中Type 0是Endpoint的配置,Type 1是Brid.

qq_28643619的博客 4060

S32K3的STCU2模块详解:从硬件FSM到MCAL配置,搞懂BIST在线测试全流程

本文深入解析S32K3系列MCU的STCU2模块,从硬件FSM架构到MCAL配置,详细讲解BIST在线测试全流程。通过分区的安全策略和实战代码示例,帮助开发者掌握汽车电子系统中的功能安全实现,提升系统可靠性和安全性。

weixin_42525328的博客 446

(连载)Android 8.0 : 系统启动流程之init进程(一)

这是一个连载的博文系列,我将持续为大家提供尽可能透彻的Android源码分析 github连载地址 前言 上一篇中讲到,Linux系统执行完初始化操作最后会执行根目录下的init文件,init是一个可执行程序, 它的源码在platform/system/core/init/init.cpp。 之前我们讲过init进程是用户空间的第一个进程,我们熟悉的app应用程序都是以它为父进程的, init...

weixin_34268610的博客 462

MoveIt避坑指南:UR机械臂编程中常见的5个错误及解决方法

本文针对UR机械臂与MoveIt集成开发中的常见问题,总结了五个典型错误及其解决方案,包括关节限位设置、坐标系混淆、规划器选择、运动学求解器配置以及线程资源管理。重点分析了正逆运动学求解错误的原因,并提供了调整容忍度、显式指定坐标系、选择合适规划器及优化IK配置等实用代码示例,帮助开发者提升编程效率与系统稳定性。

root9的博客 434

基于android2.3.5系统:开天辟地Android启动机制[三]

在我的博文基于goldfish和android2.3.5学习之:开天辟地Android启动机制[二]中,部分的介绍了uevent事件机制,这篇博文将更深入的详细分析uevent的机制以及如何android是如何透过内核传递过来的数据通过uevent机制检测设备的hotplug事件。

嵌入式与人工智能天地 4135

metahuman 下载材质 脸部灰白 脸部过亮

metahuman 下载材质 脸部灰白 脸部过亮

jacke121的专栏 244

windows在使用ping 127.0.0.1时出现一般故障的解决方案

本文主要介绍了windows在使用ping 127.0.0.1时出现一般故障的解决方案,希望能对使用windows的同学们有所帮助。 文章目录 1. 问题描述 2. 解决方案

weixin_43178406的博客 7万+

基于android2.3.5系统:开天辟地Android启动机制[四]

在我的博文基于android2.3.5学习之:开天辟地Android启动机制[三]中,详细的介绍了ueventd的解析机制,在分析andriod2.3.5中的action_list、action_queue、service_list,之前,还是先来详细介绍在Andriod是如何调用内核中的一些函数,比如:chown以及chroot等等。

嵌入式与人工智能天地 2363

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

Android内核学习文章

0、android系统启动 《Android系统启动流程 -- bootloader》 《The Android boot process from power on》 1、init 《深入理解android 卷1》 第3章 深入理解init 《Android框架揭秘》第3章 init进程 《Android的init过程详解(一)》 《

xin128888的专栏 1099

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

init 进程启动过程

init进程是Android系统中用户空间的第一个进程,进程号为1,是Android系统启动的一个关键步骤,作为第一个进程,它的主要工作是创建Zygote和启动属性服务等。init进程是由多个源文件共同组成的,源码目录在system/core/init中。

八归少年 767

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

安卓init进程详解

安卓init进程详解

似霰的博客 2557

Android 2

11、fragment生命周期关于Fragment的生命周期,博主写过Activity与Fragment生命周期详解,基本上把Fragment的生命周期详细介绍过,但是那仅仅是创建一个Fragmnet时的生命周期,而事实上Fragment的出现是为了动态的切换显示不同的界面的,因此我们对于Fragment的生命周期的了解不能仅仅停留在创建一个Fragment的时候,而是应该能够知道调用不同API切...

abcdefg221的专栏 695

《Linux设备节点创建》用户空间ueventd创建设备节点规则

一、devfs、udev和sysfs是什么关系? linux2.6之前使用devfs设备文件系统,它存在与内核空间; linux2.6之后使用udev设备文件系统,它存在与用户空间、但严重依赖与sysfs文件系统。 二、Android(使用linux2.6以后的设备节点创建策略)设备节点的创建   在Android中,没有独立的类似于udev或者mdev的用户程序,这个功能

快乐&&平凡 3097

ueventd 启动慢分析

1.ueventd 启动 init.c的main()函数中有一个巧妙的处理:可以通过判断第一个运行参数来启动不同的进程: 如果执行“./ueventd”,进入第一个条件分支,执行uevent_main()函数; 如果执行“./watchdog”,进入第二个条件分支,执行watchdogd_main()函数; 如果执行”./init”,跳过所有分支条件,继续执行main()函数。 system/core/init/main.cpp 51 int main(int argc, char** arg.

lihailin560的博客 1659

了解Android已发布的各种版本(即1.0、2.0、3.0、4.0、5.0、6.0、7.0、8.0)

Android操作系统是一个由Google和开放手持设备联盟共同开发发展的移动设备操作系统。 最早的一款系统是2008年9月,谷歌正式发布的Android 1.0系统,也就是Android最早的版本,随后不断的更新Android系统,2.1、2.2、2.3的连续推出使Android占据了大量的市场,2011年google发布了Android 3.0系统这个系统是为了平板电脑设计的,但是是一个

ZytheMoon的博客 2万+

Android系统源码分析-从init进程开始

Android系统底层用的是Linux,和Linux一样,init进程是Linux系统用户进程的第一个进程,它是由Linux内核(kenerl)启动的。其它所有的用户进程都是init进程的子进程。 我们从init进程来分析Android系统的启动流程。

记录和分享程序人生的点点滴滴 8251
上一篇: 基于mjpg-streamer-r63的源码分析之:基础知识详细解释[二]
下一篇: 基于android2.3.5系统:开天辟地Android启动机制[三]
wang-bob
博客等级 码龄20年 356粉丝 112原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值