need_sched 一些讨论

news/2024/7/5 5:11:13
我想写一个简单的设备驱动, 但对驱动模块的可重入方面不甚了解.
有的书说驱动模块不会被中断, 除非主动地调用schedule()(或是隐式
地调用, 如vmalloc()); 有的书则说即使schedule()被调用, 它也不会
去作进程切换, 因为schedule()不对内核态进程切换.

不知谁对? 望高人指点一二. 谢谢


[Original ] [Print] [Top]

Subject : Re: 设备驱动的可重入问题
Author : jkl    Posted : 2000-11-29 11:55    Length : 327 byte(s)
[Original ] [Print] [Top]
可 以认为内核态的代码是一种协作式的多线程机制,只有当前线程主动的放弃执行才能引导到新的线程.或者说,当内核有代码不能立即返回到用户代码时,它必须运 行调度过程,将自身挂起,释放对CPU的控制权,当这段线程被唤醒后,代码又从调度过程中返回,它又重新获得CPU控制权,它完成用户指定操作后就可以立 即返回到用户代码中去了.


[Original ] [Print] [Top]

Subject : Re: 设备驱动的可重入问题
Author : pengchengzou    Posted : 2000-11-29 17:40    Length : 178 byte(s)
[Original ] [Print] [Top]
非常感谢JKL的指点. 得寸进尺, 追加一个问题. 如果内核模块不主动放弃CPU,
时钟中断程序是否还会被调用. 是否可以认为在内核模块中中断是被屏蔽调的?


[Original ] [Print] [Top]

Subject : Re: 设备驱动的可重入问题
Author : difeijing    Posted : 2000-11-29 18:47    Length : 83 byte(s)
[Original ] [Print] [Top]
普通情况下,时钟中断仍然会被调用,除非你
显式的关中断.

[Original ] [Print] [Top]

Subject : Re: 设备驱动的可重入问题
Author : jkl    Posted : 2000-11-29 20:33    Length : 325 byte(s)
[Original ] [Print] [Top]
在 执行操作系统调用时,是不关CPU中断的,时钟中断永远按精确的节拍发生,不管当前CPU是在用户态还是核心态.硬件中断发生时,内核要屏蔽该中断源,当 中断返回时再打开这一号中断,因此同一中断是不会重入的.用户态的硬件中断返回之前要运行调度过程,核心态中断返回时则不运行调度过程,这就是内核过程为 什么不会被抢占的原因.


[Original ] [Print] [Top]

Subject : Re: 设备驱动的可重入问题
Author : pengchengzou    Posted : 2000-11-30 09:17    Length : 863 byte(s)
[Original ] [Print] [Top]
谢谢两位的回答. 得尺进丈一下.

我的理解是, 时钟中断处理函数(do_timer())没有进行实质性的中断服务,
只是设置TIMER_BH, 在Timer Bottom Half 被运行时再作真正的服务.
而Timer Bottom Half 被调用只在这三个时机:

* schedule()
* 系统调用返回
* slow 中断服务返回

我的问题是, 如果系统上运行了两个计算量很大的程序. 它们没有调用任何
系统调用, 那么谁会调用schedule()呢. 是不是一个程序一旦获得CPU, 只要
他不主动放弃 (不调用任何系统调用), 他便不会被调度出去.

我一直以为时钟中断处理函数会作调度工作, 但是看了书和源代码后, 发现
恰恰相反, 是schedule()激活在Timer Bottom Half. 如果真是如此,
Linux的抢占式体现在哪里呢?

我觉得我是哪儿搞错了,很是迷惑. 请大家指点.

多谢.


[Original ] [Print] [Top]

Subject : Re: 设备驱动的可重入问题
Author : jkl    Posted : 2000-11-30 11:08    Length : 3,927 byte(s)
[Original ] [Print] [Top]
看如下的代码应该就清楚了,ret_from_intr是所有硬件中断的返回点.
arch/i386/kernel/entry.S:



