分析 Linux 内核创建一个新进程的过程

张晓攀+原创作品转载请注明出处+《Linux内核分析》MOOC课程https://mooc.study.163.com/course/1000029000

实验六——分析Linux内核创建一个新进程的过程

一、实验过程

1.将github上的menu项目克隆下来

git clone https://github.com/mengning/menu.git

2.进入内核系统

更新test.c :mv test_fork.c test.c

运行脚本,自动编译和自动生成根文件系统,同时启动,输入fork命令:make rootfs

3.gdb调试

  • 关闭QEMU窗口,在命令行中输入命令:qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S

  • 另开一个shell窗口,依次输入指令进入调试:gdbfile linux-3.18.6/vmlinuxtarget remote:1234

  • 设置断点

二、实验总结

在Linux内核中,创建一个新进程主要依赖于fork()clone()等系统调用,最终由内核中的do_fork()函数完成。简要流程如下:

1. 用户态的系统调用

  • 用户进程调用fork()vfork()clone()等接口。
  • 这些接口会触发进入内核态,通过系统调用号定位到相应的内核函数,例如sys_clone

2. 进入do_fork()

  • do_fork()是创建新进程的核心内核函数,它接收用户态的参数并进行处理。
  • 主要完成以下任务:
    1. 检查参数:确保clone_flags等参数有效。
    2. 分配task_struct:为新进程分配内存,并初始化其任务描述符task_struct,其中包含进程的关键信息,如PID、优先级、调度策略等。
    3. 复制父进程资源
      • 虚拟内存:使用copy_mm()复制父进程的内存描述符。
      • 文件描述符:通过copy_files()复制文件描述符表。
      • 信号处理:通过copy_sighand()复制信号处理机制。
  • 根据clone_flags决定是否与父进程共享某些资源(如地址空间、文件描述符表等)。

3. 分配PID

  • 内核通过alloc_pid()函数为新进程分配一个唯一的进程标识符(PID)。

4. 设置调度信息

  • 调用wake_up_new_task(),将新进程加入可运行队列,并设置其初始状态为TASK_RUNNINGTASK_INTERRUPTIBLE

5. 返回到用户态

  • 新进程的task_struct初始化完毕后,父子进程分别返回到用户态。
  • 对于父进程,fork()返回新进程的PID;对于子进程,fork()返回0。

6. 执行新任务

  • 如果新进程需要执行不同的程序,可以调用execve()加载新程序。
  • 如果是vfork()或某些clone()调用,父进程可能会等待子进程执行完成后才继续运行。
posted @ 2024-11-09 18:25  zzzxp13  阅读(56)  评论(0)    收藏  举报