一个Linux的小疑问 -- i8253 count too high! resetting

本文探讨了Linux虚拟机中出现的i8253计时器错误“i8253counttoohigh!resetting..”,提供了两种解决方案:一是通过编辑GRUB配置文件关闭警告提示;二是通过修改内核源代码中的time.c文件并重新编译内核来消除错误。

安装了一个Linux虚拟机,用的软件是Microsoft Virtual PC 2004,Linux安装上了桌面环境,当我CTRL+ALT+F1切换到tty1后,隔断时间就会出现“i8253 count too high! resetting..”不知何故,后来从百度知道查找是这样解释的:"i8253是计算机内的一个计时器芯片,当使用虚拟机或是某些笔记本安装linux的时候,系统的时间会不定期的产生一些误差,包括linux在内的很多系统都可以进行纠正这种时间上的混乱。Linux的2.4.20核心以及更高版本的核心在处理这种时间上的混乱时会同时发送一条Debug信息,这条信息就是i8253 count too high"

不知道这个回答是否正确,要是那样的话,我们有没有方法纠正这种时间上的误差呢,因为总是出现这条提示信息,确实很不爽,继续研究一下......

解决它可以有两种途径:1.关闭提示 2.消除误差
1.关闭提示
开机到grub处,按下e键,选择kernel /vmlinuz-2.4.20-8 ro root=LABEL=/ ,在末尾处“空格+single”,然后回车退出,再按b键引导进入单用户模式,在单用户模式下输入chkconfig pcmcia off,然后reboot重启就可以了
2.消除误差
Linux系统本身就已经具备了消除这种误差的功能,因为i8253 count too hight,reseting,本身就是一个Debug的回显信息,系统是如何消除这种误差的呢?虚拟的什么工作原理导致了这种误差的出现呢??难道还要研究一下虚拟机的内部结构?
待续......

网上找到的方案

Re: i8253 count too high - how to fix in 2.4.xx kernel
I 'solved' the problem by removing the message from the linux kernel source
and
compiling it again then installing the new kernel. No more messages!

You *NEED* to have the kernel source on your virtual machine to do this.

On 2.4.x kernel sources (assuming your linux sources is at /usr/src/linux)
the
file that needs editing is time.c found like this...
root@dana2:/root$ cd /usr/src/
root@myserver:/usr/src$ grep " i8253 count too high! resetting.." *

which outputs:

grep: Documentation: Is a directory
grep: arch: Is a directory
grep: crypto: Is a directory
grep: drivers: Is a directory
grep: fs: Is a directory
grep: include: Is a directory
grep: init: Is a directory
grep: ipc: Is a directory
grep: kernel: Is a directory
grep: lib: Is a directory
grep: mm: Is a directory
grep: net: Is a directory
grep: scripts: Is a directory
arch/i386/kernel/time.c:                               " i8253 count too
high! resetting../n");

Go edit this time.c file and it is the two lines 690/691 (for 2.4.27
anyway). At comment
markers around the two lines then save and build a new kernel and install.

time.c lines 690 & 691
-------------------------------
/*              printk(KERN_WARNING
" i8253 count too high! resetting../n"); */

The line numbers may or may not be the same for other 2.4.xx kernels but it
will be the
same file.

Regards

...Petar



"Ben Armstrong [MSFT]" < benarm@online.microsoft.com> wrote in message
news:uCqV10exEHA.3096@tk2msftngp13.phx.gbl...
> The i8253 chip is part of the timing mechanism inside of a computer -
> now - it happens that inside of virtual machines (and on a number of
> physical laptops) time will go backwards by small amounts every now and
> then.  Most operating systems have code to support such perturbations -
> including Linux.  But for some reason in kernels 2.4.20 and later - they
> decided to print out a debug message whenever this happens.  This has
> caused a lot of confusion for laptop users - but this message can be
> ignored.
> --
> Cheers,
> Benjamin Armstrong
> ===============================
> Virtual machine Program Manager
>
> This posting is provided "AS IS" with no warranties, and confers no
rights.[vbcol=seagreen]
> You assume all risk for your use.
>
> Chris wrote:
大致意思是说:
    对于部分计算机(物理的)和虚拟机,其 i8253芯片(一块可编程计数器)会不断的  复位 『回到之前的设置』 (go backwards),这个故障是无关紧要的,可以通过重新编译内核来解决。
    文中以2.4.27的内核为例,通过修改源代码的time.c(arch/i386/kernel/time.c)文件的
