歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux綜合 >> Linux資訊 >> 更多Linux >> 通過振動向Linux ThinkPad傳輸信息

通過振動向Linux ThinkPad傳輸信息

日期:2017/2/27 14:13:14   编辑:更多Linux

2007 年 1 月 15 日

通過修改內核以在受震動導致內核出現緊急情況時自動重置 Linux 膝上型計算機,讓您的計算機處於受保護的狀態。在內核空間和用戶空間中實現震動檢測算法,從而執行自動關閉並在特定動力條件得到滿足時重新啟動。

2003 年,IBM® 開始銷售在商業操作系統中集成了加速度傳感器及相關軟件的 ThinkPad 膝上型計算機,以便在 ThinkPad 墜地時對硬盤進行保護。來自 IBM 和其他地方的富有魄力的計算機程序高手們已經為 Linux 內核開發了利用這些傳感器的模塊。膝上型計算機的屏幕顯示方向、桌面切換、甚至是游戲控制和實時 3D 模型等特性均已實現。

2006 年中期,適用於 Linux 膝上型計算機的基於敲擊的命令開始可用於用戶空間 Perl 腳本(與內核空間中的基於 C 的代碼相對),允許用戶運行基於特定敲擊序列的隨機命令。本文描述了修改 Linux 內核以添加經常需要的功能的過程:對物理輸入做出反饋。當 Linux 內核出現緊急情況時,用戶可以震動計算機(或對膝上型計算機執行開發人員可配置的任意次數的物理移動),計算機將重置。

本文還介紹了在非緊急情況模式下執行正常關閉的方法。例如,如果用戶不注意將計算機放在尚未拉好的計算機包中,則需要計算機檢測到正常行走或開車的動作,並關閉計算機。

先決條件

硬件

許多在 2003 年以後(包括 2003 年)制造的 IBM ThinkPad 都配有 HDAPS 硬件。如果不能確定硬件配置,可以到 Lenovo 的 Web 站點中查看詳細的技術信息。要運行以下代碼,必須有 ThinkPad。某些 MacBook 配有加速度傳感器及同樣的通過內核訪問這些傳感器的通用方法。但是,此處的代碼並未在 Apple 硬件上做測試,而是基於兩個 IBM ThinkPad T42p 型號開發及測試的。有關如何查找在物理上支持膝上型計算機所需的 ThinkPad 硬件的鏈接,請參閱 參考資料。

軟件

本文假定您熟悉內核構建過程,並了解內核編譯所帶來的發行版間的不一致性。有關內核構建過程的簡介,以及一些優秀的入門示例,請參閱 參考資料。

從 kernel V2.6.15 起,HDAPS 驅動程序已經包含在 Linux 內核中。為了簡單起見,請獲取最新的內核程序。為了便於開發及管理,本文是基於 Fedora Core V5 開發的。下面用於設置內核構建環境的指導信息是專門針對 Fedora Core 的,但是一般原理適用於所有 Linux 發行版。

內核開發設置

內核配置、編譯和測試

要修改內核,需要按照版本信息中的指導信息進行操作。打開 Web 浏覽器並開始按照第 8.6 節:“Preparing for Kernel Development” 中的指導信息進行操作。執行到第 2 部分時,可能會在執行第二條命令 su -c 'yumdownloader --source kernel' 時遇到問題。如果該命令未能把 kernel-2.6.15-1.2054_FC5.src.rpm 軟件包下載下來,請使用 wget 命令 wget FTP://ftp.linux.ncsu.edu/pub/fedora/linux/core/5/source/SRPMS/kernel-2.6.15-1.2054_FC5.src.rpm 來獲取該軟件包。

在執行步驟 5 時,請用 cp configs/kernel-2.6.15-i686.config .config 命令選擇基本的 i686 默認配置。確保將 makefile 中的 EXTRAVERSION 部分從 -prep 更改為 -1.2054_FC5。用 make oldconfig 更新構建配置。然後用 su -c "yum install kernel-devel" 命令安裝內核開發模塊。該模塊將用於編譯緊急情況觸發模塊。

我們現在已經完成了 Fedora Core V5 Release Notes 文檔中介紹的內核配置的相關部分。其余步驟都是所有內核構建過程通用的標准步驟。建議現在構建並安裝新內核、模塊和 RAM 磁盤設置以確保一切按預期運行。如果您對自己的新內核配置很有信心,可以跳過以下步驟並直接轉到內核修改部分。

