正文
这个函数主要作用将各种信号量,如SIGABRT,SIGBUS等的行为设置为SA_RESTART,一旦监听到这些信号即执行重启系统
static void install_reboot_signal_handlers() {
// Instead of panic'ing the kernel as is the default behavior when init crashes,
// we prefer to reboot to bootloader on development builds, as this will prevent
// boot looping bad configurations and allow both developers and test farms to easily
// recover.
struct sigaction action;
memset(&action, 0, sizeof(action));
sigfillset(&action.sa_mask);//将所有信号加入至信号集
action.sa_handler = [](int) {
// panic() reboots to bootloader
panic(); //重启系统
};
action.sa_flags = SA_RESTART;
sigaction(SIGABRT, &action, nullptr);
sigaction(SIGBUS, &action, nullptr);
sigaction(SIGFPE, &action, nullptr);
sigaction(SIGILL, &action, nullptr);
sigaction(SIGSEGV, &action, nullptr);
#if defined(SIGSTKFLT)
sigaction(SIGSTKFLT, &action, nullptr);
#endif
sigaction(SIGSYS, &action, nullptr);
sigaction(SIGTRAP, &action, nullptr);
}
1.4 add_environment
定义在platform/system/core/init/init.cpp
这个函数主要作用是将一个键值对放到一个Char数组中,如果数组中有key就替换,没有就插入,跟Java中的Map差不多
/* add_environment - add "key=value" to the current environment */
int add_environment(const char *key, const char *val)
{
size_t n;
size_t key_len = strlen(key);
/* The last environment entry is reserved to terminate the list */
for (n = 0; n < (arraysize(ENV) - 1); n++) {
/* Delete any existing entry for this key */
if (ENV[n] != NULL) {
/*
* C++中strcspn用于返回字符所在下标,相当于String的indexof
*/
size_t entry_key_len = strcspn(ENV[n], "=");
if ((entry_key_len == key_len) && (strncmp(ENV[n], key, entry_key_len) == 0)) { //如果key相同,删除对应数据
free((char*)ENV[n]);
ENV[n] = NULL;
}
}
/* Add entry if a free slot is available */
if (ENV[n] == NULL) { //如果没有对应key,则插入数据
char* entry;
asprintf(&entry, "%s=%s", key, val);
ENV[n] = entry;
return 0;
}
}
LOG(ERROR) << "No env. room to store: '" << key << "':'" << val << "'";
return -1;
}
二、 挂载文件系统并创建目录
bool is_first_stage = (getenv("INIT_SECOND_STAGE") == nullptr);//查看是否有环境变量INIT_SECOND_STAGE
/*
* 1.init的main方法会执行两次,由is_first_stage控制,first_stage就是第一阶段要做的事
*/
if (is_first_stage) {//只执行一次,因为在方法体中有设置INIT_SECOND_STAGE
boot_clock::time_point start_time = boot_clock::now();
// Clear the umask.
umask(0); //清空文件权限
// 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.
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));
// Don't expose the raw commandline to unprivileged processes.
chmod("/proc/cmdline", 0440);
gid_t groups[] = { AID_READPROC };
setgroups(arraysize(groups), groups);
mount("sysfs", "/sys", "sysfs", 0, NULL);
mount("selinuxfs", "/sys/fs/selinux", "selinuxfs", 0, NULL);
mknod("/dev/kmsg", S_IFCHR | 0600, makedev(1, 11));
mknod("/dev/random", S_IFCHR | 0666, makedev(1, 8));
mknod("/dev/urandom", S_IFCHR | 0666, makedev(1, 9));
...
}
...
}
2.1 mount
mount是用来挂载文件系统的,mount属于Linux系统调用
int mount(const char *source, const char *target, const char *filesystemtype,
unsigned long mountflags, const void *data);
参数:
source:将要挂上的文件系统,通常是一个设备名。
target:文件系统所要挂载的目标目录。
filesystemtype:文件系统的类型,可以是"ext2","msdos","proc","ntfs","iso9660"。。。
mountflags:指定文件系统的读写访问标志,可能值有以下
参数
|
含义
|
MS_BIND
|
执行bind挂载,使文件或者子目录树在文件系统内的另一个点上可视。
|
MS_DIRSYNC
|
同步目录的更新。
|
MS_MANDLOCK
|
允许在文件上执行强制锁。
|
MS_MOVE
|
移动子目录树。
|
MS_NOATIME
|
不要更新文件上的访问时间。
|
MS_NODEV
|
不允许访问设备文件。
|
MS_NODIRATIME
|
不允许更新目录上的访问时间。
|
MS_NOEXEC
|
不允许在挂上的文件系统上执行程序。
|
MS_NOSUID
|
执行程序时,不遵照set-user-ID和set-group-ID位。
|
MS_RDONLY
|
指定文件系统为只读。
|
MS_REMOUNT
|
重新加载文件系统。这允许你改变现存文件系统的mountflag和数据,而无需使用先卸载,再挂上文件系统的方式。
|
MS_SYNCHRONOUS
|
同步文件的更新。
|
MNT_FORCE
|
强制卸载,即使文件系统处于忙状态。
|
MNT_EXPIRE
|
将挂载点标记为过时。
|
data:文件系统特有的参数