免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 4357 | 回复: 15
打印 上一主题 下一主题

[CPU及多核] 中断返回与调度救助 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2015-01-06 11:46 |只看该作者 |倒序浏览
各位大神有没有搞汇编或懂底层的高人。有个问题困扰了蛮久
如能回答不胜感激

中断返回与进程调度的区别是什么?
我这里主要指的是smp环境下的状态恢复

比如中断打断当前运行的环境包括两种
1.当前运行在进程上下文
2.当前运行在软中断上下文
中断处理的一般步骤为:保存cpu寄存器 和 堆栈等--->切换到中断处理--->中断处理完成--->恢复cpu环境
那么这个恢复cpu环境的过程,有没有可能发生cpu的切换。又是如何控制的?
比如软中断一般的理解是“谁触发,谁执行”,就是说软中断执行过程中不会跨cpu。而开启smp的同个进程,却又是可以跨cpu的。
那么针对软中断 和 进程 被中断后的恢复,是否可能发生cpu的切换?


还有针对以上问题。调度又是如何处理的。现在一般都是 抢占式内核
那么如果进程a 被进程b给打断,也是  保存cpu寄存器 和 堆栈等--->切换到进程b--->进程b完成,重新调度--->恢复cpu环境
这种流程吗。应该不对吧。感觉很奇怪


还有中说法是,系统堆栈是 per cpu结构。所以从这个理解,中断返回后,中断前的环境肯定只能恢复到原来的cpu上
而这种说法同时认为 cpu的负载均衡,是通过调度器拉实现的。那么这种拉 指的是per cpu变量的copy 和 删除吗?

论坛徽章:
15
射手座
日期:2014-02-26 13:45:082015年迎新春徽章
日期:2015-03-04 09:54:452015年辞旧岁徽章
日期:2015-03-03 16:54:15羊年新春福章
日期:2015-02-26 08:47:552015年亚洲杯之卡塔尔
日期:2015-02-03 08:33:45射手座
日期:2014-12-31 08:36:51水瓶座
日期:2014-06-04 08:33:52天蝎座
日期:2014-05-14 14:30:41天秤座
日期:2014-04-21 08:37:08处女座
日期:2014-04-18 16:57:05戌狗
日期:2014-04-04 12:21:33技术图书徽章
日期:2014-03-25 09:00:29
2 [报告]
发表于 2015-01-06 14:15 |只看该作者
看似有点乱,呵呵~

中断返回是进程调度的一个时机点,这两者并非并列的概念。进程调度通常发生在:
1、中断、异常、系统调用返回处。
2、wakeup和手工调用schedule的地方
其中中断返回时,进行系统调度,是进程调度发生最频繁的地方,因为调度主要依赖于时钟中断(一般来说哈)。具体的代码可以看看entry_xx.S汇编代码。

"中断处理的一般步骤为:保存cpu寄存器 和 堆栈等--->切换到中断处理--->中断处理完成--->恢复cpu环境
那么这个恢复cpu环境的过程,有没有可能发生cpu的切换。又是如何控制的?"
--- 这个应该是不会发生CPU切换的,也就是说中断处理过程中不会切换CPU(准确的说应该是迁移)。

”比如软中断一般的理解是“谁触发,谁执行”,就是说软中断执行过程中不会跨cpu。而开启smp的同个进程,却又是可以跨cpu的。
那么针对软中断 和 进程 被中断后的恢复,是否可能发生cpu的切换?“
--- 首先软中断确实是“谁触发,谁执行”,所以软中断通常不会发生CPU迁移;进程在被中断后,在中断返回时,有一个调度的时机点,如果此时没发生调度,则返回原进程上下文执行,此时应该也不会迁移CPU;如果此时发生调度,则调度其它进程到当前CPU运行,则原来的进程暂停运行,此时通常也不会迁移到其它CPU,除非有特殊的情况(如:cpu负载均衡将其拉倒其它CPU)。

”还有针对以上问题。调度又是如何处理的。现在一般都是 抢占式内核
那么如果进程a 被进程b给打断,也是  保存cpu寄存器 和 堆栈等--->切换到进程b--->进程b完成,重新调度--->恢复cpu环境
这种流程吗。应该不对吧。感觉很奇怪“
--- 刚才说的中断返回只是调度的一个时机点,不是并行的概念。抢占式内核比普通内核来说,只能调度的时机点更多,但主要还是要依赖中断返回,所以这里”进程a 被进程b给打断“说法不对,b进程不能直接打断a进程,能打断a进程的只能是中断或异常等情况,然后待中断/异常返回时,进行调度,调度时检查是否开启了抢占,如果开启,则能在内核态发生调度。