690/691行(不同版本的位置不同,但文件相同)解决,文中将
printk(KERN_WARNING" i8253 count too high! resetting../n");
一句加上了注释,解决了这个问题,(当然要重新编译一下内核).
我用的是dsl,没有源代码,郁闷啊!~
 
<think>我们正在处理一个关于shell警告"shell level too high resetting to 1"的问题。根据用户提供的信息,这个警告通常发生在shell嵌套层级(通过环境变量SHLVL表示)过高时,系统为了防止无限递归或资源耗尽而将SHLVL重置为1。 根据引用[1]中的内容,我们可以了解到在bash中,即使前面的命令出错,bash也会继续执行后面的命令。这可能导致一些问题,特别是在脚本中嵌套调用shell(比如在一个shell脚本中调用另一个shell脚本)时,可能会使得SHLVL不断增加,直到达到某个阈值(通常是100)而触发此警告。 解决方案: 1. 检查脚本中是否存在不必要的shell嵌套调用。例如,在脚本中使用`sh`或`bash`命令调用另一个脚本,而实际上可以使用函数或者使用`source`命令(.命令)来避免创建新的shell进程。 2. 如果确实需要调用子shell,注意控制嵌套深度,或者考虑重构代码以减少嵌套。 3. 检查环境变量SHLVL的值,如果发现异常增长,可以尝试在适当的位置重置它(但需谨慎,因为SHLVL是用于记录shell嵌套层级的,通常由shell自动管理)。 然而,需要注意的是,SHLVL变量是由shell自动维护的,每当启动一个新的子shell时,SHLVL就会增加1,退出子shell时减少1。当SHLVL达到一个很高的值(比如100)时,shell会发出警告并重置为1,以防止无限递归。 因此,常见的原因可能是: - 在某个脚本中循环调用自身(直接或间接递归),导致SHLVL不断增加。 - 在配置文件(如.bashrc, .profile等)中意外地启动了新的shell,导致每次打开终端时SHLVL都增加。 具体解决步骤: 步骤1:检查脚本中的递归调用 如果是在运行某个脚本时出现此警告,检查该脚本以及它调用的其他脚本是否存在递归调用。特别注意循环中是否调用了相同的脚本。 步骤2:检查shell配置文件 在用户的shell配置文件(如~/.bashrc, ~/.bash_profile, ~/.profile等)中,检查是否有启动新shell的命令。例如,在配置文件中直接调用一个脚本,而该脚本又启动了新的shell,这样每次打开终端都会增加SHLVL。 步骤3:使用调试信息 在出现问题的脚本中添加调试信息,打印SHLVL的值,以便追踪嵌套层级增加的位置。 例如,在脚本开头添加: ```sh echo "Current shell level: $SHLVL" ``` 步骤4:避免不必要的子shell - 使用函数替代脚本:如果多个脚本需要执行相同的任务,可以将这些任务封装成函数,然后在主脚本中调用这些函数,这样就不会启动新的shell进程。 - 使用`source`或`.`命令:如果需要在当前shell环境中执行另一个脚本(比如设置环境变量),应该使用`source script.sh`或`. script.sh`,而不是`sh script.sh`。 步骤5:检查终端启动配置 如果每次打开终端都会出现警告,那么问题可能出在终端启动时加载的配置文件。检查配置文件中是否有启动新shell的命令,比如在配置文件的末尾有`bash`或`sh`命令。 步骤6:重置SHLVL(临时解决方案) 如果问题难以定位,可以在需要的时候手动重置SHLVL(但这不是根本解决办法): ```sh export SHLVL=0 ``` 注意:这可能会干扰shell的正常嵌套计数,所以只建议作为临时调试手段。 根据引用[2]的内容,我们注意到一个与QEMU虚拟机和内核相关的问题,但这个问题似乎与当前的shell警告无关。因此,我们主要关注shell脚本的嵌套问题。 总结:解决"shell level too high resetting to 1"警告的关键是减少shell的嵌套深度,避免不必要的子shell启动,并检查递归调用。 相关问题: 1. 如何检查shell脚本中的递归调用? 2. 在bash中,`source`命令和直接执行脚本有什么区别? 3. 如何调试shell脚本的嵌套层级问题? 4. 环境变量SHLVL的作用是什么? 5. 在.bashrc文件中应该注意哪些问题以避免shell嵌套?</think>### 解决 "shell level too high resetting to 1" 警告 此警告表示 Shell 嵌套层级(通过 `$SHLVL` 环境变量跟踪)超过系统阈值(通常为 100 层),系统自动将其重置为 1。这通常由以下原因引起: #### 常见原因及解决方案 1. **递归调用 Shell 脚本** - **问题**:脚本直接或间接调用自身(如 `A.sh` 调用 `B.sh`,`B.sh` 又调用 `A.sh`) - **解决**: - 检查脚本调用链,避免循环依赖 - 使用函数替代重复调用的脚本 ```bash # 错误示例:递归调用 # script.sh 内容: ./script.sh # 调用自身 # 正确做法:改用函数 main_task() { # 核心逻辑 } main_task ``` 2. **Shell 配置文件问题** - **问题**:`~/.bashrc`、`~/.profile` 等文件意外启动新 Shell - **解决**: - 检查配置文件中是否包含 `bash`、`sh` 等命令 - 避免在配置文件中直接执行可能启动子 Shell 的操作 ```bash # 错误示例:在 .bashrc 中启动新 Shell if [ -f /some/file ]; then bash # 导致嵌套 fi ``` 3. **终端模拟器配置问题** - **问题**:终端设置(如 GNOME Terminal)在启动时额外调用 Shell - **解决**:检查终端配置的 "自定义命令" 选项,确保未设置强制启动 Shell 的命令。 4. **环境变量污染** - **问题**:`$SHLVL` 被手动修改或异常继承 - **解决**: - 临时重置:`export SHLVL=0` - 检查脚本中是否有修改 `SHLVL` 的代码 #### 调试步骤 1. **追踪 Shell 层级** 在脚本中添加调试信息: ```bash echo "[DEBUG] Current SHLVL: $SHLVL" # 显示当前层级 ``` 2. **检查配置文件** 使用 `grep` 扫描配置文件中可疑命令: ```bash grep -r "sh\\|bash" ~/.bashrc ~/.profile /etc/profile.d/ ``` 3. **简化复现** 通过最小化脚本逐步排除问题: ```bash # test.sh echo "SHLVL start: $SHLVL" # 注释掉可疑代码块 # ./other_script.sh echo "SHLVL end: $SHLVL" ``` #### 预防措施 - 用 `source` 替代直接执行(避免新建 Shell): ```bash # 替代 ./utils.sh source utils.sh # 在当前 Shell 执行 ``` - 控制脚本调用深度,必要时用 `wait` 管理并行任务 - 定期检查环境变量: ```bash env | grep SHLVL # 监控层级变化 ``` > 引用说明:调试时使用 `echo` 输出关键状态是定位 Shell 问题的有效方法,通过检查输出可快速定位嵌套层级异常点[^1]。 --- ### 相关问题 1. 如何查看当前 Shell 的嵌套层级? 2. `source script.sh` 和 `./script.sh` 有何区别? 3. 在 Shell 脚本中如何避免环境变量污染? 4. 哪些操作会隐式创建新的 Shell 子进程? 5. 如何调试 Shell 脚本中的无限递归问题? [^1]: 引用自用户提供的调试方法说明,通过插入唯一标识消息定位代码问题段落。 [^2]: 引用自用户提供的系统兼容性说明,涉及内核版本与虚拟化问题(与当前问题关联度较低)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值