解决i8253 count too high !resetting!的其他方法

本文介绍了解决Linux系统启动时出现的提示和消除特定错误的方法。包括如何进入单用户模式禁用pcmcia服务以及通过修改内核源代码来消除i8253计数过高的警告。
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的回显信息,系统是如何消除这种误差的呢?

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.
// 系统校准流程 void AD7190_SystemCalibrate(void) { if (!ad7190_state.is_initialized) AD7190_Init(); uint8_t rx_char; uint32_t start_time = HAL_GetTick(); // 获取开始时间 printf("===== System Calibration =====\r\n"); // 1. 零点校准 printf("Ensure platform is empty, then press 'z' for zero calibration...\r\n"); while(1) { if (HAL_UART_Receive(&huart1, &rx_char, 1, 100) == HAL_OK) { if(rx_char == 'z' || rx_char == 'Z') break; } // 添加超时检测 if (HAL_GetTick() - start_time > CALIBRATION_TIMEOUT) { printf("Calibration timed out\n"); return; } } // 读取32个样本,丢弃异常值 uint32_t samples[32]; int valid_count = 0; for(int i = 0; i < 32; i++) { uint32_t data = AD7190_ReadData(); // 检查数据有效性(排除异常值) if (data > 0 && data < 0xFFFFFF) { samples[valid_count++] = data; } HAL_Delay(10); } if (valid_count < 16) { printf("ERROR: Not enough valid samples for zero calibration (%d/32)\n", valid_count); return; } // 计算中值代替平均值(更抗干扰) qsort(samples, valid_count, sizeof(uint32_t), compare_uint32); ad7190_state.calib.calibration_offset = samples[valid_count / 2]; // 2. 量程校准 printf("Place 1000.0g weight, then press 'f' for full scale calibration...\r\n"); while(1) { if (HAL_UART_Receive(&huart1, &rx_char, 1, 100) == HAL_OK) { if(rx_char == 'f' || rx_char == 'F') break; } // 添加超时检测 if (HAL_GetTick() - start_time > CALIBRATION_TIMEOUT) { printf("Calibration timed out\n"); return; } } // 读取32个样本,丢弃异常值 // 读取32个样本,丢弃异常值 uint32_t F_samples[32]; int F_valid_count = 0; for(int i = 0; i < 32; i++) { uint32_t data = AD7190_ReadData(); // 检查数据有效性(排除异常值) if (data > 0 && data < 0xFFFFFF) { F_samples[F_valid_count++] = data; } HAL_Delay(10); } if (valid_count < 16) { printf("ERROR: Not enough valid samples for full scale calibration (%d/32)\n", valid_count); return; } // 计算中值代替平均值 qsort(F_samples, F_valid_count, sizeof(uint32_t), compare_uint32); uint32_t full_scale = F_samples[valid_count / 2]; // 计算校准因子(增加安全范围检查) int32_t diff = (int32_t)full_scale - (int32_t)ad7190_state.calib.calibration_offset; if (diff <= 1000) { // 1000是经验值,根据实际传感器调整 printf("ERROR: Invalid calibration difference (%ld). Too small!\n", diff); return; } if (diff > 10000000) { // 防止异常大值 printf("ERROR: Invalid calibration difference (%ld). Too large!\n", diff); return; } ad7190_state.calib.calibration_factor = 1000.0f / (float)diff; // 重置去皮值和滤波器 ad7190_state.calib.tare_value = 0.0f; KalmanFilter_Init(&ad7190_state.kf, 0.001f, 0.01f, 1.0f, 0.0f); // 保存到EEPROM // AD7190_SaveCalibrationToEEPROM(); printf("System calibration completed! Factor: %f\n", ad7190_state.calib.calibration_factor); } REFIN2 configured successfully (GPOCON: 0x00) Internal zero calibration completed AD7190 initialized successfully ===== System Calibration ===== Ensure platform is empty, then press 'z' for zero calibration... Place 1000.0g weight, then press 'f' for full scale calibration... System calibration completed! Factor: 0.004975 WARNING: Only 0/32 valid samples Weight: 0.0g WARNING: Only 0/32 valid samples Weight: 0.0g WARNING: Only 0/32 valid samples Weight: -69.0g WARNING: Only 0/32 valid samples什么原因?
08-21
<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、付费专栏及课程。

余额充值