”还有中说法是,系统堆栈是 per cpu结构。所以从这个理解,中断返回后,中断前的环境肯定只能恢复到原来的cpu上
而这种说法同时认为 cpu的负载均衡,是通过调度器拉实现的。那么这种拉 指的是per cpu变量的copy 和 删除吗?“
--- 这里的”系统堆栈“说法也不准确,应该是说的中断栈吧?中断栈的确是per cpu的,但内核栈和用户栈是per task的,因为Linux中对中断进行了串行话处理,所以中断通常不会嵌套,所以per cpu的中断栈应该不会有问题。中断返回后会切换到进程的内核栈,而内核栈是per task的,上下文也是独立的,所以被中断的进程理论上是可以被拉到其它CPU上运行的(通常不会)。

请参考:
http://blog.chinaunix.net/uid-14528823-id-4739291.html
http://blog.chinaunix.net/uid-14528823-id-4740294.html


论坛徽章:
0
3 [报告]
发表于 2015-01-06 19:53 |只看该作者
回复 2# humjb_1983
多谢83兄的指导。说的很明白。尤其是per task栈的概念,以前完全没这个概念。所以总是感觉明白了,深浅想却又糊涂

看你两篇大作应该是刚发出来的。还未审核通过。稍后一定拜读

还有个问题不太明白。你也说了per task栈重新调度后。一般还是保持在原来的cpu上运行
这个很容易理解 可能是为了cache击中考虑
但是既然非 per cpu结构,如何还能保证调度后还在原来的cpu上执行,这个很难理解

当然还有种说法 是 所有的栈都是per cpu的,所以负载均衡导致的切换,代价会很大。但至于如何切换倒是不慎明了
   

论坛徽章:
15
射手座
日期:2014-02-26 13:45:082015年迎新春徽章
日期:2015-03-04 09:54:452015年辞旧岁徽章
日期:2015-03-03 16:54:15羊年新春福章
日期:2015-02-26 08:47:552015年亚洲杯之卡塔尔
日期:2015-02-03 08:33:45射手座
日期:2014-12-31 08:36:51水瓶座
日期:2014-06-04 08:33:52天蝎座
日期:2014-05-14 14:30:41天秤座
日期:2014-04-21 08:37:08处女座
日期:2014-04-18 16:57:05戌狗
日期:2014-04-04 12:21:33技术图书徽章
日期:2014-03-25 09:00:29
4 [报告]
发表于 2015-01-07 08:46 |只看该作者
anyhit 发表于 2015-01-06 19:53
回复 2# humjb_1983
多谢83兄的指导。说的很明白。尤其是per task栈的概念,以前完全没这个概念。所以总是 ...

每个CPU的调度是相对独立运转的,每个cpu都有自己的调度队列,当某task在某CPU上运行后,该task就位于该CPU相应的调度队列中了,在没有特别情况时(如需要负载均衡),该task应该一直在该CPU上运行的。

论坛徽章:
0
5 [报告]
发表于 2015-02-03 17:18 |只看该作者


中断 和软中断,都是中断,没有进程上下文,不能发生调度
你可能跟ksoftirqd这个进程搞混了,他只是一个进程访问了
全局的 softirq那个数组变量

ksoftirqd这个进程里面做了好多限制(就是你乱想的那些)
1》这个进程不会被抢占,除非自己声明可以被抢占(看代码是他没有真正调用do_softirq的时候)
2》他也不会被调度,除非自己让出CPU(调用schedule 看代码)
3》他可以被中断,但是中断之后,他直接是进不了do_softirq函数的(do_softirq做了检测),反回之后,被中断的ksoftirqd进程 GO ON

1 2 要时不时让出CPU,因为他要一直执行下去(因有中断可以打断),其它进程没法执行了

论坛徽章:
0
6 [报告]
发表于 2015-02-03 17:19 |只看该作者
本帖最后由 wzw200 于 2015-02-03 17:19 编辑

blog.csdn.net/dianhuiren/article/details/7294408

http://

我没有权限发URL,我这样发吧

论坛徽章:
0
7 [报告]
发表于 2015-02-03 18:42 |只看该作者
回复 5# wzw200
你说的我是明白的。irq_exit 中调用do_softirq 时 会判断in_interrupt 。若之前为软中断环境,in_interrupt 通不过就返回了

ksoftirqd的复杂实现 只是为了保证两点 1.软中断不可被进程打断的特性 2. 中断谁触发谁执行的特性(通过绑定cpu实现)

humjb_1983 兄说的是对的。我是没搞清楚 “中断栈,用户栈” 这些概念

也就是中断返回后。如何保证原先执行的软中断 还在本来执行的cpu上执行。也就是说我对中断“谁触发谁执行”的特性产生了疑问

而进程 被中断后返回 ,跨cpu又是如何实现的。因为一般认为进程跨cpu调度,发生在中断返回后

