在做Exercise
5.9中的open函数时,虽然根据注释是可以写出来代码,但是对其中原理很不理解。
open函数中,首先用fd_alloc
分配一个新的Fd。
然后fsipc_open
函数就不太理解了。1、传入的path和mode强制转换为虚拟地址是什么原理?fsipc_open中的参数path和mode最后是要存放到req中,然后调用fsipc(FSREQ_OPEN, req, fd, &perm);
而fsipc这个函数又用了ipc_send
,在ipc_send中req又做为srcva传入syscall_ipc_try_send(whom, val, srcva, perm)
中。综上,经过一番转换,path和mode存入一段空间后被作为一个虚拟地址传到了lab4完成的sys_ipc_try_send
中。想问一下这是什么原理?把const
char *path和u_int
omode放入结构体强制转换为虚拟地址就能正确使用这个地址了?
2、在fsipc函数中调用的ipc_send(envs[1].env_id, type, fsreq, PTE_D);
这里的envs[1].env_id
是一个常量,envs[1]是指导书中提到的文件系统进程吗?
3、fsipc函数中先调用ipc_send(envs[1].env_id, type, fsreq, PTE_D);
,然后return ipc_recv(……)
。我记得如果不先对envs[1]的env_ipc_recving进行设置,会返回-E_IPC_NOT_RECV。所以这里是不是应该先用sys_ipc_recv设置一下envs[1]的env_ipc_recving?
最后修改于:
最后回复于:
回复主题帖
fsipc_open
(user/lib/fsipc.c
)函数定义如下:
1 | int fsipc_open(const char *path, u_int omode, struct Fd *fd) { |
该函数将预先定义好的fsipcbuf
(user/lib/fsipc.c
)转化为需要使用的struct Fsreq_open
(user/include/fsipc.h
)便于存放数据。
fsipcbuf定义如下:
1 u_char fsipcbuf[PAGE_SIZE] __attribute__((aligned(PAGE_SIZE)));注:任何包含了该源文件的用户程序都会在bss段中定义fsipcbuf,长度为一页大小,attribute属性规定其地址与页大小对齐,便于后续使用。
然后,将path
参数使用strcpy
拷贝到req
结构体中的req_path
成员变量中。将mode
的值赋值给req
结构体的req_mode
成员变量。
1 | struct Fsreq_open { |
fsreqbuf
自此存放了需要使用的数据,对于ipc_send
,其srcva
若不为0,则表示需要从源进程共享一页空间给目标空间。
这里的共享指的是将进程地址空间中对应srcva的那一页物理页框同样映射到到目标空间的对应页表中,映射到的虚拟地址由
ipc_recv
决定。具体内容参考kern/syscall_all.c
中的sys_ipc_try_send
对于srcva
的处理。
这样目标进程就能够通过ipc_recv
传递的dstva
使用源进程传入的Fsreq_open
结构体。
- 是的。
- 请参考
fs/serv.c
中serv
函数的实现,fs进程通过该函数实现其逻辑业务,该函数会一直使用ipc_recv
等待请求并处理,所以不需要再对env[1]
进行额外的处理。
最后修改于:2024-05-19 12:56:30
我应该明白了。fsipc_open
函数中req是一个结构体指针,这个指针是虚拟地址,而且对应着某一个物理页框,req指向的这个结构体就存放在这个物理页框中。
我们将想要传递的数据写入这个结构体(也就是写入这个物理页框)后,把req作为srcva传给ipc_send,之后再通过这个srcva这个虚拟地址找到其对应的物理页框(也就是找到了其中存放那个结构体),然后完成映射后,就可以让目标进程也读取到这个结构体的内容,从而实现共享。
最后修改于:2024-05-19 13:20:43