用 make 命令構建新內核。成功構建內核後,請用 su -c "cp ./arch/i386/boot/bzImage /boot/vmlinuz-2.6.15hdaps" 命令將其復制到 /boot 目錄。您需要使用 su -c "make modules_install" 命令構建模塊。最後一個構建步驟是用 su -c "/sbin/mkinitrd hdapsInitrd.img 2.6.15-1.2054_FC5" 命令為 HDAPS 內核創建 RAM 磁盤。用 su -c "cp hdapsInitrd.img /boot/" 命令將這個新的 RAM 磁盤復制到引導區。引導時,用以下行更新 grub.conf 文件:

清單 1. grub 配置

title Fedora Core (2.6.15hdaps) root (hd0,0) kernel /vmlinuz-2.6.15hdaps ro root=/dev/VolGroup00/LogVol00 rhgb quiet initrd /hdapsInitrd.img修改 panic.c 和 hdaps.c

現在已經准備好開始一些可快速完成的內核配置。確保位於 ~/rpmbuild/BUILD/kernel-2.6.15/linux-2.6.15.i686 目錄。一定要先包含 hdaps 模塊作為內核的內置組件,從而准備好在計算機的運行模式中提供對各處的震動檢查。

使用 make menUConfig 命令並選擇 Device Drivers > Hardware Monitoring Support。鍵入 Y 以包含 Hardware Monitoring Support 模塊,因為 HDAPS 模塊依賴於此模塊。滾動到清單底部,並在 IBM Hard Drive Active Protection System (hdaps) 條目的旁邊再次鍵入 Y。退出菜單並保存配置。

打開 drivers/hwmon/hdaps.c 文件,然後將以下文本添加到 include 部分中:#include <linux/reboot.h>。並緊挨著 hdaps_read_pair 子程序後面添加下面的新子程序:

清單 2. 來自 hdaps.c 的完整的 panicShake 子程序