humjb_1983 兄说的中断栈 是per cpu  而用户栈 是 per task,可以解释这些情况。但因为汇编较差,其实更深层次我还是未搞明白





   

论坛徽章:
0
8 [报告]
发表于 2015-02-03 18:50 |只看该作者
回复 6# wzw200
而你另外一个帖子。我还以为你也是对中断“谁触发,谁执行”等产生了疑问
因为软中断变量是 per cpu的32位数,所以一旦 软中断执行过程中跨cpu,就会发生冲突

可能是我理解错了你的问题

论坛徽章:
0
9 [报告]
发表于 2015-02-03 18:54 |只看该作者
回复 5# wzw200

没有真正调用 do_softirq 不知道你的意思是什么?

以下为我之前看的ksoftirqd执行函数,部分注释是自己写的,不知道是否正确


/*软中断维护内核线程
每个处理器都有一个这样的线程,命名为ksoftirqd/n*/
static int ksoftirqd(void * __bind_cpu)
{
    set_user_nice(current, 19);
    current->flags |= PF_NOFREEZE;
    set_current_state(TASK_INTERRUPTIBLE);
    while (!kthread_should_stop()) {
        preempt_disable(); //禁止抢占
        if (!local_softirq_pending()) {
            preempt_enable_no_resched();
            schedule();//调度其他进程执行
            preempt_disable();
        }
        __set_current_state(TASK_RUNNING);//do_softirq中便不会重新**ksoftirqd(wakeup_softirqd会判断当前状态)
        while (local_softirq_pending()) {      
              /*禁止抢占会停止让CPU下线,如果已经下线,那么就
              正在一个错误的CPU上,那么就不要执行
               goto wait_to_die
            */
            /* Preempt disable stops cpu going offline.
               If already offline, we'll be on wrong CPU:
               don't process */
            if (cpu_is_offline((long)__bind_cpu))
                goto wait_to_die;
            do_softirq();    // 执行软中断
            preempt_enable_no_resched();// 可以抢占
            cond_resched();   // 确保对当前进程设置了TIE_NEED_RESCHED . 因为所有这些函数执行时都启用了硬件中断
            preempt_disable();//禁止抢占
        }
        preempt_enable();
        set_current_state(TASK_INTERRUPTIBLE);
    }
    __set_current_state(TASK_RUNNING);
    return 0;
wait_to_die:
    preempt_enable();
    /* Wait for kthread_stop  等待kthread_stop停止 */
    set_current_state(TASK_INTERRUPTIBLE);//可抢占
    while (!kthread_should_stop()) {
        schedule();//显示调度
        set_current_state(TASK_INTERRUPTIBLE);
    }
    __set_current_state(TASK_RUNNING);
    return 0;
}


   

论坛徽章:
0
10 [报告]
发表于 2015-02-03 20:33 |只看该作者
本帖最后由 wzw200 于 2015-02-03 21:04 编辑

  也就是中断返回后。如何保证原先执行的软中断 还在本来执行的cpu上执行。也就是说我对中断“谁触发谁执行”的特性产生了疑问

我先回这个问题,不知道我说的对不对,
do_softirq 这个函数是所有CPU都可以调用的
你再向下跟代码就会发现tasklet_hi_action之类的函数里面都用了每CPU变量
用tasklet_schedule函数都加到每CPU变量里面

中断返回后,别的CPU也只是执行自己 每CPU变量的 BH,多CPU的就不是一个变量,你想想,会冲突吗,
不知道你明白了没有

open_softirq(NET_TX_SOFTIRQ, net_tx_action);
open_softirq(NET_RX_SOFTIRQ, net_rx_action);
open_softirq(HRTIMER_SOFTIRQ, run_hrtimer_softirq);
open_softirq(int nr, void (*action)(struct softirq_action *))
open_softirq(TASKLET_SOFTIRQ, tasklet_action);
open_softirq(HI_SOFTIRQ, tasklet_hi_action);
open_softirq(TIMER_SOFTIRQ, run_timer_softirq);

深入Linux设备驱动程序内核机制.pdf 这本书的
第6章  tasklet,你看明白了,就知道了
http://
www.
cnblogs.com/hustcat/archive/2009/08/15/1546601.html
YY哥的中断三编,你可以看看

因为软中断变量是 per cpu的32位数 这个不是每CPU变量
softirq_vec 不是每CPU变量
raise_softirq_irqoff-》__raise_softirq_irqoff(nr)-》or_softirq_pending-再向下跟,pending是每CPU变量
tasklet_hi_action的链表是每CPU变量

do_softirq
{
     查看自己的每CPU变量pending
     tasklet_hi_action
           开始用每CPU变量
}
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP