20169217 《Linux内核原理与分析》 第八周作业
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了20169217 《Linux内核原理与分析》 第八周作业,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含4120字,纯文字阅读大概需要6分钟。
内容图文
![20169217 《Linux内核原理与分析》 第八周作业](/upload/InfoBanner/zyjiaocheng/1164/0d887f6ffb6d49e8af809fcc17ef8624.jpg)
此次作业仍然分为两个部分,第一部分为实验。
实验要求:
1. 阅读理解task_struct数据结构。
2. 分析fork函数对应的内核处理过程sys_clone,理解创建一个新进程如何创建和修改task_struct数据结构。
3.使用gdb跟踪分析一个fork系统调用内核处理函数sys_clone ,验证对Linux系统创建一个新进程的理解。
实验内容:
1.理解task_struct数据结构。
操作系统内核里面有操作系统所谓的三大功能,就是进程管理,内存管理和文件系统。但这里面最核心的就是进程管理,也就是 在linux里面我们有一个数据结构task_struct。为了管理进程,内核要描述进程的这个东西,我们也称它为进程描述符。它提供了进程所需要了解的信息。
进程状态变化图为:
我们来分析一下进程的变化,操作系统中的进程状态有就绪态、运行态、阻塞态三大状态,实际的,内核管理的进程状态是不一样的。我们来看一下为什么不一样,你看我们在linux进程状态的转换图,我们使用fork来创建一个新进程的时候,实际它的状态是就绪,但是没有在运行。当调度器选择到新创建的进程的时候它就切换到运行态,也是TASK_RUNNING。两个状态都是相同的,也就是说,当进程是TASK_RUNNING状态的时候,它是可运行的,有没有在运行呢,这个取决于它有没有获得CPU的控制权。也就是说这个进程有没有在CPU上实际的执行。如果在CPU上实际的执行就是运行态,如果被调度出去了,在那等待着就是就绪态。所以这个和在操作系统原理中有点不一样。一个正在运行的进程,我们调用do_exit,也就是终止,就会进入TASK_ZOMBIE,也就是进程的终止状态,那么系统会把进程给处理掉。这是就绪态和运行态。我们看一个正在运行的进程,它在等待特定的事件或资源的时候就会进入阻塞态。
2.分析fork函数对应的内核处理过程sys_clone,理解创建一个新进程如何创建和修改task_struct数据结构。
fork、vfork和clone三个系统调用都可以创建一个新进程,而且都是通过调用do_fork来实现进程的创建,函数在/linux-3.18.6/kernel/fork.c中,代码如下:
1623long do_fork(unsigned long clone_flags, 1624 unsigned long stack_start, 1625 unsigned long stack_size, 1626int __user *parent_tidptr, 1627int __user *child_tidptr) 1628{ 1629struct task_struct *p; 1630int trace = 0; 1631long nr; 16321633/* 1634 * Determine whether and which event to report to ptracer. When 1635 * called from kernel_thread or CLONE_UNTRACED is explicitly 1636 * requested, no event is reported; otherwise, report if the event 1637 * for the type of forking is enabled. 1638 */1639if (!(clone_flags & CLONE_UNTRACED)) { 1640if (clone_flags & CLONE_VFORK) 1641 trace = PTRACE_EVENT_VFORK; 1642elseif ((clone_flags & CSIGNAL) != SIGCHLD) 1643 trace = PTRACE_EVENT_CLONE; 1644else1645 trace = PTRACE_EVENT_FORK; 16461647if (likely(!ptrace_event_enabled(current, trace))) 1648 trace = 0; 1649 } 16501651 p = copy_process(clone_flags, stack_start, stack_size, 1652 child_tidptr, NULL, trace); 1653/* 1654 * Do this prior waking up the new thread - the thread pointer 1655 * might get invalid after that point, if the thread exits quickly. 1656 */1657if (!IS_ERR(p)) { 1658struct completion vfork; 1659struct pid *pid; 16601661 trace_sched_process_fork(current, p); 16621663 pid = get_task_pid(p, PIDTYPE_PID); 1664 nr = pid_vnr(pid); 16651666if (clone_flags & CLONE_PARENT_SETTID) 1667 put_user(nr, parent_tidptr); 16681669if (clone_flags & CLONE_VFORK) { 1670 p->vfork_done = &vfork; 1671 init_completion(&vfork); 1672 get_task_struct(p); 1673 } 16741675 wake_up_new_task(p); 16761677/* forking complete and child started to run, tell ptracer */1678if (unlikely(trace)) 1679 ptrace_event_pid(trace, pid); 16801681if (clone_flags & CLONE_VFORK) { 1682if (!wait_for_vfork_done(p, &vfork)) 1683 ptrace_event_pid(PTRACE_EVENT_VFORK_DONE, pid); 1684 } 16851686 put_pid(pid); 1687 } else { 1688 nr = PTR_ERR(p); 1689 } 1690return nr; 1691}
先定义一个task_sturct结构指针,再用copy_process函数复制一个进程,故真正的复制过程在copy_process函数中,该函数主要执行内容为:
struct task_struct *p; retval = security_task_create(clone_flags); p = dup_task_struct(current); retval = sched_fork(clone_flags, p);
retval = copy_files(clone_flags, p); retval = copy_fs(clone_flags, p);
retval = copy_sighand(clone_flags, p); retval = copy_signal(clone_flags, p);
retval = copy_mm(clone_flags, p); retval = copy_io(clone_flags, p);
retval = copy_thread(clone_flags, stack_start, stack_size, p);
linux-3.18.6/arch/x86/kernel/process_32.c的copy_thread函数中
p->thread.sp = (unsigned long) childregs; p->thread.ip = (unsigned long) ret_from_fork; childregs->ax = 0; //fork子进程返回为0
决定了子进程从系统调用中返回后的执行.ret_from_fork决定了新进程的第一条指令地址。p->thread.ip = (unsigned long) ret_from_fork;将子进程的ip设置为ret_from_fork的首地址,子进程从ret_from_fork开始执行
三、使用gdb跟踪分析一个fork系统调用内核处理函数sys_clone ,验证您对Linux系统创建一个新进程的理解
rm menu -rf git clone https://github.com/mengning/menu.git cd menu mv test_fork.c test.c make rootfs qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S gdb file linux-3.18.6/vmlinux 加载调试用的符号表 target remote:1234
设置断点:
b sys_clone
b do_fork
b dup_task_struct
b copy_process
b copy_thread
b ret_from_fork
原文:http://www.cnblogs.com/dkyliuhongyi/p/6039353.html
内容总结
以上是互联网集市为您收集整理的20169217 《Linux内核原理与分析》 第八周作业全部内容,希望文章能够帮你解决20169217 《Linux内核原理与分析》 第八周作业所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。