由ueventd创建,代码:
系统:Android M
/*
* "/init"可执行程序入口
* system/core/init/init.cpp
*/
int main(int argc, char** argv) {
if (!strcmp(basename(argv[0]), "ueventd")) {
return ueventd_main(argc, argv);
}
......
}
/*
* system/core/init/ueventd.cpp
*/
int ueventd_main(int argc, char **argv)
{
......
device_init();
......
}
/* system/core/init/devices.cpp */
void device_init() {
......
coldboot("/sys/class");
coldboot("/sys/block");
coldboot("/sys/devices");
......
}
static void coldboot(const char *path)
{
DIR *d = opendir(path);
if(d) {
do_coldboot(d);
closedir(d);
}
}
/* Coldboot walks parts of the /sys tree and pokes the uevent files
** to cause the kernel to regenerate device add events that happened
** before init's device manager was started
**
** We drain any pending events from the netlink socket every time
** we poke another uevent file to make sure we don't overrun the
** socket's buffer.
*/
static void do_coldboot(DIR *d)
{
......
fd = openat(dfd, "uevent", O_WRONLY);
if(fd >= 0) {
write(fd, "add\n", 4);
close(fd);
handle_device_fd();
}
......
}
void handle_device_fd()
{
char msg[UEVENT_MSG_LEN+2];
int n;
while ((n = uevent_kernel_multicast_recv(device_fd, msg, UEVENT_MSG_LEN)) > 0) {
if(n >= UEVENT_MSG_LEN) /* overflow -- discard */
continue;
msg[n] = '\0';
msg[n+1] = '\0';
struct uevent uevent;
parse_event(msg, &uevent);
if (sehandle && selinux_status_updated() > 0) {
struct selabel_handle *sehandle2;
sehandle2 = selinux_android_file_context_handle();
if (sehandle2) {
selabel_close(sehandle);
sehandle = sehandle2;
}
}
handle_device_event(&uevent);
handle_firmware_event(&uevent);
}
}
static void handle_device_event(struct uevent *uevent)
{
if (!strcmp(uevent->action,"add") || !strcmp(uevent->action, "change") || !strcmp(uevent->action, "online"))
fixup_sys_perms(uevent->path);
if (!strncmp(uevent->subsystem, "block", 5)) {
handle_block_device_event(uevent);
} else if (!strncmp(uevent->subsystem, "platform", 8)) {
handle_platform_device_event(uevent);
} else {
handle_generic_device_event(uevent);
}
}
static void handle_generic_device_event(struct uevent *uevent)
{
const char *base;
const char *name;
char devpath[DEVPATH_LEN] = {0};
char **links = NULL;
name = parse_device_name(uevent, 64);
if (!name)
return;
struct ueventd_subsystem *subsystem =
ueventd_subsystem_find_by_name(uevent->subsystem);
if (subsystem) {
const char *devname;
switch (subsystem->devname_src) {
case DEVNAME_UEVENT_DEVNAME:
devname = uevent->device_name;
break;
case DEVNAME_UEVENT_DEVPATH:
devname = name;
break;
default:
ERROR("%s subsystem's devpath option is not set; ignoring event\n",
uevent->subsystem);
return;
}
if (!assemble_devpath(devpath, subsystem->dirname, devname))
return;
mkdir_recursive_for_devpath(devpath);
} else if (!strncmp(uevent->subsystem, "usb", 3)) {
if (!strcmp(uevent->subsystem, "usb")) {
if (uevent->device_name) {
if (!assemble_devpath(devpath, "/dev", uevent->device_name))
return;
mkdir_recursive_for_devpath(devpath);
}
else {
/* This imitates the file system that would be created
* if we were using devfs instead.
* Minors are broken up into groups of 128, starting at "001"
*/
int bus_id = uevent->minor / 128 + 1;
int device_id = uevent->minor % 128 + 1;
/* build directories */
make_dir("/dev/bus", 0755);
make_dir("/dev/bus/usb", 0755);
snprintf(devpath, sizeof(devpath), "/dev/bus/usb/%03d", bus_id);
make_dir(devpath, 0755);
snprintf(devpath, sizeof(devpath), "/dev/bus/usb/%03d/%03d", bus_id, device_id);
}
} else {
/* ignore other USB events */
return;
}
} else if (!strncmp(uevent->subsystem, "graphics", 8)) {
base = "/dev/graphics/";
make_dir(base, 0755);
} else if (!strncmp(uevent->subsystem, "drm", 3)) {
base = "/dev/dri/";
make_dir(base, 0755);
} else if (!strncmp(uevent->subsystem, "oncrpc", 6)) {
base = "/dev/oncrpc/";
make_dir(base, 0755);
} else if (!strncmp(uevent->subsystem, "adsp", 4)) {
base = "/dev/adsp/";
make_dir(base, 0755);
} else if (!strncmp(uevent->subsystem, "msm_camera", 10)) {
base = "/dev/msm_camera/";
make_dir(base, 0755);
} else if(!strncmp(uevent->subsystem, "input", 5)) {
base = "/dev/input/";
make_dir(base, 0755);
} else if(!strncmp(uevent->subsystem, "mtd", 3)) {
base = "/dev/mtd/";
make_dir(base, 0755);
} else if(!strncmp(uevent->subsystem, "sound", 5)) {
base = "/dev/snd/"; //snd在这里创建
make_dir(base, 0755);
} else if(!strncmp(uevent->subsystem, "misc", 4) &&
!strncmp(name, "log_", 4)) {
INFO("kernel logger is deprecated\n");
base = "/dev/log/";
make_dir(base, 0755);
name += 4;
} else
base = "/dev/";
links = get_character_device_symlinks(uevent);
if (!devpath[0])
snprintf(devpath, sizeof(devpath), "%s%s", base, name);
handle_device(uevent->action, devpath, uevent->path, 0,
uevent->major, uevent->minor, links);
}
浙公网安备 33010602011771号