在init进程的main函数中有调用sigchld_handler_init() 设置SIGCHLD signal。这里设置SIGCHLD的处理函数时,在sa_flags中有加SA_NOCLDSTOP flag,这个flag表示只有当子进程终止时父进程才接受这个signal,当子进程在暂停或者继续运行的状态时是不会收到这个signal的。

void sigchld_handler_init() {// Create a signalling mechanism for SIGCHLD.int s[2];if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0, s) == -1) {PLOG(FATAL) << "socketpair failed in sigchld_handler_init";}signal_write_fd = s[0];signal_read_fd = s[1];// Write to signal_write_fd if we catch SIGCHLD.struct sigaction act;memset(&act, 0, sizeof(act));act.sa_handler = SIGCHLD_handler;act.sa_flags = SA_NOCLDSTOP;sigaction(SIGCHLD, &act, 0);ReapAnyOutstandingChildren();register_epoll_handler(signal_read_fd, handle_signal);
}

1. 注册的SIGCHLD处理函数是SIGCHLD_handler。

2. 调用register_epoll_handler()

init.cpp

void register_epoll_handler(int fd, void (*fn)()) {epoll_event ev;ev.events = EPOLLIN;ev.data.ptr = reinterpret_cast<void*>(fn);if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &ev) == -1) {PLOG(ERROR) << "epoll_ctl failed";}
}

  

1. 在子进程退出时,init进程会收到SIGCHLD signal,然后调用SIGCHLD_handler()进行处理。这个函数只是简单地调用write()

2. 由于上面有进行write,所以在init的main函数中的epoll_wait()会返回,然后调用通过register_epoll_handler()注册的函数,即hand_signal()

        epoll_event ev;int nr = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd, &ev, 1, epoll_timeout_ms));if (nr == -1) {PLOG(ERROR) << "epoll_wait failed";} else if (nr == 1) {((void (*)()) ev.data.ptr)();}

  

在hand_signal()中,首先调用read()将数据读出,然后会调用到ReapOneProcess()。在这个函数中,调用waitpid()等待子进程退出,waitpid()会拿到一个siginfo,这个siginfo中有退出的子进程的pid。

然后根据这个pid从ServiceList中找到这个退出的子进程的Service对象;

然后调用这个Service对象的Reap()。

在Reap函数中,首先调用KillProcessGroup(SIGKILL)。这个函数会调到system/core/libprocessgroup/processgroup.cpp中的killProcessGroup()。这个调用的目的是kill掉退出的子进程的所有子进程。

void Service::KillProcessGroup(int signal) {// If we've already seen a successful result from killProcessGroup*(), then we have removed// the cgroup already and calling these functions a second time will simply result in an error.// This is true regardless of which signal was sent.// These functions handle their own logging, so no additional logging is needed.if (!process_cgroup_empty_) {LOG(INFO) << "Sending signal " << signal << " to service '" << name_ << "' (pid " << pid_<< ") process group...";int r;if (signal == SIGTERM) {r = killProcessGroupOnce(uid_, pid_, signal);} else {r = killProcessGroup(uid_, pid_, signal);}if (r == 0) process_cgroup_empty_ = true;}
}

然后调用UnsetExec()将is_exec_service_running_设置为false并将SVC_EXEC flag清掉;

然后会将flags_中的SVC_RESTARTING flag设置上;

然后调用onrestart_.ExecuteAllCommands()

void Service::Reap(const siginfo_t& siginfo) {if (!(flags_ & SVC_ONESHOT) || (flags_ & SVC_RESTART)) {KillProcessGroup(SIGKILL);}// Remove any descriptor resources we may have created.std::for_each(descriptors_.begin(), descriptors_.end(),std::bind(&DescriptorInfo::Clean, std::placeholders::_1));for (const auto& f : reap_callbacks_) {f(siginfo);}if (flags_ & SVC_EXEC) UnSetExec();if (flags_ & SVC_TEMPORARY) return;pid_ = 0;flags_ &= (~SVC_RUNNING);start_order_ = 0;// Oneshot processes go into the disabled state on exit,// except when manually restarted.if ((flags_ & SVC_ONESHOT) && !(flags_ & SVC_RESTART)) {flags_ |= SVC_DISABLED;}// Disabled and reset processes do not get restarted automatically.if (flags_ & (SVC_DISABLED | SVC_RESET))  {NotifyStateChange("stopped");return;}// If we crash > 4 times in 4 minutes, reboot into recovery.boot_clock::time_point now = boot_clock::now();if ((flags_ & SVC_CRITICAL) && !(flags_ & SVC_RESTART)) {if (now < time_crashed_ + 4min) {if (++crash_count_ > 4) {LOG(FATAL) << "critical process '" << name_ << "' exited 4 times in 4 minutes";}} else {time_crashed_ = now;crash_count_ = 1;}}flags_ &= (~SVC_RESTART);
    flags_ |= SVC_RESTARTING;
// Execute all onrestart commands for this service.onrestart_.ExecuteAllCommands();NotifyStateChange("restarting");return;
}

