編輯:關於Android編程
(懶人最近想起我還有csdn好久沒打理了,這個android init躺在我的草稿箱中快5年了,稍微改改發出來吧)
ueventd主要是負責設備節點的創建、權限設定等一些列工作。服務通過使用uevent,監控驅動發送的消息,做進一步處理。
ueventd實際和init是同一個binary,只是走了不同分支,可參看前一部分。
ueventd的整體代碼比較簡單,主要是三部分:
解析ueventd.rc 初始化設備信息 循環polling uevent消息主函數及相關功能如下如下:
int ueventd_main(int argc, char **argv) { // 和init一樣,沒有std輸入輸出 open_devnull_stdio(); // 初始化kernel log,讓ueventd的log,通過kernel printk的log輸出到串口中 klog_init(); //解析和處理ueventd的rc文件 import_kernel_cmdline(0, import_kernel_nv); get_hardware_name(hardware, &revision); ueventd_parse_config_file(/ueventd.rc); snprintf(tmp, sizeof(tmp), /ueventd.%s.rc, hardware); ueventd_parse_config_file(tmp); // 設備初始化 device_init(); // polling uevent消息,對設備進行管理 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(); // polling到消息,處理event消息 } }
處理和解析ueventd.rc
這部分相比init.rc來說,巨簡單,沒什麼特別的。主要是通過rc文件,來控制目錄節點的權限。如:
/dev/ttyUSB2 0666 radio radio /dev/ts0710mux* 0640 radio radio /dev/ppp 0666 radio vpn # sysfs properties /sys/devices/virtual/input/input* enable 0666 system system /sys/devices/virtual/input/input* poll_delay 0666 system system詳情應該不需要展開,基本都能了解。
設備初始化
kernel在加載設備時,會通過socket發送uevent事件給userspace, 在init裡,通過接受這些uevent事件,來創建設備的節點。主要函數是device_init()
初始化函數為device_init,如下
void device_init(void) { suseconds_t t0, t1; struct stat info; int fd; sehandle = NULL; if (is_selinux_enabled() > 0) { sehandle = selinux_android_file_context_handle(); } /* is 256K enough? udev uses 16MB! */ device_fd = uevent_open_socket(256*1024, true); if(device_fd < 0) return; fcntl(device_fd, F_SETFD, FD_CLOEXEC); fcntl(device_fd, F_SETFL, O_NONBLOCK); if (stat(coldboot_done, &info) < 0) { t0 = get_usecs(); coldboot(/sys/class); coldboot(/sys/block); coldboot(/sys/devices); t1 = get_usecs(); fd = open(coldboot_done, O_WRONLY|O_CREAT, 0000); close(fd); log_event_print(coldboot %ld uS , ((long) (t1 - t0))); } else { log_event_print(skipping coldboot, already done ); } }
open_uevent_socket();
這是打開uevent的socket。這裡的uevent是用到netlink中的內核事件向用戶態通知(NETLINK_KOBJECT_UEVENT)功能,是內核和用戶態進行雙向數據傳輸的非常好的方式,除了eventd外,netd和vold也是使用uevent的。
初始化函數中,比較要注意的coldboot這個函數,字面意思是冷啟動,它的作用是,對那些在uventd啟動前,已經add上的驅動,再重新操作一下,讓他們再發一次event消息,上層號針對性處理。
這裡對 /sys/class,/sys/block和/sys/devices下的設備遍歷一遍:
static void do_coldboot(DIR *d) { struct dirent *de; int dfd, fd; dfd = dirfd(d); fd = openat(dfd, uevent, O_WRONLY); if(fd >= 0) { write(fd, add , 4); close(fd); handle_device_fd(); } while((de = readdir(d))) { DIR *d2; if(de->d_type != DT_DIR || de->d_name[0] == '.') continue; fd = openat(dfd, de->d_name, O_RDONLY | O_DIRECTORY); if(fd < 0) continue; d2 = fdopendir(fd); if(d2 == 0) close(fd); else { do_coldboot(d2); closedir(d2); } } }write(fd, add , 4)激活內核,重發add事件的uevent,handle_device_fd();針對event消息,做響應的處理。
uevent消息處理
初始化好了之後,daemon程序只要polling新的event事件即可,polling到了,就調用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] = ''; msg[n+1] = ''; struct uevent uevent; parse_event(msg, &uevent); handle_device_event(&uevent); handle_firmware_event(&uevent); } }
功能就是接受內核發的event消息,然後parser此消息,處理對應的消息事件。
這裡:
static void handle_device_event(struct uevent *uevent) { if (!strcmp(uevent->action,add) || !strcmp(uevent->action, change)) 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); } }
主要功能,就是根據發過來的uevent,創建/刪除設備節點,同時以ueventd.rc中描述的權限設置更新一些節點權限。
static void handle_firmware_event(struct uevent *uevent) { pid_t pid; int ret; if(strcmp(uevent->subsystem, firmware)) return; if(strcmp(uevent->action, add)) return; /* we fork, to avoid making large memory allocations in init proper */ pid = fork(); if (!pid) { process_firmware_event(uevent); exit(EXIT_SUCCESS); } }如果有協處理器, 還要下載協處理器的firmware,這裡是處理協處理器要下載firmware的指令,fork一個子進程處理。
最近,華為的新機可以說是不斷湧出,這不,剛剛發布了由吳亦凡代言的榮耀8新機,隨之又發布了華為麥芒5,那麼有很多朋友都在問,麥芒5和榮耀8哪個好?麥芒5和榮耀
基本概念AsyncTask:異步任務,從字面上來說,就是在我們的UI主線程運行的時候,異步的完成一些操作。AsyncTask允許我們的執行一個異步的任務在後台。我們可以將
首先來看看效果圖:1,SweepGradient(梯度渲染)public SweepGradient (float cx, float cy, int[] colors,
本文實例為大家分享了Android用戶注冊界面的設計,供大家參考,具體內容如下I. 實例目標 設計一個用戶注冊界面,在其中要使用到一些基礎控件,如 文本框、編輯框、按鈕、