linux内核初始化成功后是如何过度到android初始化的

2024-04-18 14:52

本文主要是介绍linux内核初始化成功后是如何过度到android初始化的,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Android用的linux内核,以完成OS该有的功能,例如,文件系统,网络,内存管理,进程调度,驱动等 ,向下管理硬件资源向上提供系统调用。另一些Android特有驱动也放在内核之中。
当linux内核启动完成后,便进行Android的初始化工作。

内核端

内核是在main.c中进行初始化,从kernel_init开始

static int __init kernel_init(void * unused)
{lock_kernel();/** init can run on any cpu.*/set_cpus_allowed_ptr(current, CPU_MASK_ALL_PTR);/** Tell the world that we're going to be the grim* reaper of innocent orphaned children.** We don't want people to have to make incorrect* assumptions about where in the task array this* can be found.*/init_pid_ns.child_reaper = current;cad_pid = task_pid(current);smp_prepare_cpus(setup_max_cpus);do_pre_smp_initcalls();start_boot_trace();smp_init();sched_init_smp();cpuset_init_smp();do_basic_setup();/** check if there is an early userspace init.  If yes, let it do all* the work*/if (!ramdisk_execute_command)ramdisk_execute_command = "/init";if (sys_access((const char __user *) ramdisk_execute_command, 0) != 0) {ramdisk_execute_command = NULL;prepare_namespace();}/** Ok, we have completed the initial bootup, and* we're essentially up and running. Get rid of the* initmem segments and start the user-mode stuff..*/init_post();return 0;
}

在main.c 函数init_post()开始执行Android相关代码

	if (ramdisk_execute_command) {run_init_process(ramdisk_execute_command);printk(KERN_WARNING "Failed to execute %s\n",ramdisk_execute_command);}/** We try each of these until one succeeds.** The Bourne shell can be used instead of init if we are* trying to recover a really broken machine.*/if (execute_command) {run_init_process(execute_command);printk(KERN_WARNING "Failed to execute %s.  Attempting ""defaults...\n", execute_command);}run_init_process("/sbin/init");run_init_process("/etc/init");run_init_process("/bin/init");run_init_process("/bin/sh");

run_init_process便是加载执行文件。可以看到有六处出现了这个函数,但是执行的是第一个,
也就是run_init_process(ramdisk_execute_command), 变量ramdisk_execute_command在kernel_init执行时被赋值为’/init’, 也就是说,将会执行根文件目录下的init进程,而这个进程正是Android的初始化进程.

Android端

在根目录下可以看到init是个软链接,真正的init文件在/system/bin下面
在这里插入图片描述
进入目录,真身就在里面

在这里插入图片描述
加载执行后,就是大家耳熟能详的init进程了,开始进入Android的世界。

int main(int argc, char** argv) {
#if __has_feature(address_sanitizer)__asan_set_error_report_callback(AsanReportCallback);
#endifif (!strcmp(basename(argv[0]), "ueventd")) {return ueventd_main(argc, argv);}if (argc > 1) {if (!strcmp(argv[1], "subcontext")) {android::base::InitLogging(argv, &android::base::KernelLogger);const BuiltinFunctionMap& function_map = GetBuiltinFunctionMap();return SubcontextMain(argc, argv, &function_map);}if (!strcmp(argv[1], "selinux_setup")) {return SetupSelinux(argv);}if (!strcmp(argv[1], "second_stage")) {return SecondStageMain(argc, argv);}}return FirstStageMain(argc, argv);
}

# init可执行文件的命名

在源码/system/core/init目录下查看mk和bp文件,在文件Android.mk中

LOCAL_MODULE := init_first_stage
LOCAL_MODULE_STEM := init

在文件Android.bp中

cc_binary {name: "init_second_stage",recovery_available: true,stem: "init",defaults: ["init_defaults"],static_libs: ["libinit"],required: ["e2fsdroid","init.rc","mke2fs","sload_f2fs","make_f2fs","ueventd.rc",],srcs: ["main.cpp"],symlinks: ["ueventd"],target: {recovery: {cflags: ["-DRECOVERY"],exclude_shared_libs: ["libbinder","libutils",],},},
}

在Android 11源码中,mk文件和bp文件还是共存的,但mk最终会被转换成bp文件。无论在初始化的第一阶段,还是第二阶段,其stem都是init。

