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 }
# Make a symlink from /sbin/ueventd and /sbin/watchdogd to /init
SYMLINKS := \
$(TARGET_ROOT_OUT)/sbin/ueventd \
$(TARGET_ROOT_OUT)/sbin/watchdogd
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 }