/* * panicShake - reboot the machine if shaken */extern void panicShake(void){ int ret, x, y; // return value and x,y from hdaps int int baseX = -5000; // off scale default values int baseY = -5000; int totalDev = 0; // running total of deviations from rest (shaking total) int devThreshold = 4000; // larger threshold for more shaking int dimShiftX = 150; // in case your users shake more in a certain dimension int dimShiftY = 150; while(1) { ret = hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y); if (!ret) { if( x != 0 && y != 0 ) { // if its a successful read and not a zero read if( baseX == -5000 ) { baseX = x; baseY = y; } if( abs(baseX - x) > dimShiftX abs(baseY - y) > dimShiftY ) { totalDev += abs(baseX - x); totalDev += abs(baseY - y); } if( totalDev > devThreshold ) { printk(KERN_EMERG "ok, ok! you're shaking my substrate - restarting"); emergency_restart(); } }//if not a zero value }//if successful read of hdaps data }//infinite while}//panicShake震動檢測程序就緒後,需要在系統出現緊急情況時調用該檢測程序。打開 kernel/panic.c 文件,並在緊挨著 panicBlink 條件部分之前的位置上放置一個對 panicShake(); 子程序的調用。發出 make 命令。趁著對內核進行重新構建時,讓我們復查一下震動檢測代碼。首先,設置一些變量:

清單 3. panicShake 變量

int ret, x, y; // return value and x,y from hdaps int baseX = -5000; // off scale default values int baseY = -5000; int totalDev = 0; // running total of deviations from rest (shaking total) int devThreshold = 4000; // larger threshold for more shaking int dimShiftX = 150; // in case your users shake more in a certain dimension int dimShiftY = 150;

需要特別注意的是偏差阈值參數和空間移位參數。這些參數可能需要根據嘗試檢測的動作的獨特性質做出調整。例如,如果感覺迫切需要像完成籃球傳球動作一樣震動計算機,可嘗試減少 dimShiftX 參數以更輕松地檢測垂直於計算機屏幕的動作。反過來,如果震動脈沖觸發劇烈的鋸齒狀動作,則考慮減少 dimShiftY 參數,以便快速地檢測平行於屏幕的震動並在發生進一步的損害之前重置計算機。

空間參數選擇 150 及總偏差選擇 4000 都旨在檢測一般用戶的典型震動動作。要立即響應輸入,請嘗試將空間移位參數減少到 10 或更少,並將總偏差參數減少到 10 或更少。這些值將導致其他類型的輸入被立即識別出來,例如猛擊鍵盤或拍打顯示器外殼。

接下來,考慮無限循環語句和條件。

清單 4. panicShake hdaps 讀取和基本設置

while(1) { ret = hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y); if (!ret) { if( x != 0 && y != 0 ) { // if its a successful read and not a zero read if( baseX == -5000 ) { baseX = x; baseY = y; }代碼運行如下:其余時間裡,從 Hdaps 傳感器中讀取當前加速度傳感器讀數。讀數經常是不成功的或者兩個值都等於 0,0,這是不能用的數據。需要避免這些虛假的 0,0 讀數,來自傳感器各個方向上的每 10 個讀數中就會有一個讀數是 0,0 —— 無效的數據,確實如此。如果是首次成功讀取,則將基本參數設為第一個 x 值和 y 值。如果計算機被放在不平的表面(例如人的膝蓋上)時發生緊急情況,這將允許我們更有力地檢測震動或其他動作。

子程序的其余部分實現簡單的震動檢測算法。

清單 5. panicShake 震動檢測

if( abs(baseX - x) > dimShiftX abs(baseY - y) > dimShiftY ) { totalDev += abs(baseX - x); totalDev += abs(baseY - y); baseX = x; baseY = y; } if( totalDev > devThreshold ) { printk(KERN_EMERG "ok, ok! you're shaking my substrate - restarting"); emergency_restart(); } }//if not a zero value }//if successful read of hdaps data }//infinite while如果在任意方向上的空間移位大於我們先前設定的阈值,就按照兩個方向上移動的量增加總偏差。然後將當前的基數設為現有的加速度級別。這樣重復地重新初始化基數值要求用戶持續超出空間移位值以增加檢測到的總偏差。這允許用戶在緊急模式下移動並存儲 ThinkPad,從而安全地將機器送到系統管理員那裡。如果僅需要側立、傾斜和持拿 ThinkPad 以觸發重新啟動,請刪除重新初始化設定。

測試 panicShake() 內核

要發動一種緊急情況,需要在內核中調用緊急情況子程序。創建以下 makefile:obj-m := panicCall.o,程序 panicCall.c 在編譯時將使用該文件:

清單 6. panicCall.c 內核模塊源代碼

/* * panicCall.c - Instigate a kernel panic */#include <linux/module.h> /* Needed by all modules */#lincude <linux/kernel.h> /* Needed for KERN_INFO */static char *pMesgStr = "PANIC SHAKE AND BAKE";int init_module(void){ printk(KERN_INFO,"panicCall module loaded\n"); panic(pMesgStr); return(0);}void cleanup_module(void){ printk(KERN_INFO,"panicCall module unloaded, beyond possible");}以超級用戶身份用 make -C /lib/modules/$(uname -r)/build SUBDIRS=$PWD modules 命令編譯 panicCall 模塊。現在就有了一個可調用的模塊可以使用 insmod panicCall.ko 命令觸發緊急情況。如果還沒有該模塊則重新引導(以激活 hdaps 緊急情況下觸發啟用震動的內核),並運行 insmod panicCall.ko。應當會看到類似以下內容:

清單 7. 內核緊急情況堆棧

panicCall: module license 'unspecified' taints kernel.Kernel panic - not syncing: PANIC SHAKE AND BAKE ACTIVE [<c011a32e>] panic+0x3e/0x174 [<f8a97017>] init_module+0xb/0xc [panicCall] [<c013050a>] sys_init_module+0x1382/0x1514 [<c0152413>] do_sync_read+0xb8/0xf3 [<c012a17f>] autoremove_wake_function+0x0/0x2d [<c01c0672>] _atomic_dec_and_lock+0x22/0x2c [<c0169c32>] mntput_no_expire+0x11/0x6d [<c0102bc1>] syscall_call+0x7/0xb現在拿起計算機,然後用力地晃動它,計算機將打印出 “shaking substrate” 消息並執行重新啟動。如果您不希望晃動可能活動的磁盤驅動器,請以超級用戶身份發出以下命令:

清單 8. RAM 磁盤創建和模塊復制

mkdir /tmp/ramdisk0mke2fs /dev/ram0mount /dev/ram0 /tmp/ramdisk0/cp /root/panicCall.ko /tmp/ramdisk0/cp /sbin/insmod /tmp/ramdisk0/現在有了將模塊插入位於 RAM 磁盤的內核所需的兩個文件。用以下部分更新 /etc/init.d/halt 腳本,將其放在剛好位於 fsck check 部分之下 halt execute 部分之上的位置:

清單 9. 修改 /etc/init.d/halt

echo "disks now mounted in readonly mode, spin down in 5 seconds";/sbin/hdparm -S 1 /dev/hdaecho "spin down hda called, waiting 10 seconds";sleep 10echo "calling panic from ramdisk location";/tmp/ramdisk0/insmod /tmp/ramdisk0/panicCall.ko

以超級用戶身份執行命令 init 0 以將計算機轉入關閉模式中。在調用關閉程序前,計算機將把緊急情況觸發模塊裝入內核,並調用震動檢測程序。 如果在系統關閉時仔細聽硬盤的聲音,可以聽到明顯比以往更長的喀哒聲,然後多普勒磁盤將隨著機械臂逐漸下降的 “積載” 位置而降低並且磁盤旋轉停止。再過大約五秒鐘後,將從 RAM 磁盤執行緊急情況模塊,而物理磁盤頭仍停止不動。現在,您可以隨心所欲地晃動 ThinkPad 而無需考慮磁盤的運行狀況。

用戶空間關閉和動作檢測

很多 IT 管理員都十分懷念能夠隨時獲知硬件物理歷史記錄的功能。使用同一個簡單的震動檢測算法、一個 Perl 腳本和一種監視策略,管理員將能夠更好地跟蹤硬件的狀態。例如,使用下面的 Perl 腳本在計算機遭到用戶震動時平穩地關閉計算機。根據用戶對 ThinkPad 的操作發送一封電子郵件、閃爍 “ThinkLight” 或播放一個聲音文件,這些都可以輕松地完成。

清單 10. 用於檢測震動的 Perl 腳本,第 1 部分

#!/usr/bin/perl -w # shakeShutdown.pl - shutdown (or other command) when the computer is shakenuse strict;my $file = "/sys/devices/platform/hdaps/position";my $baseX = -5000;my $baseY = -5000;my $totalDev = 0;if( @ARGV != 1 ){ die "specify a threshold value" }my $devThreshold = $ARGV[0];my $dimShiftX = 150;my $dimShiftY = 150;while(1){ open(HD,"$file") or die "can't open file"; my $line = <HD>; chomp($line); $line =~ s/\(//g; $line =~ s/\)//g; $line =~ s/\,/ /g; my( $x, $y ) = split " ", $line;正如您所見,初始的程序設置幾乎與 hdaps 內核代碼完全相同。正則表達式和 split 命令僅將 x 值和 y 值從 (5,4) 更改為 5 和 4。程序的其余部分實質上也是相同的:

清單 11. 用於檢測震動的 Perl 腳本,第 2 部分

if( $x != 0 >> $y != 0 ) { if( $baseX == -5000 ) { $baseX = $x; $baseY = $y; } if( abs($baseX - $x) > $dimShiftX abs($baseY - $y) > $dimShiftY ) { $totalDev += abs($baseX -$x); $totalDev += abs($baseY -$y); $baseX = $x; $baseY = $y; } if( $totalDev > $devThreshold ) { print "threshold passed $totalDev\n"; my $res=`/sbin/shutdown -h 1`; } } close(HD);}請注意 shutdown -h 1 命令。這將給用戶提供 60 秒的時間更改方法並發出關閉中止。更改此命令以運行您最喜歡的郵件程序,用戶濫用設備時可以讓系統管理員知道此情況。將消息記錄到系統日志中,或讓 PC 揚聲器發出聲響以便對獲得的物理輸入發出即時用戶反饋。用 perl shakeShutdown.lp 1000 命令運行腳本。偏差阈值變得更小,因為加速度傳感器的每次讀取間隔與內核空間的每次讀取間隔比較而言減少了。

修改空間移位參數和偏差阈值可以提供有益的對內核空間外部的物理活動的額外監視。例如,要采集 “行走” 行為的數據,需要將空間移位參數設為大約 20,並將偏差阈值設為大約 5000。這將檢測到大約 63 個雙坐標軸空間移位,這與膝上型計算機在處於運行狀態時被放在典型的單肩背膝上型計算機包中的情況一致。檢測到這種長距離行走後(不同於從辦公位置到會議室的短距離行走),計算機將進入關閉程序以避免過熱,因為空氣在背包中不流通。修改空間移位參數使其具有高靈敏度,任何較大的撞擊、墜落或震動都會被記錄下來。

結束語

通過使用針對用戶空間和內核級代碼的這些簡單算法,現在能夠檢測、記錄和響應來自用戶的各種物理輸入。使用這些代碼示例,從根據連續的加速度計算出來的高度修改硬盤性能參數,到丈量從辦公位置到會議室的距離,並將其用郵件發送給空間規劃師,您都可以應對自如。




Copyright © Linux教程網 All Rights Reserved