ENTRY(system_call)

pushl %eax # save orig_eax

SAVE_ALL

GET_CURRENT(%ebx)

cmpl $(NR_syscalls),%eax

jae badsys

testb $0x20,flags(%ebx) # PF_TRACESYS

jne tracesys

call *SYMBOL_NAME(sys_call_table)(,%eax,4)

movl %eax,EAX(%esp) # save the return value

ALIGN

.globl ret_from_sys_call

.globl ret_from_intr

ret_from_sys_call:

movl SYMBOL_NAME(bh_mask),%eax

andl SYMBOL_NAME(bh_active),%eax

jne handle_bottom_half

ret_with_reschedule:

cmpl $0,need_resched(%ebx) # need_resched可被pdate_process_times()所置位

jne reschedule


cmpl $0,sigpending(%ebx)

jne signal_return

restore_all:

RESTORE_ALL



ALIGN

signal_return:

sti # we can get here from an interrupt handler

testl $(VM_MASK),EFLAGS(%esp)

movl %esp,%eax

jne v86_signal_return

xorl %edx,%edx

call SYMBOL_NAME(do_signal)

jmp restore_all



ALIGN

v86_signal_return:

call SYMBOL_NAME(save_v86_state)

movl %eax,%esp

xorl %edx,%edx

call SYMBOL_NAME(do_signal)

jmp restore_all



ALIGN

tracesys:

movl $-ENOSYS,EAX(%esp)

call SYMBOL_NAME(syscall_trace)

movl ORIG_EAX(%esp),%eax

cmpl $(NR_syscalls),%eax

jae 1f

call *SYMBOL_NAME(sys_call_table)(,%eax,4)

movl %eax,EAX(%esp) # save the return value

1: call SYMBOL_NAME(syscall_trace)

jmp ret_from_sys_call

badsys:

movl $-ENOSYS,EAX(%esp)

jmp ret_from_sys_call



ALIGN

ret_from_exception:

movl SYMBOL_NAME(bh_mask),%eax

andl SYMBOL_NAME(bh_active),%eax

jne handle_bottom_half

ALIGN



ret_from_intr: # 硬件中断的返回点

GET_CURRENT(%ebx)

movl EFLAGS(%esp),%eax # mix EFLAGS and CS

movb CS(%esp),%al

testl $(VM_MASK | 3),%eax # return to VM86 mode or non-supervisor?

jne ret_with_reschedule # 如果是VM86态或用户态就转ret_with_reschedule

jmp restore_all



ALIGN

handle_bottom_half:

call SYMBOL_NAME(do_bottom_half)

jmp ret_from_intr



ALIGN

reschedule:

call SYMBOL_NAME(schedule) # test

jmp ret_from_sys_call


---------------------------------------

kernel/sched.c:



update_process_times()被Timer Bottom Half所调用



static void update_process_times(unsigned long ticks, unsigned long system)

{

/*

* SMP does this on a per-CPU basis elsewhere

*/

#ifndef __SMP__

struct task_struct * p = current;

unsigned long user = ticks - system;

if (p->pid) {

p->counter -= ticks;

if (p->counter < 0) {

p->counter = 0;

p->need_resched = 1;

}

if (p->priority < DEF_PRIORITY)

kstat.cpu_nice += user;

else

kstat.cpu_user += user;

kstat.cpu_system += system;

}

update_one_process(p, ticks, user, system, 0);

#endif

}





[Original ] [Print] [Top]

Subject : 万分感谢jkl, 这下清楚了. :)
Author : pengchengzou    Posted : 2000-11-30 12:40    Length : 47 byte(s)
[Original ] [Print] [Top]
万分感谢jkl, 这下清楚了. :)

[Original ] [Print] [Top]

Subject : Re: 设备驱动的可重入问题
Author : bravebird    Posted : 2002-10-10 17:06    Length : 323 byte(s)
[Original ] [Print] [Top]
update_process_timers在2.4内核里面应该是在上半部中处理的.
我理解的顺序应该是这样:
时间中断产生->update_process_times(计算各个进程的时间片和优先级,决定是否需要重新调度need_sched ?=1)
->ret_from_intr->ret_with_reschedule->call schedule(如果需要的话);

