问题
Boot sequence in Android is defined via system/core/rootdir/init.rc
and other *.rc
files. Such approach allows to bind any action to any boot stage (early-init
, init
, etc). Also in system/core/init/init.cpp
is defined the following sequence of the boot:
- ...
;
- early-init
;
- wait_for_coldboot_done
;
- ...
;
- init
;
- ...
.
It means that some action inside imported *.rc
file binded to the early-init
stage can be started before coldboot
(and SELinux initialization) will be finished by the ueventd
.
So my question: does a native service work correctly if it will be started before coldboot
done (obviously it means that such service does not require any device which should be created by the ueventd
)?
回答1:
So my question: does a native service work correctly if it will be started before
coldboot
done?
Sometimes it may work correct but in general case it may fail. If native service doesn't interact with any device it doesn't require the /dev/
file system. But binderized services communicate via Binder IPC which is require opening the binder driver (for interact between kernel and userspace layers):
frameworks/native/include/binder/BinderService.h:
template<typename SERVICE>
class BinderService
{
public:
...
static void instantiate() { publish(); }
...
static status_t publish(bool allowIsolated = false) {
sp<IServiceManager> sm(defaultServiceManager());
return sm->addService(
String16(SERVICE::getServiceName()),
new SERVICE(), allowIsolated);
}
frameworks/native/libs/binder/IServiceManager.cpp:
sp<IServiceManager> defaultServiceManager()
{
...
ProcessState::self()->getContextObject(NULL));
frameworks/native/libs/binder/ProcessState.cpp:
sp<ProcessState> ProcessState::self()
{
...
gProcess = new ProcessState("/dev/binder");
return gProcess;
}
ProcessState::ProcessState(const char *driver)
: mDriverName(String8(driver))
, mDriverFD(open_driver(driver))
...
{
if (mDriverFD >= 0) {
// mmap the binder, providing a chunk of virtual address space to receive transactions.
mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
if (mVMStart == MAP_FAILED) {
// *sigh*
...
ALOGE("Using /dev/binder failed: unable to mmap transaction memory.\n");
LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver could not be opened. Terminating.");
}
static int open_driver(const char *driver)
{
int fd = open(driver, O_RDWR | O_CLOEXEC);
if (fd >= 0) {
...
} else {
ALOGW("Opening '%s' failed: %s\n", driver, strerror(errno));
}
return fd;
}
But the Binder driver /der/binder
(as well as /dev/hwbinder
and /dev/vndbinder
) is created at the coldboot
stage by the ueventd
according to ueventd.rc
.
system/core/rootdir/ueventd.rc:
...
/dev/binder 0666 root root
/dev/hwbinder 0666 root root
/dev/vndbinder 0666 root root
...
So if a native service was be started before coldboot
done it wouldn't open the /dev/binder
!
Also at before coldboot
done the cgrops
and SELinux
(not sure) are not initialized:
system/core/rootdir/init.rc:
on init
...
# Mount cgroup mount point for cpu accounting
mount cgroup none /acct cpuacct
mkdir /acct/uid
P.S. But if a service communicates in passthrough mode?
来源:https://stackoverflow.com/questions/46128774/start-native-service-at-early-init-before-coldboot-done