在shell中执行一条可执行程序(./a.out) 系统执行的过程

目录

系统调度过程

用户空间角度:

内核角度

1、调用fork创建一个新进程

2、使用_fo_fork创建新进程

3、父进程调用wake_up_new_task尝试唤醒新进程

4、CPU选择一个合适的进程来运行;

5、运行新进程

6、实现负载均衡


扫描二维码关注公众号,回复: 14650752 查看本文章

系统调度过程

分析在命令行下使用./test程序。程序在用户态和内核台中运行的流程

用户空间角度:

shell 运行test程序,调用fork()系统调用函数来创建一个新进程;

调用exec系统调用函数来装载test程序。

ret = fork()
if(ret > 0)
{
    //父进程
}
else if(ret == 0)//子进程
{
    execve()
}
else
{
    //失败
}

内核角度

do_fork ->新进程

1、调用fork创建一个新进程

2、使用_fo_fork创建新进程

  • 创建新进程的task_struct数据结构
  • 复制父进程的task_struct数据结构到新进程
  • 复制父进程相关的页表项到新进程
  • 设置新进程的内核栈

3、父进程调用wake_up_new_task尝试唤醒新进程

  • 调用调度类select_task_rq(),为新进程寻找一个负载最轻的CPU(如果CPU0有四个线程在运行,CPU有一个线程在运行,那么新进程在寻址负载最轻的CPU为CPU1)
  • 调用调度类的enqueue_task(),把新进程添加到CPU1的就绪队列里

4、CPU选择一个合适的进程来运行;

  • 每次时钟节拍到来时,scheduler_tick()检查是否需要重新调度;check_preempt_tick会做检查,当需要重新调度时会设置当前进程的thread_info中的TIF_NEED_RESCHED标志位。
  • 在中断返回前会检查当前进程是否需要调度。如需要调度,调用preempt_schedule_irq来切换进程运行。
  • 调度器的schedule函数会调用调度类的pick_next_task来选择下一个最合适的进程
  • switch_mm切换父进程和新进程的页表
  • switch_to切换进程来运行 

5、运行新进程

  • 新进程第一次调用时会调用ret_from_fork函数
  • 返回用户空间运行shell程序
  • shell程序调用exec来运行test程序,最终新进程编程test进程

6、实现负载均衡

  • 在每个时钟节拍到来,检查是否需要触发软中断来实现SMP负载均衡,调用函数为scheduler_tick->trigger_load_balabce()。下一次实现负载均衡的时间点存放在就绪队列的next_balance成员里。
  • 触发 SCHED_SOFTIRQ软中断
  • 在软中断函数run_rebalance_domains里,从当前CPU开始遍历CPU拓扑关系,寻找负载不均匀的调度组;
  • 找到调度组最繁忙的,然后计算迁移多少到CPU1上才能保持两个调度组负载平衡;
  • 从CPU0迁移部分进程到CPU1 

参考

https://course.0voice.com/v1/course/intro?courseId=2&agentId=0 

猜你喜欢

转载自blog.csdn.net/WANGYONGZIXUE/article/details/129228481
今日推荐