2021 |
您所在的位置:网站首页 › zzx连接器 › 2021 |
分析 Linux 内核创建一个新进程的过程
一、阅读理解 task_struct 数据结构1、进程描述符2、进程状态
二、使用 gdb 跟踪分析一个 fork 系统调用内核处理函数 sys_clone1、MenuOS中添加fork并测试2、跟踪调试
三、分析 fork 函数对应的系统调用处理过程四、Linux内核编译过程中遇到的问题1、添加自定义系统调用2、make bzImage出错3、开机时不能进入4、总结
一、阅读理解 task_struct 数据结构
1、进程描述符
task_struct具有非常庞大的数据结构,400多行代码。包括对进程链表的管理,控制台,文件系统描述,文件描述符,内存管理描述,信号描述等,其结构示意图如下图所示: 当使用fork()创建一个新的进程时,进程的状态是TASK_RUNNING(就绪态),新进程被调度运行时,就切换到TASK_RUNNING(运行态)。对于一个正在运行的进程,调用用户库函数exit()会陷入内核执行该内核函数do_exit(),也就是终止进程,就会进入TASK_ZOMBIE状态(僵尸进程)。一个正在运行的进程在等待特定的事件和资源时会进入阻塞态。阻塞态也分两种:TASK_INTERRUPTIBLE和TASK_UNINTERRUPTLBLE。TASK_INTERRUPTIBLE可以被信号和wake_up唤醒的,当信号到来时,进程会被设置为TASK_RUNNING(就绪态),而TASK_UNINTERRUPTLBLE只能被wake-up()唤醒。进程状态转化图如下图所示: 如下图所示,以下为MenuOS运行fork的效果,可以看到父进程和子进程都有信息输出: 按照之前的方法对内核进行调试,分别在sys_clone,do_fork,dup_task_struct,copy_process,copy_thread,ret_from_fork这几处设置断点,如下图所示: Linux内核编译时,虚拟机的Linux内核版本为5.0.0-23-generic,下载的Linux内核版本为5.14.16。 1、添加自定义系统调用问题: arch/x86/entry/syscall_64.o:(.rodata+0xa78):对‘__x64_sys_zzx’未定义的引用 问题原因: 添加系统调用时出错 解决方案: 三处修改方式分别如下: 问题: make bzImage过程中出现如下错误: Killed Makefile:1183: recipe for target ‘vmlinux’ failed 问题原因: 在编译过程中,交换分区不够 解决方案: 可以通过扩大交换分区swap解决,可参考 https://blog.csdn.net/ssrmygod/article/details/70157716 3、开机时不能进入问题: 开机重复显示以下内容,无法启动: [ OK ] Started User Manager for UID 121... Stopping User Manager for UID 121...问题原因: 进行内核编译时把/dev/sda1主分区占满,导致空间不够 解决方案: 无法开机时对/dev/sda1进行扩容,可参考 https://blog.csdn.net/huanghai381/article/details/50033775 4、总结Linux内核编译过程中还出现了一些其他的小问题,但是因为还没有养成记录错误的习惯,也就没能记录下来供其他人参阅。总之,Linux内核编译本身不难,但是细节很多,耗时也很长,追求做完作业本身并没有很大的价值,真正的意义在于如何解决问题,以后遇到困难时是否还能够坚持下去。 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |