編輯:關於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一個子進程處理。
麥芒5和榮耀8哪個好 麥芒5和榮耀8對比
最近,華為的新機可以說是不斷湧出,這不,剛剛發布了由吳亦凡代言的榮耀8新機,隨之又發布了華為麥芒5,那麼有很多朋友都在問,麥芒5和榮耀8哪個好?麥芒5和榮耀
詳解Android App中的AsyncTask異步任務執行方式
基本概念AsyncTask:異步任務,從字面上來說,就是在我們的UI主線程運行的時候,異步的完成一些操作。AsyncTask允許我們的執行一個異步的任務在後台。我們可以將
Android實現漸變色的圓弧虛線效果
首先來看看效果圖:1,SweepGradient(梯度渲染)public SweepGradient (float cx, float cy, int[] colors,
Android用戶注冊界面簡單設計
本文實例為大家分享了Android用戶注冊界面的設計,供大家參考,具體內容如下I. 實例目標 設計一個用戶注冊界面,在其中要使用到一些基礎控件,如 文本框、編輯框、按鈕、