forked from xuzhongxing/fuchsia-notes
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathappmgr.txt
346 lines (281 loc) · 14.9 KB
/
appmgr.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
appmgr的启动
static const char* argv_appmgr[] = { "/system/bin/appmgr" };
appmgr_hnds[0] = appmgr_req_srv;
devmgr_launch(fuchsia_job_handle, "appmgr", countof(argv_appmgr),
argv_appmgr, NULL, -1, appmgr_hnds, appmgr_ids,
appmgr_hnd_count, NULL, FS_FOR_APPMGR);
env是空
launchpad_create(job_copy, name, &lp);
launchpad_create_with_jobs(job, xjob, name, result);
zx_process_create(creation_job, name, name_len, 0, &proc, &vmar);
launchpad_create_with_process(proc, vmar, &lp)
file_vmo = devmgr_load_file("/system/bin/appmgr")
bootfs_open(&bootfs, path + 6, &vmo);
zx_vmo_clone(bfs->vmo, ZX_VMO_CLONE_COPY_ON_WRITE,
e->data_off, e->data_len, &vmo)
launchpad_load_from_vmo(lp, file_vmo)
launchpad_file_load_with_vdso(lp, vmo);
launchpad_file_load(lp, vmo);
launchpad_elf_load_body(lp, first_line, to_read, vmo);
不是脚本,作为elf 加载
elf_load_start(vmo, hdr_buf, buf_sz, &elf)
elf_load_get_interp(elf, vmo, &interp, &interp_len)
handle_interp(lp, vmo, interp, interp_len)
加载动态连接器
elf_load_start(interp_vmo, NULL, 0, &elf)
elf_load_finish(lp_vmar(lp), elf, interp_vmo,
&segments_vmar, &lp->base, &lp->entry);
真正的exe vmo会作为HND_EXEC_VMO类型的handle传给ld.so
launchpad_load_vdso(lp, ZX_HANDLE_INVALID);
launchpad_elf_load_extra(lp, vmo, &lp->vdso_base, NULL);
elf_load_start(vmo, NULL, 0, &elf)
elf_load_finish(lp_vmar(lp), elf, vmo, NULL, base, entry)
launchpad_add_vdso_vmo(lp);
launchpad_go(lp, proc, &errmsg)
launchpad_start(lp, &h);
prepare_start(lp, "initial-thread", to_child, &thread, &sp);
zx_thread_create(lp_proc(lp), thread_name,strlen(thread_name), 0, thread);
send_loader_message(lp, *thread, to_child);
把arg, env, names作为消息发送给新进程
names包含了那些appmgr可见的namespace的路径,定义在devmgr-fdio.c:FSTAB
create stack vmo for the new thread
zx_process_start(proc, thread, lp->entry, sp, child_bootstrap, lp->vdso_base);
动态链接库是libc.so. 入口在dl-entry.S文件里。这里会链接真正的可执行文件,找到
它的入口地址,进入它。实现在zircon/third_party/ulib/musl/ldso/dynlink.c
这里推测,fuchsia认为动态链接是libc的功能,不是libzircon的功能。
可执行文件的入口在zircon/third_party/ulib/musl/arch/aarch64/Scrt1.S
__libc_start_main()设置一些全局变量
__environ
__zircon_process_self;
__zircon_vmar_root_self;
__zircon_job_default;
main_thread_handle
__allocate_thread分配线程需要的内存
进入start_main(),调用构造函数。进入main!
argv = "/system/bin/appmgr"
async::Loop loop(&kAsyncLoopConfigMakeDefault)
async_loop_create(config, &loop_)
fs::SynchronousVfs vfs(loop.async())
缺省构造函数
component::RootLoader root_loader
一个服务,用的fidl接口, 重载LoadComponent()
directory->AddEntry(
component::Loader::Name_, //"component.Loader"
fbl::AdoptRef(new fs::Service([&root_loader](zx::channel channel) {
root_loader.AddBinding(
fidl::InterfaceRequest<component::Loader>(std::move(channel)));
return ZX_OK;
})));
让"component.Loader"对应到一个fs::Service上。Service是Vnode的一种。
Connector = fbl::Function<zx_status_t(zx::channel channel)>;
vfs.ServeDirectory(directory, std::move(h2)
请求从h2进来
// Tell the calling process that we've mounted the directory.
r = channel.signal_peer(0, ZX_USER_SIGNAL_0)
vn->Serve(this, fbl::move(channel), ZX_FS_RIGHT_ADMIN);
vfs->ServeConnection(fbl::make_unique<Connection>(vfs, fbl::WrapRefPtr(this), fbl::move(channel), flags));
connection->Serve()
wait_.set_object(channel_.get());
wait_.object = object;
wait_.Begin(vfs_->async());
async_begin_wait(async, &wait_)
async->ops->v1.begin_wait(async, wait)
zx_object_wait_async(
wait->object, loop->port, (uintptr_t)wait, wait->trigger, ZX_WAIT_ASYNC_ONCE);
把前面那个h2挂到async loop的port上
h1交给Realm, 让Realm能够向component.Loader这个服务发送请求
接下来仔细看看Realm的构造
component::Realm root_realm(nullptr, std::move(h1), kRootLabel)
parent_是空
构造一个缺省的default_namespace_
Namespace(nullptr, this, nullptr)
services_.set_backend(std::move(services_backend)); ServiceProviderBridge
services_.AddService<Environment>(
[this](fidl::InterfaceRequest<Environment> request) {
environment_bindings_.AddBinding(this, std::move(request));
});
AddServiceForName()
name_to_service_connector_[service_name] = std::move(connector);
构造RealmHub
vfs获取缺省的async
zx::channel::create(0, &svc_channel_server_, &svc_channel_client_)
看看后面怎么用这个通道
hub_.AddServices(default_namespace_->services());
default_namespace_->services().set_backing_dir(std::move(host_directory))
把通向"component.Loader"目录服务的通道赋值给ServiceProviderDirImpl的backing_dir_
ServiceProviderPtr service_provider;
ServiceProviderPtr是InterfacePtr<ServiceProvider>
我们先看这个函数调用,
service_provider.NewRequest()
zx::channel::create(0, &h1, &h2)
创建一个通道,一头给Bind(),另一头返回
Bind(std::move(h1), async)
impl_->controller.reader().Bind(std::move(channel), async)
impl里有ServiceProvider::Proxy_ 和 fidl::internal::ProxyController
ProxyController里的MessageReader reader_监听h1
wait_.object = channel_.get()
async_begin_wait(async_, &wait_)
controller收到消息会调用proxy_->Dispatch_()
h1这头的处理目前看好像是fidl生成的缺省代码
service_provider应该是作为客户端,所以还不需要处理返回的消息
return InterfaceRequest<ServiceProvider>(std::move(h2));
返回h2
ServiceProviderBridge::AddBinding(h2)
bindings_.AddBinding(this, std::move(request))
this是ServiceProviderBridge自己 ImplPtr=ServiceProviderBridge*
Binding(impl, request)
Binding(std::forward<ImplPtr>(impl)
impl_(std::forward<ImplPtr>(impl)), stub_(&*this->impl())
stub_是ServiceProvider::Stub_,这个类的Dispatch_()会调用impl的ConnectToService(),
也就是ServiceProviderBridge::ConnectToService()
controller_.reader().Bind(std::move(channel), async);
这里设置处理来自service_provider的请求
把channel挂到事件循环上
bindings_.push_back()
binding的类型是这个::fidl::Binding<ServiceProvider, InterfaceRequest<ServiceProvider>>
建立了一个通道,一头让ServiceProvider::Proxy_处理,另一头给了ServiceProviderBridge添加binding,监听上
service_provider.get()
返回impl里的ServiceProvider::Proxy_ 它继承了ServiceProvider
下面这个ConnectToService的定义在connect.h里
loader_ = ConnectToService<Loader>(ServiceProvider::Proxy_) 模板类型是Loader, interface_name="component.Loader"
这里service_provider是ServiceProvider::Proxy_
InterfacePtr<Loader> interface_ptr
先看interface_ptr.NewRequest()
创建通道,一头h1是Loader::Proxy_缺省处理,另一头h2返回
service_provider->ConnectToService("component.Loader",h2)
这个函数是fidl生成的
controller_->Send
把h2发送给了ServiceProviderDirImpl,因为之前通道的另一头给了ServiceProviderDirImpl::AddBinding(h2)
ServiceProviderDirImpl::ConnectToService()会被调用,把h2发送给RootLoader::AddBinding监听起来
fdio_service_connect_at()
RootLoader::AddBinding
返回InterfacePtr<Loader>
上面这段代码的含义就是通过service_provider建立和Loader这个服务的联系
service_provider是个客户端,它被AddBinding到ServiceProviderBridge里。
ServiceProviderDirImpl本身是个服务,它的唯一的服务内容就是去ConnectToService()
PublishRootDir(&root_realm, &publish_vfs);
request = zx_get_startup_handle(PA_DIRECTORY_REQUEST)
dir(fbl::AdoptRef(new fs::PseudoDir()
svc = fbl::AdoptRef(new fs::Service([root](zx::channel channel) {
return root->BindSvc(std::move(channel));
}));
碰到Serve请求会调用这个函数。
fdio_service_clone_to(root_realm->svc_channel_client_.get(),channel.release());
zxrio_connect(svc, srv, ZXRIO_CLONE, ZX_FS_RIGHT_READABLE |ZX_FS_RIGHT_WRITABLE, 0755, "");
把channel发送给svc
这里有点奇怪,svc_channel_client_的另一头要等到sysmgr调用CreateNestedEnvironment才会被监听
dir->AddEntry("hub", root->hub_dir());
hub_.dir()
dir_
dir->AddEntry("svc", svc);
publish_vfs_.ServeDirectory(publish_dir_, zx::channel(args.pa_directory_request));
把从devmgr发来的通道挂到目录服务上
OpenVnode(flags, &vn)
(*vnode)->Open(flags, &redirect)
PseudoDir::Open()啥也不干
vn->Serve(this, fbl::move(channel), ZX_FS_RIGHT_ADMIN)
vfs->ServeConnection(fbl::make_unique<Connection>(vfs, fbl::WrapRefPtr(this), fbl::move(channel), flags));
connection->Serve();
wait_.set_object(channel_.get());
wait_.Begin(vfs_->async());
run_sysmgr()
fuchsia::sys::LaunchInfo launch_info;
LaunchInfo是fidl生成的, launcher.fidl
sysmgr.NewRequest() InterfacePtr<ComponentController>
Bind(std::move(h1), async)
impl_->controller.reader().Bind(std::move(channel), async);
wait_.object = channel_.get();
async_begin_wait(async_, &wait_)
ComponentController_Proxy缺省处理
返回另一头h2
root_realm.CreateComponent(std::move(launch_info),h2);
scheme = "file"
cb = lambda
loader_->LoadComponent(url, cb)
Loader_Proxy::LoadComponent()
把cb发送给root loader
RootLoader::LoadComponent(fidl::StringPtr url,
LoadComponentCallback callback)
CreateComponentWithProcess(
std::move(package), std::move(launch_info),
std::move(controller), std::move(ns));
builder.AddServices(std::move(svc));
PushDirectoryFromChannel("/svc", std::move(services));
这里设置了sysmgr的"/svc"指向appmgr的服务
flat namespace没有
channels = Util::BindDirectory(&launch_info);
launch_info->directory_request = std::move(exported_dir_server);
CreateProcess(job_for_child_, std::move(executable), url,
std::move(launch_info), zx::channel(), builder.Build());
fdio_spawn_vmo(job.get(), flags, data.vmo().release(), argv.data(),
nullptr, actions.size(), actions.data(),
process.reset_and_get_address(), err_msg);
zx_channel_create(0, &launcher, &launcher_request)
fdio_service_connect("/svc/fuchsia.process.Launcher", launcher_request);
fdio_ns_connect(fdio_root_ns, svcpath,
ZX_FS_RIGHT_READABLE | ZX_FS_RIGHT_WRITABLE, h);
ns_walk_locked(&vn, &path)
fdio_open_at(vn->remote, path, flags, h);
zxrio_connect(dir, h, ZXRIO_OPEN, flags, 0755, path);
建立和process launcher的通道
send_string_array(launcher, fuchsia_process_LauncherAddArgsOrdinal, argv);
send_handles(launcher, handle_capacity, flags, job, action_count, actions, err_msg);
send_namespace(launcher, name_count, name_len, flat, action_count, actions, err_msg);
zx_channel_call(launcher, 0, ZX_TIME_INFINITE, &args,
&actual_bytes, &actual_handles);
fdio_service_connect("/svc/.", h1.release())
fdio_ns_connect(fdio_root_ns, svcpath,
ZX_FS_RIGHT_READABLE | ZX_FS_RIGHT_WRITABLE, h);
ns_walk_locked(&vn, &path)
------------
收到从sysmgr来的rpc:
Namespace::CreateNestedEnvironment()
realm_->CreateNestedJob(std::move(host_directory), std::move(environment),
std::move(controller), label);
host_directory是sysmgr开过来的通道
controller = EnvironmentControllerImpl(
std::move(controller_request),
std::make_unique<Realm>(this, std::move(host_directory), label));
child = controller->realm();
这是新建的child realm
child->default_namespace_->services().ServeDirectory(
std::move(root_realm->svc_channel_server_));
让子realm来服务svc_channel_server_
前面PublishRootDir把devmgr发来的通道发给了svc_channel_client_, 所以这里child realm会
服务devmgr的请求
------------------------------------------------------
下面这些结构用来模拟unix fd io
typedef struct {
mtx_t lock;
mtx_t cwd_lock;
bool init;
mode_t umask;
fdio_t* root;
fdio_t* cwd;
fdio_t* fdtab[FDIO_MAX_FD];
fdio_ns_t* ns;
char cwd_path[PATH_MAX];
} fdio_state_t;
extern fdio_state_t __fdio_global_state;
#define fdio_lock (__fdio_global_state.lock)
#define fdio_root_handle (__fdio_global_state.root)
#define fdio_cwd_handle (__fdio_global_state.cwd)
#define fdio_cwd_lock (__fdio_global_state.cwd_lock)
#define fdio_cwd_path (__fdio_global_state.cwd_path)
#define fdio_fdtab (__fdio_global_state.fdtab)
#define fdio_root_init (__fdio_global_state.init)
#define fdio_root_ns (__fdio_global_state.ns)
typedef struct async_dispatcher async_t;
static const async_ops_t async_loop_ops = {
.version = ASYNC_OPS_V1,
.reserved = 0,
.v1 = {
.now = async_loop_now,
.begin_wait = async_loop_begin_wait,
.cancel_wait = async_loop_cancel_wait,
.post_task = async_loop_post_task,
.cancel_task = async_loop_cancel_task,
.queue_packet = async_loop_queue_packet,
.set_guest_bell_trap = async_loop_set_guest_bell_trap,
},
};