init进程作为系统启动后用户空间的第一个进程,通过解析init.rc文件启动一些系统服务进程,为防止子进程成为僵尸进程,init进程需要监测子进程状态。
本文以Android 13代码为例。
1,在/system/core/init/init.cpp文件中
在第二个启动阶段的SecondStageMain函数中进行信号的处理
int SecondStageMain(int argc, char** argv) {
Epoll epoll; //初始化epoll实例,用于处理I/O事件
if (auto result = epoll.Open(); !result.ok()) {
PLOG(FATAL) << result.error();
}
InstallSignalFdHandler(&epoll); //安装信号处理器
}
static void InstallSignalFdHandler(Epoll* epoll) {
//新建一个sigaction结构体,sa_handler是信号处理函数,指向内核指定的函数指针SIG_DFL,和Android 9.0及之前的版本不同,这里不再通过socket的读写句柄进行接收信号,改成了内核的信号处理函数SIG_DFL
//将SA_NOCLDSTOP应用于默认的SIGCHLD处理程序可以防止signalFd在子进程停止或继续时接收SIGCHLD,即SA_NOCLDSTOP使init进程只有在其子进程终止时才会受到SIGCHLD信号。
const struct sigaction act { .sa_handler = SIG_DFL, .sa_flags = SA_NOCLDSTOP }; //新建一个sigaction结构体,sa_handler是信号处理函数,指向内核指定的函数指针SIG_DFL.
sigaction(SIGCHLD, &act, nullptr); //建立信号绑定关系,也就是说当监听到SIGCHLD信号时,由act这个sigaction结构体处理
sigset_t mask; //初始化信号集,准备将其用于signalfd的创建
sigemptyset(&mask);
sigaddset(&mask, SIGCHLD);
signal_fd = signalfd(-1, &mask, SFD_CLOEXEC | SFD_NONBLOCK); //创建一个signalfd,用于接收上面定义的信号集mask中的信号.它允许应用程序通过文件描述符接口接收信号
if (signal_fd == -1) {
PLOG(FATAL) << "failed to create signalfd";
}
constexpr int flags = EPOLLIN | EPOLLPRI; //EPOLLIN表示对应的文件描述符准备好进行读操作,而EPOLLPRI表示有紧急的数据可读
//std::bind的第一个参数是要绑定的函数,后续参数是该函数的参数.当事件发生时,handler将作为一个回调,被epoll机制调用,执行HandleSignalFd函数,并传入false作为HandleSignalFd的参数。
auto handler = std::bind(HandleSignalFd, false); //使用std::bind来创建一个可调用对象handler,它绑定了HandleSignalFd函数和一个参数false
//将前面定义的事件处理器handler和事件标志flags注册到epoll实例上,以监视signal_fd(一个信号文件描述符)上的事件。
if (auto result = epoll->RegisterHandler(signal_fd, handler, flags); !result.ok()) {
LOG(FATAL) << result.error();
}
}
2,在system/core/init/epoll.cpp文件中
Result<void> Epoll::RegisterHandler(int fd, Handler handler, uint32_t events) { //向epoll事件监听机制中注册一个新的文件描述符(fd)和对应的处理函数(handler),以及该fd感兴趣的事件(events)
if (!events) {
return Error() << "Must specify events";
}
Info info;
info.events = events;
info.handler = std::make_shared<decltype(handler)>(std::move(handler)); //使用std::make_shared来创建一个Handler的智能指针,以便在epoll事件触发时能够安全地调用处理函数。
auto [it, inserted] = epoll_handlers_.emplace(fd, std::move(info)); //使用std::map将fd和Info结构体关联起来。如果fd已经存在于映射中,表示已经为该fd注册了处理函数,因此返回错误。
if (!inserted) {
return Error() << "Cannot specify two epoll handlers for a given FD";
}
epoll_event ev; //创建一个epoll_event结构体实例ev
ev.events = events;
// std::map's iterators do not get invalidated until erased, so we use the
// pointer to the std::function in the map directly for epoll_ctl.
ev.data.ptr = reinterpret_cast<void*>(&it->second);
if (epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, fd, &ev) == -1) { //调用epoll_ctl函数将fd加入到epoll_fd_的监听队列中
Result<void> result = ErrnoError() << "epoll_ctl failed to add fd";
epoll_handlers_.erase(fd);
return result;
}
return {};
}
3,在/system/core/init/init.cpp文件中
static void HandleSignalFd(bool one_off) {
signalfd_siginfo siginfo;
do {
ssize_t bytes_read = TEMP_FAILURE_RETRY(read(signal_fd, &siginfo, sizeof(siginfo))); //从signal_fd中读取信号信息到siginfo结构体中
if (bytes_read < 0 && errno == EAGAIN) {
auto now = std::chrono::steady_clock::now();
std::chrono::duration<double> waited = now - started;
if (waited >= kDiagnosticTimeout) {
LOG(ERROR) << "epoll() woke us up, but we waited with no SIGCHLD!";
started = now;
}
std::this_thread::sleep_for(100ms);
continue;
}
if (bytes_read != sizeof(siginfo)) {
PLOG(ERROR) << "Failed to read siginfo from signal_fd";
return;
}
break; //如果read调用成功读取了siginfo结构体大小的字节数,则跳出循环
} while (!one_off);
switch (siginfo.ssi_signo) {
//当init进程启动一个子进程时,它会继续运行并等待来自其子进程的信号或消息。如果子进程结束了,内核会向init进程发送SIGCHLD信号。
case SIGCHLD:
ReapAnyOutstandingChildren(); //终止出现问题的子进程,会走到sigchld_handler.cpp中的ReapOneProcess函数
break;
case SIGTERM:
HandleSigtermSignal(siginfo);
break;
default:
PLOG(ERROR) << "signal_fd: received unexpected signal " << siginfo.ssi_signo;
break;
}
}
在Android系统中,子进程并不直接给init进程发送SIGCHLD信号。SIGCHLD信号是当一个进程终止或停止时,由内核发送给其父进程的信号。这个机制是UNIX和类UNIX系统(包括Android)中进程管理的一部分,用于通知父进程其子进程的状态变化。
init进程通过信号处理器(signal handler)HandleSignalFd来响应SIGCHLD信号。当init进程接收到SIGCHLD信号时,它会执行一个特定的函数(即信号处理器)ReapOneProcess来处理这个信号。
4,在system/core/init/sigchld_handler.cpp文件中
void ReapAnyOutstandingChildren() {
while (ReapOneProcess() != 0) {
}
}
static pid_t ReapOneProcess() {
siginfo_t siginfo = {};
// This returns a zombie pid or informs us that there are no zombies left to be reaped.
// It does NOT reap the pid; that is done below.
if (TEMP_FAILURE_RETRY(waitid(P_ALL, 0, &siginfo, WEXITED | WNOHANG | WNOWAIT)) != 0) { //用waitpid函数获取状态发生变化的子进程pid
PLOG(ERROR) << "waitid failed";
return 0;
}
auto pid = siginfo.si_pid;
if (pid == 0) return 0;
std::string name;
std::string wait_string;
Service* service = nullptr;
service = ServiceList::GetInstance().FindService(pid, &Service::pid);//查找死亡进程服务
if (service) {
name = StringPrintf("Service '%s' (pid %d)", service->name().c_str(), pid);
if (service->flags() & SVC_EXEC) {
auto exec_duration = boot_clock::now() - service->time_started();
auto exec_duration_ms =
std::chrono::duration_cast<std::chrono::milliseconds>(exec_duration).count();
wait_string = StringPrintf(" waiting took %f seconds", exec_duration_ms / 1000.0f);
} else if (service->flags() & SVC_ONESHOT) {
auto exec_duration = boot_clock::now() - service->time_started();
auto exec_duration_ms =
std::chrono::duration_cast<std::chrono::milliseconds>(exec_duration)
.count();
wait_string = StringPrintf(" oneshot service took %f seconds in background",
exec_duration_ms / 1000.0f);
}
} else {
name = StringPrintf("Untracked pid %d", pid);
}
service->Reap(siginfo); //调用system/core/init/service.cpp中的Reap函数清理子进程
}
5,在system/core/init/service.cpp文件中
void Service::Reap(const siginfo_t& siginfo) {
if (!(flags_ & SVC_ONESHOT) || (flags_ & SVC_RESTART)) {
KillProcessGroup(SIGKILL, false); //杀死进程
}
for (const auto& socket : sockets_) {
if (socket.persist) {
continue;
}
auto path = ANDROID_SOCKET_DIR "/" + socket.name;
unlink(path.c_str());
}
if (name_ == "zygote" || name_ == "zygote64") { //如果是zygote则清除所有服务进程
removeAllEmptyProcessGroups();
}
flags_ &= (~SVC_RESTART);
flags_ |= SVC_RESTARTING; //设置重启标志位
onrestart_.ExecuteAllCommands();//执行rc中该服务的所有onrestart命令
}
6,此时在system/core/init/init.cpp文件中
int SecondStageMain(int argc, char** argv) {
while (true) { //这是一个无限循环,init进程在这里处理各种事件和任务,如执行命令、处理进程动作、等待epoll事件等
if (!IsShuttingDown()) {
auto next_process_action_time = HandleProcessActions(); //nit进程的死循环中HandleProcessActions会处理服务重启
// If there's a process that needs restarting, wake up in time for that.
if (next_process_action_time) {
epoll_timeout = std::chrono::ceil<std::chrono::milliseconds>(
*next_process_action_time - boot_clock::now());
if (*epoll_timeout < 0ms) epoll_timeout = 0ms;
}
}
}
}
static std::optional<boot_clock::time_point> HandleProcessActions() {
//遍历所有的service
for (const auto& s : ServiceList::GetInstance()) {
if (!(s->flags() & SVC_RESTARTING))
continue;
auto restart_time = s->time_started() + s->restart_period();
if (boot_clock::now() > restart_time) {
if (auto result = s->Start(); !result.ok()) { //调用start重启服务
LOG(ERROR) << "Could not restart process '" << s->name() << "': " << result.error();
}
} else {
if (!next_process_action_time || restart_time < *next_process_action_time) {
next_process_action_time = restart_time;
}
}
}
}
7,在system/core/init/service.cpp文件中
Result<void> Service::Start() {
pid_t pid = -1;
if (namespaces_.flags) {
pid = clone(nullptr, nullptr, namespaces_.flags | SIGCHLD, nullptr);
} else {
pid = fork();
}
if (pid == 0) {
umask(077);
RunService(override_mount_namespace, descriptors, std::move(pipefd));//在子进程中运行服务
_exit(127);
}
}
void Service::RunService(const std::optional<MountNamespace>& override_mount_namespace,
const std::vector<Descriptor>& descriptors,std::unique_ptr<std::array<int, 2>, decltype(&ClosePipe)> pipefd) {
if (!ExpandArgsAndExecv(args_, sigstop_)) { //调用ExpandArgsAndExecv执行
PLOG(ERROR) << "cannot execv('" << args_[0]
<< "'). See the 'Debugging init' section of init's README.md for tips";
}
}
static bool ExpandArgsAndExecv(const std::vector<std::string>& args, bool sigstop) {
std::vector<std::string> expanded_args;
std::vector<char*> c_strings;
expanded_args.resize(args.size());
c_strings.push_back(const_cast<char*>(args[0].data()));
for (std::size_t i = 1; i < args.size(); ++i) {
auto expanded_arg = ExpandProps(args[i]);
if (!expanded_arg.ok()) {
LOG(FATAL) << args[0] << ": cannot expand arguments': " << expanded_arg.error();
}
expanded_args[i] = *expanded_arg;
c_strings.push_back(expanded_args[i].data());
}
c_strings.push_back(nullptr);
if (sigstop) {
kill(getpid(), SIGSTOP);
}
return execv(c_strings[0], c_strings.data()) == 0; //执行c_string[0]对应的文件,比如启动zygote64
}
调用execv执行可执行文件即可启动相应的服务。