----
我是一只小小小鸟,想要飞却怎么也飞不高....
[Original ] [Print] [Top]

Subject : Re: 设备驱动的可重入问题
Author : xunclapton    Posted : 2002-10-10 18:24    Length : 152 byte(s)
[Original ] [Print] [Top]
进程不调用系统调用也就是一直运行在用户态,但时钟中断还是会发生,如果这个进程时间片到期,时钟中断会把他的need_schedule置1,这样在返回用户态前被schedule()

http://www.niftyadmin.cn/n/4464089.html

相关文章

nginx环境下配置nagios-关于nagios配置文件

接上文&#xff1a;nginx环境下配置nagios-关于nginx.conf nagios文件应该处于conf/domain/目录下 nagios配置如下&#xff1a; server {listen 80;server_name 192.168.44.44;index index.html index.htm index.php;root /usr/local/nagios/share;auth_basic "…

操作系统多级页表计算问题

某计算机有64位虚地址空间&#xff0c;页大小是2048B.每个页表项长为4B。因为所有页表都必须包含在一页中&#xff0c;故使用多级页表&#xff0c;问一共需要多少级&#xff1f; 最佳答案2048B2^11 64-1153&#xff08;地址中扣除页内地址位数&#xff09; 共有2^53页一页中可…

nginx环境下配置nagiosQL-关于nagiosql配置文件

接上文&#xff1a;nginx环境下配置nagios-关于nginx.conf nagiosql文件应该处于conf/domain/目录下 nagiosql配置如下&#xff1a; server {listen 8088;server_name 192.168.44.44;index index.html index.htm index.php;root /usr/local/nagios/nagiosql/;locatio…

函数ERR_PTR,PTR_ERR还有IS_ERR理解

ERR_PTR()和PTR_ERR()都是很简单的类型转换&#xff0c;没有什么可说的。 IS_ERR()有一些妙处。 内核中的函数常常返回指针&#xff0c;问题是如果出错&#xff0c;也希望能够通过返回的指针体现出来。 所幸的是&#xff0c;内核返回的指针一般是指向页面的边界(4K边界)&#x…

nginx环境下配置nagios-关于start_perl_cgi.sh

文件配置如下&#xff1a; #!/bin/bash set -x dir/export/servers/nginxstop () { #pkill -f $dir/perl-fcgi.pl kill $(cat $dir/logs/perl-fcgi.pid) rm $dir/logs/perl-fcgi.pid 2>/dev/null rm $dir/logs/perl-fcgi.sock 2>/dev/null echo "stop perl-fcgi d…

sys_call_table undefined 及 如何替换系统调用

版权声明&#xff1a;转载时请以超链接形式标明文章原始出处和作者信息及本声明http://chenm.blogbus.com/logs/52077181.html 2.4的内核中可以通过修改sys_call_table来很轻松的替换系统调用&#xff0c;来完成很多trick&#xff0c;很多的rootkit就是基于这种手法来完成的。…

nginx环境下配置nagios-关于perl-fcgi.pl

配置文件如下&#xff1a; 请注意&#xff0c;网上提供的官方文档在运行时可能会出现问题&#xff0c;此文中保证无问题。 #!/usr/bin/perl # # author Daniel Dominik Rudnicki # thanks to: Piotr Romanczuk # email danielsardz…

(转)在Linux2.6内核下实现进程隐藏

很早以前的小程序&#xff0c;比较简单但是觉得有趣原理很简单&#xff0c;Linux查看进程的命令ps是通过系统调用sys_getdents实现&#xff0c;sys_getdents用户获取一个指定路径下的目录条目&#xff0c;实际上就是枚举/proc/ 下的pid&#xff0c;这样我们只需要hook一下sys_…