然后在init的main函数的死循环中,会调用Service::is_exec_service_running()函数,这个函数是直接return Service class的is_exec_service_running_ static bool变量(注意这个变量是static变量)。

因为上面有将is_exec_service_running_变量设置为false,所以这个if条件成立,所以会调用RestartProcesses()。在这个函数中,会从ServiceList中取出每一个Service对象,然后判断其flags_变量中是否有SVC_RESTARTING flag,如果有,最终会调到这个service的Start()去再次启动这个service。

  

  

转载于:https://www.cnblogs.com/aspirs/p/11407611.html

android init重启service(进程)相关推荐

  1. android init.rc中启动的service 默认是disable的,后续如何启动此服务

    如果 android init.rc中启动的service 默认是disable的,如何才能启动此服务呢? init.rc中可以直接启动service 附带的参数决定启动程序的状态,例如数据业务中配置 ...

  2. Android init.rc分析

    1 前言 什么是init.rc文件? import /init.usb.rc import /init.${ro.hardware}.rc import /init.trace.rcon early- ...

  3. android 初始化语言,Android Init Language(安卓初始化语言)

    android源码学习目录 了解Android init进程的都知道,启动 init进程之前会解析init.rc文件,init.rc是Android的配置文件脚本,它由一种被称为"Andro ...

  4. Android init.rc 服务启动不成功

    Android init.rc 服务启动不成功 问题 在开发过程中发现一个问题,我们需要在开机的时候判断硬件版本号去启动服务, 服务的名字是ledservice和ledservice4,但是发现每次烧 ...

  5. Android 手机重启解决方案

    本篇文章主要介绍 Android 开发中的部分知识点,通过阅读本篇文章,您将收获以下内容: 1.MTK 平台AEE 搜集重启问题介绍 欢迎关注微信公众号:程序员Android 微信公众号:Progra ...

  6. Android如何降低service被杀死概率

    让app 的service常驻其实是很流氓的做法,但是需求摆在那里...  但是要清除一点:想百分百保活service在当前是无法做到的,只能降低service被杀死的概率,曾经看了多少篇网上大神的牛 ...

  7. Android Init Language(RC文件)介绍

    Android Init Language介绍 基本概念 什么是rc文件? Android Init进程用rc做了什么? 相关内容 Android RC文件应用 Android rc文件语法解析 Li ...

  8. Android Init(后期还会更加完善)

    代码分析基于android-12.0.0_r28 前期阶段 kernel/init/main.c: static int __ref kernel_init(void *unused) {// ... ...

  9. Android系统在新进程中启动自定义服务过程(startService)的原理分析 (下)

    Step 10. ActivityManagerService.attachApplicationLocked 这个函数定义在frameworks/base/services/java/com/and ...

  10. Android init.rc文件解析过程详解(三)

    Android init.rc文件解析过程详解(三) 三.相关结构体 1.listnode listnode结构体用于建立双向链表,这种结构广泛用于kernel代码中, android源代码中定义了l ...

最新文章

  1. http响应Last-Modified和ETag以及Apache和Nginx中的配置
  2. linux学习-awk工具
  3. 1013 Battle Over Cities(图的DFS解法)
  4. html月球绕地球转,CSS3地球公转,月球绕地球转
  5. FreeRTOS内核详解(1) —— 临界段保护原理
  6. 第二天:Swift手势操控弹性按钮
  7. C#LeetCode刷题之#686-重复叠加字符串匹配(Repeated String Match)
  8. 源码分析Dubbo Invoker概述----服务发现、集群、负载均衡、路由体系
  9. Python 数据类型 布尔类型
  10. Leecode-2 Add Two Numbers
  11. MATLAB自适应平滑滤波
  12. 计算机用户里的AppData,AppData是什么意思,Appdata文件夹可以删除吗?
  13. 浅谈探索性数据分析的方法—如何下手处理一堆繁杂的数据
  14. ✨✨✨【C语言】带你用最短的时间刷题(附解题思路、具体代码)不断更新(二)✨✨✨
  15. vue项目各个文件的作用
  16. 2014-11-20动态规划:顺推法与逆推法中递推公式的不同!
  17. 快一年没用工作了继续学习编程中。
  18. 京东店铺如何做好关联销售?
  19. SQL语句更改字段名
  20. 多元高斯分布(Multivariate Gaussian Distribution)(详细说明,便于理解)

热门文章

  1. java自己写不出来_java学习中,能看懂代码,但是自己写不出来怎么处理?
  2. 拓端tecdat|R语言有状态依赖强度的非线性、多变量跳跃扩散过程模型似然推断分析股票价格波动
  3. 拓端tecdat|R语言使用Bass模型进行手机市场产品周期预测
  4. 拓端tecdat|用Rapidminer做文本挖掘的应用:情感分析
  5. 拓端tecdat|使用R语言对进行地理空间数据可视化
  6. 网卡变慢_解Bug之路记一次线上请求偶尔变慢的排查
  7. C语言模拟信号量解决同步、互斥问题
  8. wpf textblock可以复制_C# WPF:这次把文件拖出去!
  9. 深度学习论文和开源代码
  10. eclipse中html设置,无法在eclipse中设置HTMLUNIT