这篇关于linux内核初始化成功后是如何过度到android初始化的的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/915090

相关文章

Linux使用nload监控网络流量的方法

《Linux使用nload监控网络流量的方法》Linux中的nload命令是一个用于实时监控网络流量的工具,它提供了传入和传出流量的可视化表示,帮助用户一目了然地了解网络活动,本文给大家介绍了Linu... 目录简介安装示例用法基础用法指定网络接口限制显示特定流量类型指定刷新率设置流量速率的显示单位监控多个

ElasticSearch+Kibana通过Docker部署到Linux服务器中操作方法

《ElasticSearch+Kibana通过Docker部署到Linux服务器中操作方法》本文介绍了Elasticsearch的基本概念,包括文档和字段、索引和映射,还详细描述了如何通过Docker... 目录1、ElasticSearch概念2、ElasticSearch、Kibana和IK分词器部署

Linux流媒体服务器部署流程

《Linux流媒体服务器部署流程》文章详细介绍了流媒体服务器的部署步骤,包括更新系统、安装依赖组件、编译安装Nginx和RTMP模块、配置Nginx和FFmpeg,以及测试流媒体服务器的搭建... 目录流媒体服务器部署部署安装1.更新系统2.安装依赖组件3.解压4.编译安装(添加RTMP和openssl模块

Android 悬浮窗开发示例((动态权限请求 | 前台服务和通知 | 悬浮窗创建 )

《Android悬浮窗开发示例((动态权限请求|前台服务和通知|悬浮窗创建)》本文介绍了Android悬浮窗的实现效果,包括动态权限请求、前台服务和通知的使用,悬浮窗权限需要动态申请并引导... 目录一、悬浮窗 动态权限请求1、动态请求权限2、悬浮窗权限说明3、检查动态权限4、申请动态权限5、权限设置完毕后

C++初始化数组的几种常见方法(简单易懂)

《C++初始化数组的几种常见方法(简单易懂)》本文介绍了C++中数组的初始化方法,包括一维数组和二维数组的初始化,以及用new动态初始化数组,在C++11及以上版本中,还提供了使用std::array... 目录1、初始化一维数组1.1、使用列表初始化(推荐方式)1.2、初始化部分列表1.3、使用std::

linux下多个硬盘划分到同一挂载点问题

《linux下多个硬盘划分到同一挂载点问题》在Linux系统中,将多个硬盘划分到同一挂载点需要通过逻辑卷管理(LVM)来实现,首先,需要将物理存储设备(如硬盘分区)创建为物理卷,然后,将这些物理卷组成... 目录linux下多个硬盘划分到同一挂载点需要明确的几个概念硬盘插上默认的是非lvm总结Linux下多

Android里面的Service种类以及启动方式

《Android里面的Service种类以及启动方式》Android中的Service分为前台服务和后台服务,前台服务需要亮身份牌并显示通知,后台服务则有启动方式选择,包括startService和b... 目录一句话总结:一、Service 的两种类型:1. 前台服务(必须亮身份牌)2. 后台服务(偷偷干

linux进程D状态的解决思路分享

《linux进程D状态的解决思路分享》在Linux系统中,进程在内核模式下等待I/O完成时会进入不间断睡眠状态(D状态),这种状态下,进程无法通过普通方式被杀死,本文通过实验模拟了这种状态,并分析了如... 目录1. 问题描述2. 问题分析3. 实验模拟3.1 使用losetup创建一个卷作为pv的磁盘3.

Linux环境变量&&进程地址空间详解

《Linux环境变量&&进程地址空间详解》本文介绍了Linux环境变量、命令行参数、进程地址空间以及Linux内核进程调度队列的相关知识,环境变量是系统运行环境的参数,命令行参数用于传递给程序的参数,... 目录一、初步认识环境变量1.1常见的环境变量1.2环境变量的基本概念二、命令行参数2.1通过命令编程

Linux之进程状态&&进程优先级详解

《Linux之进程状态&&进程优先级详解》文章介绍了操作系统中进程的状态,包括运行状态、阻塞状态和挂起状态,并详细解释了Linux下进程的具体状态及其管理,此外,文章还讨论了进程的优先级、查看和修改进... 目录一、操作系统的进程状态1.1运行状态1.2阻塞状态1.3挂起二、linux下具体的状态三、进程的