1.ueventd 启动
init.c的main()函数中有一个巧妙的处理:可以通过判断第一个运行参数来启动不同的进程:
如果执行“./ueventd”,进入第一个条件分支,执行uevent_main()函数; 如果执行“./watchdog”,进入第二个条件分支,执行watchdogd_main()函数; 如果执行”./init”,跳过所有分支条件,继续执行main()函数。
system/core/init/main.cpp 51 int main(int argc, char** argv) { 52 #if __has_feature(address_sanitizer) 53 __asan_set_error_report_callback(AsanReportCallback); 54 #endif 55 56 if (!strcmp(basename(argv[0]), "ueventd")) { //判断是否是ueventd 进程 57 return ueventd_main(argc, argv); 58 } 59 60 if (argc > 1) { 61 if (!strcmp(argv[1], "subcontext")) { 62 android::base::InitLogging(argv, &android::base::KernelLogger); 63 const BuiltinFunctionMap function_map; 64 65 return SubcontextMain(argc, argv, &function_map); 66 } 67 68 if (!strcmp(argv[1], "selinux_setup")) { 69 return SetupSelinux(argv); 70 } 71 72 if (!strcmp(argv[1], "second_stage")) { 73 return SecondStageMain(argc, argv); 74 } 75 } 76 77 return FirstStageMain(argc, argv); 78 }system/core/rootdir/init.rc 15 on early-init 16 # Disable sysrq from keyboard 17 write /proc/sys/kernel/sysrq 0 18 19 # Set the security context of /adb_keys if present. 20 restorecon /adb_keys 21 22 # Set the security context of /postinstall if present. 23 restorecon /postinstall 24 25 mkdir /acct/uid 26 27 # memory.pressure_level used by lmkd 28 chown root system /dev/memcg/memory.pressure_level 29 chmod 0040 /dev/memcg/memory.pressure_level 30 start ueventd
system/core/init/ueventd.cpp 220 int ueventd_main(int argc, char** argv) { 221 /* 222 * init sets the umask to 077 for forked processes. We need to 223 * create files with exact permissions, without modification by 224 * the umask. 225 */ 226 umask(000); 227 228 android::base::InitLogging(argv, &android::base::KernelLogger); 229 230 LOG(INFO) << "ueventd started!"; 231 232 SelinuxSetupKernelLogging(); 233 SelabelInitialize(); 234 235 std::vector<std::unique_ptr<UeventHandler>> uevent_handlers; 236 237 // Keep the current product name base configuration so we remain backwards compatible and 238 // allow it to override everything. 239 // TODO: cleanup platform ueventd.rc to remove vendor specific device node entries (b/34968103) 240 auto hardware = android::base::GetProperty("ro.hardware", ""); 241 242 auto ueventd_configuration = ParseConfig({"/ueventd.rc", "/vendor/ueventd.rc", 243 "/odm/ueventd.rc", "/ueventd." + hardware + ".rc"}); 244 245 uevent_handlers.emplace_back(std::make_unique<DeviceHandler>( 246 std::move(ueventd_configuration.dev_permissions), 247 std::move(ueventd_configuration.sysfs_permissions), 248 std::move(ueventd_configuration.subsystems), android::fs_mgr::GetBootDevices(), true)); 249 uevent_handlers.emplace_back(std::make_unique<FirmwareHandler>( 250 std::move(ueventd_configuration.firmware_directories))); 251 252 if (ueventd_configuration.enable_modalias_handling) { 253 uevent_handlers.emplace_back(std::make_unique<ModaliasHandler>()); 254 } 255 UeventListener uevent_listener(ueventd_configuration.uevent_socket_rcvbuf_size); 256 257 if (access(COLDBOOT_DONE, F_OK) != 0) {//热启动就不进这里 258 ColdBoot cold_boot(uevent_listener, uevent_handlers); 259 cold_boot.Run(); 260 } 261 262 for (auto& uevent_handler : uevent_handlers) { 263 uevent_handler->ColdbootDone(); 264 } 265 266 // We use waitpid() in ColdBoot, so we can't ignore SIGCHLD until now. 267 signal(SIGCHLD, SIG_IGN); 268 // Reap and pending children that exited between the last call to waitpid() and setting SIG_IGN 269 // for SIGCHLD above. 270 while (waitpid(-1, nullptr, WNOHANG) > 0) { 271 } 272 273 uevent_listener.Poll([&uevent_handlers](const Uevent& uevent) { 274 for (auto& uevent_handler : uevent_handlers) { 275 uevent_handler->HandleUevent(uevent); 276 } 277 return ListenerAction::kContinue; 278 }); 279 280 return 0; 281 } 282 283 } // namespace init 284 } // namespace android
一般情况ueventd启动到创建 /dev/.coldboot_done,只需要2秒。如果有异常可以在这里添加log,看是哪里耗时。
205 void ColdBoot::Run() { 206 android::base::Timer cold_boot_timer; 207 208 RegenerateUevents(); //这个函数调用非常多的驱动接口,最容易出问题。99% ueventd耗时的就 是这里导致 209 210 ForkSubProcesses(); 211 212 DoRestoreCon(); 213 214 WaitForSubProcesses(); 215 216 close(open(COLDBOOT_DONE, O_WRONLY | O_CREAT | O_CLOEXEC, 0000)); 创建 #define COLDBOOT_DONE "/dev/.coldboot_done" 217 LOG(INFO) << "Coldboot took " << cold_boot_timer.duration().count() / 1000.0f << " seconds"; 218 }
2 .ueventd启动慢,或者ueventd耗时
system/core/init/ueventd.cpp 146 void ColdBoot::RegenerateUevents() { 147 uevent_listener_.RegenerateUevents([this](const Uevent& uevent) {//这个括号是一个回 调函数 148 uevent_queue_.emplace_back(std::move(uevent)); 149 return ListenerAction::kContinue; 150 }); 151 }
这段代码,看起来比较多,其实就做了一件事情,就是找出{"/sys/class", "/sys/block", "/sys/devices"} 目录下面的所有的uevent文件,往文件中写 add. 驱动的属性文件uevent收到"add"之后,就会做各种事情,如果驱动工程师是水平不高,随便搞几个delay,或者是死锁,就在这里有延时了,就算你在open的时候加了O_NONBLOCK ,也不会返回。
出现延时最多的可能就是 write(fd, "add\n", 4);这个地方
system/core/init/uevent_listener.cpp 130 ListenerAction UeventListener::RegenerateUeventsForDir(DIR* d, 131 const ListenerCallback& callback) const { 132 int dfd = dirfd(d); 133 134 int fd = openat(dfd, "uevent", O_WRONLY); 135 if (fd >= 0) { 136 write(fd, "add\n", 4); 137 close(fd); 138 139 Uevent uevent; 140 while (ReadUevent(&uevent)) { 141 if (callback(uevent) == ListenerAction::kStop) return ListenerAction::kStop; 142 } 143 } 144 145 dirent* de; 146 while ((de = readdir(d)) != nullptr) { 147 if (de->d_type != DT_DIR || de->d_name[0] == '.') continue; 148 149 fd = openat(dfd, de->d_name, O_RDONLY | O_DIRECTORY); 150 if (fd < 0) continue; 151 152 std::unique_ptr<DIR, decltype(&closedir)> d2(fdopendir(fd), closedir); 153 if (d2 == 0) { 154 close(fd); 155 } else { 156 if (RegenerateUeventsForDir(d2.get(), callback) == ListenerAction::kStop) { 157 return ListenerAction::kStop; 158 } 159 } 160 } 161 162 // default is always to continue looking for uevents 163 return ListenerAction::kContinue; 164 } 165 166 ListenerAction UeventListener::RegenerateUeventsForPath(const std::string& path, 167 const ListenerCallback& callback) const { 168 std::unique_ptr<DIR, decltype(&closedir)> d(opendir(path.c_str()), closedir); 169 if (!d) return ListenerAction::kContinue; 170 171 return RegenerateUeventsForDir(d.get(), callback); 172 } 173 174 static const char* kRegenerationPaths[] = {"/sys/class", "/sys/block", "/sys/devices"}; 175 176 void UeventListener::RegenerateUevents(const ListenerCallback& callback) const { 177 for (const auto path : kRegenerationPaths) { 178 if (RegenerateUeventsForPath(path, callback) == ListenerAction::kStop) return; 179 } 180 }经过搜索之后,发现有3个地方实现了uevent的 store_uevent,就是 write(fd, "add\n", 4);要写的地方。
sys/module/ 目录下面的uevent
kernel/msm-4.19/kernel/module.c 1201 static ssize_t store_uevent(struct module_attribute *mattr, 1202 struct module_kobject *mk, 1203 const char *buffer, size_t count) 1204 { 1205 int rc; 1206 1207 rc = kobject_synth_uevent(&mk->kobj, buffer, count); 1208 return rc ? rc : count; 1209 } 1210 1211 struct module_attribute module_uevent = 1212 __ATTR(uevent, 0200, NULL, store_uevent);sys/bus 目录下面的uevent
kernel/msm-4.19/drivers/base/bus.c 833 static ssize_t bus_uevent_store(struct bus_type *bus, 834 const char *buf, size_t count) 835 { 836 int rc; 837 838 rc = kobject_synth_uevent(&bus->p->subsys.kobj, buf, count); 839 return rc ? rc : count; 840 } 841 static BUS_ATTR(uevent, S_IWUSR, NULL, bus_uevent_store); 614 static ssize_t uevent_store(struct device_driver *drv, const char *buf, 615 size_t count) 616 { 617 int rc; 618 619 rc = kobject_synth_uevent(&drv->p->kobj, buf, count); 620 return rc ? rc : count; 621 } 622 static DRIVER_ATTR_WO(uevent);其他路径下的 uevent
kernel/msm-4.19/drivers/base/core.c 1073 static ssize_t uevent_store(struct device *dev, struct device_attribute *attr, 1074 const char *buf, size_t count) 1075 { 1076 int rc; 1077 1078 rc = kobject_synth_uevent(&dev->kobj, buf, count); 1079 1080 if (rc) { 1081 dev_err(dev, "uevent: failed to send synthetic uevent\n"); 1082 return rc; 1083 } 1084 1085 return count; 1086 } 1087 static DEVICE_ATTR_RW(uevent);最终都是调
kobject_synth_uevent
kernel/msm-4.19/lib/kobject_uevent.c 192 int kobject_synth_uevent(struct kobject *kobj, const char *buf, size_t count) 193 { 194 char *no_uuid_envp[] = { "SYNTH_UUID=0", NULL }; 195 enum kobject_action action; 196 const char *action_args; 197 struct kobj_uevent_env *env; 198 const char *msg = NULL, *devpath; 199 int r; 200 201 r = kobject_action_type(buf, count, &action, &action_args); 202 if (r) { 203 msg = "unknown uevent action string\n"; 204 goto out; 205 } 206 207 if (!action_args) { 208 r = kobject_uevent_env(kobj, action, no_uuid_envp); 209 goto out; 210 } 211 212 r = kobject_action_args(action_args, 213 count - (action_args - buf), &env); 214 if (r == -EINVAL) { 215 msg = "incorrect uevent action arguments\n"; 216 goto out; 217 } 218 219 if (r) 220 goto out; 221 222 r = kobject_uevent_env(kobj, action, env->envp); 223 kfree(env); 224 out: 225 if (r) { 226 devpath = kobject_get_path(kobj, GFP_KERNEL); 227 printk(KERN_WARNING "synth uevent: %s: %s", 228 devpath ?: "unknown device", 229 msg ?: "failed to send uevent"); 230 kfree(devpath); 231 } 232 return r; 233 }所有实现了uevent_ops->uevent方法的struct kobject都有可能导致延迟,或者是死锁。
把可以在这里把用时多的kobject就可以了。
454 int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, 455 char *envp_ext[]) 456 { 463 const struct kset_uevent_ops *uevent_ops; 478 top_kobj = kobj; 479 while (!top_kobj->kset && top_kobj->parent) 480 top_kobj = top_kobj->parent; 481 482 if (!top_kobj->kset) { 483 pr_debug("kobject: '%s' (%p): %s: attempted to send uevent " 484 "without kset!\n", kobject_name(kobj), kobj, 485 __func__); 486 return -EINVAL; 487 } 488 489 kset = top_kobj->kset; 490 uevent_ops = kset->uevent_ops; 553 if (uevent_ops && uevent_ops->uevent) { 554 retval = uevent_ops->uevent(kset, kobj, env); 555 if (retval) { 556 pr_debug("kobject: '%s' (%p): %s: uevent() returned " 557 "%d\n", kobject_name(kobj), kobj, 558 __func__, retval); 559 goto exit; 560 } 561 }init 进程会在这里等待60s,如果60秒ueventd还没起来,手机就会重启。
system/core/init/init.cpp 347 static Result<Success> wait_for_coldboot_done_action(const BuiltinArguments& args) { 348 Timer t; 349 std::chrono::nanoseconds timeout = 60s; 350 #ifdef SLOW_BOARD 351 timeout = 6000s; 352 #endif 353 354 LOG(VERBOSE) << "Waiting for " COLDBOOT_DONE "..."; 355 364 if (wait_for_file(COLDBOOT_DONE, timeout) < 0) { 365 LOG(FATAL) << "Timed out waiting for " COLDBOOT_DONE; 366 } 367 368 property_set("ro.boottime.init.cold_boot_wait", std::to_string(t.duration().count())); 369 return Success(); 370 }