Presentation is loading. Please wait.

Presentation is loading. Please wait.

Bionic libc & ucore 沈彤 2008012108 张超 2008012100. Bionic libc 编译 前期:只下载 bionic libc 的源码 – 修改 bionic libc 使之能编译通过,东拼西凑,费 力不讨好 – 隐患:很多宏不知道是否应该定义,可能对代 码造成较大影响.

Similar presentations


Presentation on theme: "Bionic libc & ucore 沈彤 2008012108 张超 2008012100. Bionic libc 编译 前期:只下载 bionic libc 的源码 – 修改 bionic libc 使之能编译通过,东拼西凑,费 力不讨好 – 隐患:很多宏不知道是否应该定义,可能对代 码造成较大影响."— Presentation transcript:

1 Bionic libc & ucore 沈彤 2008012108 张超 2008012100

2 Bionic libc 编译 前期:只下载 bionic libc 的源码 – 修改 bionic libc 使之能编译通过,东拼西凑,费 力不讨好 – 隐患:很多宏不知道是否应该定义,可能对代 码造成较大影响 后期:使用 Android-x86 项目 – 无需再手动修改 bionic libc – Android-x86 项目已经实现了 Android 在部分 x86 机型上的运行,正确性把握较大

3 syscall 连接 将 ucore 中原有的 syscall 调用全部改为 int 0x81 ,将 bionic libc 使用的 syscall 调用设置为 int 0x80 好处:两套 syscall 机制不会互相干扰, ucore 原有的机制不会被破坏;同时 bionic libc 的 syscall 方便单独进行调试 坏处:有不少几乎完全相同的 syscall ,需要 重复写一次

4 syscall 实现 多数 syscall 可以直接利用 ucore 已有的 syscall 。 部分可以用 ucore 有,但没有用到过的函数, 比如利用 vfs_readlink() 完成 readlink() 系统调 用。 此外还有一些需要改变接口,如 brk, mmap 的参数、返回值不一样。 剩下的就是需要我们自己实现的,比如 signal 。

5 signal data struct sigset_t 信号集合 用 uint64_t 替代 uint32_t[2] sigpending, sigqueue 挂起队列 sigaction 信号处理函数 signal_struct 信号描述符 sighand_struct 信号处理描述符 sigframe 神奇的结构

6 signal syscalls kill() 和 tkill() 产生并发送信号 sigaction() 设置信号处理函数 sigprocmask() 设置或解除阻塞信号 sigpending() 获取挂起的阻塞信号 sigsuspend() 等待一些信号 sigaltstack() 设置信号处理函数栈地址

7 产生信号 一个进程 do_tkill() 得到进程描述符,关中断、获取 信号锁,调用 specific_send_sig_info() ,释放 锁、开中断。 specific_send_sig_info() 检查信号是否会被 忽略,检查信号是否是非实时的,调用 send_signal() 将信号加入进程的私有等待队 列中。对非阻塞信号,调用 signal_wakeup() 将进程唤醒。

8 产生信号 线程组 do_kill() 调用 group_send_sig_info() group_send_sig_info() 检查信号是否需要被 产生,调用 send_signal() 将其加入进程的共 享等待队列中。 handle_stop_signal() 实现信号的相互屏蔽。 group_complete_signal() 从线程组中选择一 个合适的进程,并用 signal_wakeup() 唤醒它。

9 默认的处理 中断结束时调用 do_signal() do_signal() 不断的调用 dequeue_signal() 获 取下一个信号。 对每个信号,如果是 SIGKILL 或 SIGSTOP 则直 接终止或停止该进程所在线程组,否则如 果处理方式是 SIG_IGN 则忽略 SIG_DFL 判断信号的类型,有些信号的默认 操作有忽略、停止线程组、终止线程组。

10 用户指定的处理函数 sigframe 保存 trapframe 阻塞信号 参数和返回地址 神奇的数字 movl $400, %eax; int $0x80 修改 eip esp sigreturn 系统调用 恢复

11 test1 产生信号给一个进程 测试 sigaction() sigprocmask() tkill() 信号处理函数的调用(包括在自定义信号 处理函数中使用系统调用) SIGKILL 终止进程

12 test2 产生信号给一个线程组 测试 sigsuspend() kill_bionic() SIGSTOP 停止线程组 SIGKILL 终止线程组

13 动态链接 —— 原理 内核态准备工作: – 通过可执行文件是否包含 PT_INTERP“ 段 ” ,判断 其为动态链接或静态链接 – 将可执行文件的 PT_LOAD 的 “ 段 ” 都载入内存 – 若为动态链接,可执行文件必包含 PT_INTERP“ 段 ” ,该 “ 段 ” 的内容为动态链接器的 路径。将动态链接器的 PT_LOAD“ 段 ” 都载入内存 – 动态链接器和可执行程序本身的装载地址就是 链接地址,无需重定位

14 动态链接 —— 原理 内核态准备工作: – 若为动态链接,将 eip 置为动态链接器的入口; 否则,将 eip 置为可执行文件的入口 – 设置初始堆栈。若为动态链接,堆栈中需要有 一些动态链接器需要的信息。 Android 的动态链 接器叫做 linker ,其源码中体现出只需要三项: AT_PHDR : program header 在内存中的地址 AT_PHNUM : program header 个数 AT_ENTRY :可执行文件的入口 – glibc 需要的更多此类信息

15 动态链接 —— 原理 用户态: – 若为动态链接,先执行的将是动态链接器。 – 动态链接器根据内核在堆栈中放置的辅助信息, 找到 PT_DYNAMIC“ 段 ” 。这个段中存放着动态链 接器需要的一切信息 – 例如,该段中类型为 DT_NEED 的项表示该可执 行程序依赖的动态链接库的名称在 strtab 段中的 序号,由此动态链接器可以得到需要加载的动 态链接库的名称

16 动态链接 —— 原理 用户态: – 动态链接库的链接地址一般从 0x0 开始,由动态 链接器选择可用地址作为基地址后加载。 – 加载完动态链接库之后,需要对动态链接库的 每一个重定位项(包括变量和函数)进行重定 位,具体机制可参见《程序员的自我修养 —— 链接、装载与库》

17 mmap file 动态链接器加载动态链接库是通过 mmap 文 件的方法,而 ucore 的 mmap 是在文件系统出 现以前就有的,从而没有 mmap 文件的功能 我们的做法:如果 mmap 传进了 fd 参数,就 在 mmap 的末尾把文件相应的部分直接读入 内存,并在 vma 中存储文件的相关信息;在 munmap 时把内存写回文件。

18 mmap file 失败的尝试 我们尝试如下实现 mmap 文件: – mmap 文件时,给相应 vma 加入文件信息( struct file 指针),不立即载入内存 – 发生缺页中断时,检查 vma 是否是 mmap 文件的 vma 。 如果是,将文件读取一页载入相应内存 更进一步地,实现共享文件的映射: – 在 struct file 中,加入被 mmap 的信息,包括:被 mmap 起始偏移、长度、起始物理内存地址 – 第一次缺页时,新申请一页空间,将文件内容载入 页中,并将 mmap 信息设置好 – 以后再缺页时,如果是同一块被 mmap 的区域,直 接将页表项改为已被 mmap 到的物理地址

19 mmap anonymous 另外,动态链接器还有 mmap 带有标志 MAP_ANONYMOUS 的行为 我们对它的理解:它用来预留一块虚存地 址空间,以后可以在这块预留空间上进一 步 mmap ,这是其他 mmap 不允许的 因此,给 vma 加上 ANONYMOUS 标志位。如 果碰到这样的情况,先分配 vma ;进一步分 配时,将这个 vma 分裂即可。

20 Dalvikvm 失败的尝试 第九周、第十周精力主要在尝试运行 dalvikvm 上 成功的在 Android 的 ARM 模拟器上运行 dalvikvm ,并跑出 Hello world 程序 未能在 x86 Linux 上运行成功。初期加载动 态链接库等阶段都已完成,是在 dalvikvm 开 始初始化的时候出错的。错误信息是无法 加载某个国际化语言模块。 Google 很久,无 果。

21 glibc 失败的尝试 一度 bionic libc 动态链接不能成功,尝试跑出 glibc 的动态链接(现在看来很荒谬)。 成功编译出 glibc ,在 Linux 上用编译出的 glibc 替 代本机的 glibc ,能够正常运行。 在 ucore 上始终提示 assert failed ,想修改 glibc 源码使之多输出一些调试信息(例如 __FILE__, __LINE__ ),竟然未能成功。 glibc 比 bionic libc 复杂得多需要更多的 syscall , 更多的动态链接信息,还有很多不太了解的编 译参数,最终作罢。


Download ppt "Bionic libc & ucore 沈彤 2008012108 张超 2008012100. Bionic libc 编译 前期:只下载 bionic libc 的源码 – 修改 bionic libc 使之能编译通过,东拼西凑,费 力不讨好 – 隐患:很多宏不知道是否应该定义,可能对代 码造成较大影响."

Similar presentations


Ads by Google