本文共 3117 字,大约阅读时间需要 10 分钟。
Asynchronous function calls for boot performance个人理解主要是通过函数异步调用还减少启动时间,即将没有依赖且没有严格串行的程序可以异步执行来减少启动时间。异步函数调用的具体实现在kernel/async.c中。我们举例说明async的用法.这个例子是在drivers/acpi/battery.c中static int __init acpi_battery_init(void){ if (acpi_disabled) return -ENODEV;#可见在入口函数中,通过async_schedule来让acpi_battery_init_async 异步调用以#加快系统的启动时间,从这里可以知道acpi_battery_init_async和其他硬件没有依赖,且#没有严格的串行关系.注意这里会返回一个static async_cookie_t async_cookie;在模块的注销函数#中需要调用acpi_battery_init_async。 async_cookie = async_schedule(acpi_battery_init_async, NULL); return 0;}static void __exit acpi_battery_exit(void){# async_synchronize_cookie(async_cookie + 1); if (battery_driver_registered) { acpi_bus_unregister_driver(&acpi_battery_driver); battery_hook_exit(); }#ifdef CONFIG_ACPI_PROCFS_POWER if (acpi_battery_dir) acpi_unlock_battery_dir(acpi_battery_dir);#endif}#定义模块的入口函数module_init(acpi_battery_init);module_exit(acpi_battery_exit);所以async的用法就是这样。下来我们看看acpi_battery_init_async的具体实现async_cookie_t async_schedule(async_func_t func, void *data){#默认的domain是async_dfl_domain return __async_schedule(func, data, &async_dfl_domain);}static async_cookie_t __async_schedule(async_func_t func, void *data, struct async_domain *domain){ struct async_entry *entry; unsigned long flags; async_cookie_t newcookie; /* allow irq-off callers */#注册一个entry entry = kzalloc(sizeof(struct async_entry), GFP_ATOMIC); /* * If we're out of memory or if there's too much work * pending already, we execute synchronously. */#异步执行的函数执行的个数有限制,不能超过MAX_WORK,这个限制应该和memory有关 if (!entry || atomic_read(&entry_count) > MAX_WORK) { kfree(entry); spin_lock_irqsave(&async_lock, flags); newcookie = next_cookie++; spin_unlock_irqrestore(&async_lock, flags); /* low on memory.. run synchronously */ func(data, newcookie); return newcookie; }#初始化两个列表 INIT_LIST_HEAD(&entry->domain_list); INIT_LIST_HEAD(&entry->global_list);#初始化一个workqueue,并设置回调函数为async_run_entry_fn INIT_WORK(&entry->work, async_run_entry_fn); entry->func = func; entry->data = data; entry->domain = domain; spin_lock_irqsave(&async_lock, flags); /* allocate cookie and queue */ newcookie = entry->cookie = next_cookie++;#将新建的entry添加到全局列表中 list_add_tail(&entry->domain_list, &domain->pending); if (domain->registered) list_add_tail(&entry->global_list, &async_global_pending); atomic_inc(&entry_count); spin_unlock_irqrestore(&async_lock, flags); /* mark that this task has queued an async job, used by module init */ current->flags |= PF_USED_ASYNC;#开始调度workqueue,这里可以看明白async的精髓,以本例为例,也就是你调用module_init后你的函数不一定立刻运行了 /* schedule for execution */ queue_work(system_unbound_wq, &entry->work); return newcookie;}static void async_run_entry_fn(struct work_struct *work){ struct async_entry *entry = container_of(work, struct async_entry, work); unsigned long flags; ktime_t uninitialized_var(calltime), delta, rettime; /* 1) run (and print duration) */ if (initcall_debug && system_state < SYSTEM_RUNNING) { pr_debug("calling %lli_%pF @ %i\n", (long long)entry->cookie, entry->func, task_pid_nr(current)); calltime = ktime_get(); }#执行用户调用__async_schedule时传入的回调函数 entry->func(entry->data, entry->cookie); }
转载地址:http://rsnmi.baihongyu.com/