Linux裝置節點建立》使用者空間ueventd建立裝置節點規則
說明:本文基於Android2.3和Linux2.6,其餘版本僅供參考。
一、devfs、udev和sysfs是什麼關係?
linux2.6之前使用devfs裝置檔案系統,它存在與核心空間;
linux2.6之後使用udev裝置檔案系統,它存在與使用者空間、但嚴重依賴與sysfs檔案系統。
二、Android(使用linux2.6以後的裝置節點建立策略)裝置節點的建立
在Android中,沒有獨立的類似於udev或者mdev的使用者程式,這個功能整合到了init中做了。程式碼見:system/core/init/init.c檔案,如下:
- if (ufds[0].revents == POLLIN)
- handle_device_fd(device_fd);
其中handle_device_fd(device_fd)函式在system/core/init/devices.c中實現,引數device_fd 由函式device_init()->open_uevent_socket()->socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT)函式呼叫返回。
函式handle_device_fd(device_fd)中,根據傳進來的device_fd引數,呼叫recv(fd, msg, UEVENT_MSG_LEN, 0)函式,將核心探測到的裝置並通過NETLINK機制傳過來的socket描述符轉化成訊息。接著呼叫parse_event(msg, &uevent);函式將訊息翻譯成uevent事件,並將改事件傳遞給handle_device_event(&uevent)函式。
handle_device_event(&uevent)函式中,依據引數uevent->subsystem型別建立dev下的相應目錄,如:/dev/graphics。緊接著根據uevent->action是"add"還是"remove"來實現裝置節點的建立與刪除。如果uevent->action是"add",則呼叫make_device(devpath, block, uevent->major, uevent->minor)函式生成裝置節點。如果uevent->action是"remove",則呼叫unlink(devpath)對裝置節點進行刪除。
三、下邊看看Android的ueventd程序
說明:其配置檔案uevent.rc不起實際作用,只是對建立的裝置節點檔案屬性做設定。
1.system/core/init/ueventd.c
- int ueventd_main(int argc, char **argv){
- device_init();
- /*
- system/core/init/device.c
- void device_init(void){
- device_fd = uevent_open_socket(64*1024, true);
- coldboot("/sys/class");
- coldboot("/sys/block");
- coldboot("/sys/devices");
- }
- */
- ufd.events = POLLIN;
- ufd.fd = get_device_fd();
- while(1) {
- ufd.revents = 0;
- nr = poll(&ufd, 1, -1);
- if (nr <= 0)
- continue;
- if (ufd.revents == POLLIN)
- handle_device_fd();
- }
- }
2.system/core/init/device.c
注意:只有主次裝置號的事件才會建立裝置節點
- void handle_device_fd(){
- while ((n = uevent_kernel_multicast_recv(device_fd, msg, UEVENT_MSG_LEN)) > 0) {
- handle_device_event(&uevent);
- }
- }
- staticvoid handle_device_event(struct uevent *uevent){
- if (!strcmp(uevent->action,"add"))
- fixup_sys_perms(uevent->path);
- /* if it's not a /dev device, nothing else to do */
- if((uevent->major < 0) || (uevent->minor < 0)){//只有主次裝置號的事件才會建立裝置節點
- //ERROR("TK------------>>>>device.c>>>>>>handle_device_event>>>>>>uevent->major and minor < 0\n");//add by tankai
- return;
- }
- if(!strncmp(uevent->subsystem, "block", 5)) {
- block = 1;
- base = "/dev/block/";
- mkdir(base, 0755);
- if (!strncmp(uevent->path, "/devices/platform/", 18))
- links = parse_platform_block_device(uevent);
- } else {
- block = 0;
- /* this should probably be configurable somehow */
- if (!strncmp(uevent->subsystem, "usb", 3)) {
- if (!strcmp(uevent->subsystem, "usb")) {
- /* 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 */
- mkdir("/dev/bus", 0755);
- mkdir("/dev/bus/usb", 0755);
- snprintf(devpath, sizeof(devpath), "/dev/bus/usb/%03d", bus_id);
- mkdir(devpath, 0755);
- snprintf(devpath, sizeof(devpath), "/dev/bus/usb/%03d/%03d", bus_id, device_id);
- devpath_ready = 1;
- } else {
- /* ignore other USB events */
- return;
- }
- } elseif (!strncmp(uevent->subsystem, "graphics", 8)) {
- base = "/dev/graphics/";
- mkdir(base, 0755);
- } elseif (!strncmp(uevent->subsystem, "oncrpc", 6)) {
- base = "/dev/oncrpc/";
- mkdir(base, 0755);
- } elseif (!strncmp(uevent->subsystem, "adsp", 4)) {
- base = "/dev/adsp/";
- mkdir(base, 0755);
- } elseif (!strncmp(uevent->subsystem, "msm_camera", 10)) {
- base = "/dev/msm_camera/";
- mkdir(base, 0755);
- } elseif(!strncmp(uevent->subsystem, "input", 5)) {
- base = "/dev/input/";
- mkdir(base, 0755);
- } elseif(!strncmp(uevent->subsystem, "mtd", 3)) {
- base = "/dev/mtd/";
- mkdir(base, 0755);
- } elseif(!strncmp(uevent->subsystem, "sound", 5)) {
- base = "/dev/snd/";
- mkdir(base, 0755);
- } elseif(!strncmp(uevent->subsystem, "misc", 4) &&
- !strncmp(name, "log_", 4)) {
- base = "/dev/log/";
- mkdir(base, 0755);
- name += 4;
- } else
- base = "/dev/";
- }
- if (!devpath_ready)
- snprintf(devpath, sizeof(devpath), "%s%s", base, name);
- if(!strcmp(uevent->action, "add")) {
- //ERROR("TK------_>>>>>>>>>make_devices\n");//add by tankai
- make_device(devpath, uevent->path, block, uevent->major, uevent->minor);
- if (links) {
- for (i = 0; links[i]; i++)
- make_link(devpath, links[i]);
- }
- }
- }
- staticvoid make_device(constchar *path,
- constchar *upath,
- int block, int major, int minor)
- {
- mode = get_device_perm(path, &uid, &gid) | (block ? S_IFBLK : S_IFCHR);
- setegid(gid);
- mknod(path, mode, dev);
- chown(path, uid, -1);
- setegid(AID_ROOT);
- }