Get the basic filesystem setup we need put together in the initramdisk
// on / and then we'll let the rc file figure out the rest.
if (is_first_stage) {
// (3)创建一些基本的目录;同时把一些文件系统Mount到相应的目录。
mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");//基于内存的文件系统
mkdir("/dev/pts", 0755);
mkdir("/dev/socket", 0755);
mount("devpts", "/dev/pts", "devpts", 0, NULL);//虚拟终端文件系统
#define MAKE_STR(x) __STRING(x)
mount("proc", "/proc", "proc", 0, "hidepid=2,gid=" MAKE_STR(AID_READPROC));//基于内存的虚拟文件系统,内部数据结构的接口
mount("sysfs", "/sys", "sysfs", 0, NULL);//用于把系统的设备和总线按层次组织起来
}
// We must have some place other than / to create the device nodes for
// kmsg and null, otherwise we won't be able to remount / read-only
// later on. Now that tmpfs is mounted on /dev, we can actually talk
// to the outside world.
// (4)把标准输入、标准输出和标准错误重定向到空设备文件/dev/_null_
open_devnull_stdio();
// (5)创建节点/dev/_msg_,这样init进程可以使用kernel的log系统来输出log
klog_init();
klog_set_level(KLOG_NOTICE_LEVEL);
NOTICE("init %s started!\n", is_first_stage ? "first stage" : "second stage");
if (!is_first_stage) {
// (6)在/dev目录下创建一个空文件.booting表示初始化正在进行,is_booting函数将依
// 靠.booting来判断进程是否处于初始化中
// Indicate that booting is in progress to background fw loaders, etc.
close(open("/dev/.booting", O_WRONLY | O_CREAT | O_CLOEXEC, 0000));
// (7)初始化Android属性系统。创建一个共享区域来存储属性值。
property_init();
// If arguments are passed both on the command line and in DT,
// properties set in DT always have priority over the command-line ones.
process_kernel_dt();
// (8)解析kernel的启动参数,通常放在/proc/cmdline中,利用解析结果参数中的值设置几个属性值
process_kernel_cmdline();
// Propagate the kernel variables to internal variables
// used by init as well as the current required properties.
export_kernel_boot_props();
}
// Set up SELinux, including loading the SELinux policy if we're in the kernel domain.
// (9)初始化SElinux
selinux_initialize(is_first_stage);
// If we're in the kernel domain, re-exec init to transition to the init domain now
// that the SELinux policy has been loaded.
if (is_first_stage) {
if (restorecon("/init") == -1) {
//按SELinux要求,重新设定/init文件属性
ERROR("restorecon failed: %s\n", strerror(errno));
security_failure();
}
char* path = argv[0];
char* args[] = { path, const_cast("--second-stage"), nullptr };
//设置参数--second-stage
if (execv(path, args) == -1) {
// 执行init进程,重新进入main函数
ERROR("execv(\"%s\") failed: %s\n", path, strerror(errno));
security_failure();
}
}
// These directories were necessarily created before initial policy load
// and therefore need their security context restored to the proper value.
// This must happen before /dev is populated by ueventd.
// 这些目录必须在初始策略加载之前创建,因此需要将其安全上下文恢复到适当的值。 这必须在/ dev由ueventd填充之前发生。
NOTICE("Running restorecon...\n");
restorecon("/dev");
restorecon("/dev/socket");
restorecon("/dev/__properties__");
restorecon("/property_contexts");
restorecon_recursive("/sys");
// Queue an action that waits for coldboot done so we know ueventd has set up all of /dev...
am.QueueBuiltinAction(wait_for_coldboot_done_action, "wait_for_coldboot_done"); //等待冷插拔设备初始化完成
// ... so that we can start queuing up actions that require stuff from /dev.
am.QueueBuiltinAction(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");
//从硬件RNG的设备文件/dev/hw_random中读取512字节并写到Linux RNG的设备文件/dev/urandom中。
am.QueueBuiltinAction(set_mmap_rnd_bits_action, "set_mmap_rnd_bits");
am.QueueBuiltinAction(keychord_init_action, "keychord_init");
//初始化组合键监听模块
am.QueueBuiltinAction(console_init_action, "console_init");
//在屏幕上显示Android字样的logo
// Trigger all the boot actions to get us started.
am.QueueEventTrigger("init");
// 添加触发器init,执行on init内容,主要包括创建/挂载一些目录,以及symlink等
// Repeat mix_hwrng_into_linux_rng in case /dev/hw_random or /dev/random
// wasn't ready immediately after wait_for_coldboot_done
am.QueueBuiltinAction(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");//重复以防冷插拔设备初始化后/dev/hw_random或者/dev/random未就绪
// Don't mount filesystems or start core system services in charger mode.
std::string bootmode = property_get("ro.bootmode");
if (bootmode == "charger") {
// 判断是否为充电模式
am.QueueEventTrigger("charger");
} else {
am.QueueEventTrigger("late-init");
// 非充电模式添加触发器late-init
}
// Run all property triggers based on current state of the properties.
am.QueueBuiltinAction(queue_property_triggers_action, "queue_property_triggers");//检查Action列表中通过修改属性来触发的Action,查看相关的属性值是否已经设置,如果已经设置,则将该Action加入到执行列表中。
/* 360OS begin */
get_cpu_id();
/* 360OS end */
// (15)处理添加到运行队列中的事件
while (true) {
if (!waiting_for_exec) {
am.ExecuteOneCommand();
//依次执行每个action中携带的命令
restart_processes();
//重启一些挂掉的进程
}
int timeout = -1;
if (process_needs_restart) {
//还有服务进程需要重启
timeout = (process_needs_restart - gettime()) * 1000;
//把timeout值设为下次启动服务的时间
if (timeout < 0)
timeout = 0;
}
if (am.HasMoreCommands()) {
//命令列表中还有命令
timeout = 0;
}
bootchart_sample(&timeout);
epoll_event ev;
int nr = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd, &ev, 1, timeout));
if (nr == -1) {
ERROR("epoll_wait failed: %s\n", strerror(errno));
} else if (nr == 1) {
((void (*)()) ev.data.ptr)();
}
}
return 0;
}
2、解析init.rc init.cpp的main函数中,(13)步对init.rc做了解析,这是我们比较关注的东西。
init.rc(/system/core/rootdir/init.rc)是什么?
init.rc是一个配置文件,内部由Android初始化语言编写(Android Init Language)编写的脚本,在Android中有特定的格式以及规则。
Android初始化语言由四大类型的声明组成,即Actions(动作)、Commands(命令)、Services(服务)、以及Options(选项)。所有这些都以行为单位,各种符号则用空格隔开。
1)init.rc(/system/core/rootdir/init.rc):
import /init.environ.rc
import /init.usb.rc
import /init.${ro.hardware}.rc
import /init.usb.configfs.rc
import /init.${ro.zygote}.rc
...
导入一些配置文件,zygote的.rc文件有多个。主要就是来区分不同的平台(32、64及64_32)。 init.rc文件进行了拆分,每个服务一个rc文件。
2)init.rc(/system/core/rootdir/init.rc):
...
on early-init
# Set init and its forked children's oom_adj.
write /proc/1/oom_score_adj -1000
# Disable sysrq from keyboard
write /proc/sys/kernel/sysrq 0
# Set the security context of /adb_keys if present.
restorecon /adb_keys
# Shouldn't be necessary, but sdcard won't start without it. http://b/22568628.
mkdir /mnt 0775 root system
# Set the security context of /postinstall if present.
restorecon /postinstall
start ueventd
...
on early-init为action类型语句,其一般格式为:
on [&& ]* //设置触发器
//动作触发之后要执行的命令
3)init.zygote64.rc(/system/core/rootdir/init.zygote64.rc):
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
class main
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart audioserver
onrestart restart cameraserver
onrestart restart media
onrestart restart netd
writepid /dev/cpuset/foreground/tasks /dev/stune/foreground/tasks
service zygote ...为service类型语句,其一般格式为:
service [ ]* //<执行程序路径><传递参数>
1,java读取.properties配置文件
InputStream in;
try {
in = test.class.getClassLoader().getResourceAsStream("config/ipnetOracle.properties");//配置文件的路径
Properties p = new Properties()
create or replace procedure proc_test01
as
type emp_row is record(
empno emp.empno%type,
ename emp.ename%type,
job emp.job%type,
mgr emp.mgr%type,
hiberdate emp.hiredate%type,
sal emp.sal%t
今天在执行一个脚本时,本来是想在脚本中启动hdfs和hive等程序,可以在执行到service hive-server start等启动服务的命令时会报错,最终解决方法记录一下:
脚本报错如下:
./olap_quick_intall.sh: line 57: service: command not found
./olap_quick_intall.sh: line 59
最近重新安装的电脑,配置了新环境,老是出现:
adb server is out of date. killing...
ADB server didn't ACK
* failed to start daemon *
百度了一下,说是端口被占用,我开个eclipse,然后打开cmd,就提示这个,很烦人。
一个比较彻底的解决办法就是修改
import java.util.HashMap;
public class Title {
public static void main(String[] args){
f();
}
// 二位数组的应用
//12、二维数组中,哪一行或哪一列的连续存放的0的个数最多,是几个0。注意,是“连续”。
public static void f(){