プロセスの優先度を強制的に変更
仕事で少し必要になったので得意じゃないVCを。
OpenProcess()でプロセスのハンドラを取得してSetPriorityClass()で優先度を変更するだけと思っていたのですが、一部のプロセスはアクセス拒否で弾かれてしまいました。サービスプロセスやSYSTEMユーザで起動しているプロセスは変更できないのですね。
でもSysinternal社のProcess Explorer*1だとお構いなしに優先度を変更できるので少し調べたところ、こんな感じでいけるのではなかろうかと。(あってるのか?)
- AdjustTokenPrivileges()で特権をつけて
- OpenProcess()でハンドラを取得して
- SetPriorityClass()で優先度変更
- AdjustTokenPrivileges()の特権を無効
とりあえずゴミコード。ここのMicrosoftサポートオンラインをまるパクリ。
#include "stdafx.h" #include <windows.h> #include <stdio.h> #define RTN_OK 0 #define RTN_USAGE 1 #define RTN_ERROR 13 BOOL SetPrivilege( HANDLE hToken, // token handle LPCTSTR Privilege, // Privilege to enable/disable BOOL bEnablePrivilege // TRUE to enable. FALSE to disable ); void DisplayError(LPTSTR szAPI); int _tmain(int argc, char **argv) { DWORD priority_class = BELOW_NORMAL_PRIORITY_CLASS; DWORD pid; DWORD result = true; HANDLE hProcess; HANDLE hToken; if(!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, FALSE, &hToken)) { if (GetLastError() == ERROR_NO_TOKEN) { if (!ImpersonateSelf(SecurityImpersonation)) return RTN_ERROR; if(!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, FALSE, &hToken)){ DisplayError("OpenThreadToken"); return RTN_ERROR; } } else return RTN_ERROR; } // enable SeDebugPrivilege if(!SetPrivilege(hToken, SE_DEBUG_NAME, TRUE)) { DisplayError("SetPrivilege"); CloseHandle(hToken); return RTN_ERROR; } pid = atoi(argv[1]); if ((hProcess = OpenProcess (PROCESS_SET_INFORMATION, FALSE, pid)) == NULL) { DisplayError("OpenProcess"); CloseHandle(hToken); return false; } if (!SetPriorityClass(hProcess, priority_class)) { DisplayError("SetPriorityClass"); result = false; } else { fprintf(stdout,"SetPriorityClass() Success: %d\n", priority_class); } // disable SeDebugPrivilege SetPrivilege(hToken, SE_DEBUG_NAME, FALSE); CloseHandle (hProcess); CloseHandle (hToken); return true; } BOOL SetPrivilege( HANDLE hToken, // token handle LPCTSTR Privilege, // Privilege to enable/disable BOOL bEnablePrivilege // TRUE to enable. FALSE to disable ) { TOKEN_PRIVILEGES tp = { 0 }; // Initialize everything to zero LUID luid; DWORD cb=sizeof(TOKEN_PRIVILEGES); if(!LookupPrivilegeValue( NULL, Privilege, &luid )) return FALSE; tp.PrivilegeCount = 1; tp.Privileges[0].Luid = luid; if(bEnablePrivilege) { tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; } else { tp.Privileges[0].Attributes = 0; } AdjustTokenPrivileges( hToken, FALSE, &tp, cb, NULL, NULL ); if (GetLastError() != ERROR_SUCCESS) return FALSE; return TRUE; } void DisplayError( LPTSTR szAPI // pointer to failed API name ) { LPTSTR MessageBuffer; DWORD dwBufferLength; fprintf(stderr,"%s() error!\n", szAPI); if(dwBufferLength=FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), GetSystemDefaultLangID(), (LPTSTR) &MessageBuffer, 0, NULL )) { DWORD dwBytesWritten; // Output message string on stderr WriteFile(GetStdHandle(STD_ERROR_HANDLE), MessageBuffer, dwBufferLength, &dwBytesWritten, NULL); // free the buffer allocated by the system LocalFree(MessageBuffer); } }
いちおう出来てるっぽいかな。
プロセスの優先順位クラスを備忘録としてメモ。
REALTIME_PRIORITY_CLASS | リアルタイム(R) |
HIGH_PRIORITY_CLASS | 高(H) |
ABOVE_NORMAL_PRIORITY_CLASS | 通常以上(A) |
NORMAL_PRIORITY_CLASS | 通常(N) |
BELOW_NORMAL_PRIORITY_CLASS | 通常以下(B) |
IDLE_PRIORITY_CLASS | 低(L) |
*1:sysinternalのツールさいこー
freeSSHdを試してみた
freeSSHd という Free の Windows版 SSHサーバがあるので使ってみました。
インストール
インストーラを何も考えずにすべてYesとOkを押して終わり。
設定
タスクトレイのアイコンから [setting] -> [Users] の Add を押します。Windowsの既存の認証にする場合は NT Authentication を選択してユーザを入力します。使いたい機能にチェックを入れます。わからない場合は Shell, SFTP, Tunnelingすべてにチェックしてください。
Cygwinをインストールしている場合は、Cygtermに変更すると便利になります。
ファイアウォールにポート22の許可を入れましょう。
Windows7beta版を試してみた
巷ではWindows7は結構軽くて速いと言われているので、VMware-Server1.xにインストールして確認してみました。
簡易ベンチ
- http://www.gizmodo.jp/2008/11/giz_explains_windows_7vista_1.html
- http://www.gizmodo.jp/2008/12/windows_7_vs_vista_vs_xp.html
色々なところでベンチマークが行われていますね。リソース使用量だけ知りたかったので、スタートメニューにテストコードを登録しておいて、起動直後の「メモリ使用量とサービスの数」を確認しました。
VMwareホストマシン
OS | Microsoft Windows XP Professional SP3 |
---|---|
CPU | AMD Phenom X4 9550 Quad Core |
VMwareゲストマシン
比較OS | WindowsXPXP3, Windows7beta版 |
---|---|
CPU | 2CPU割り当て |
Memory | 1024MB |
Disk | 30GB(スパースファイルで作成) |
VMwareTools | インストール済み |
- テストコード
Set wbemServices = GetObject("winmgmts:\\" & "localhost") Set wbemObjectSet = wbemServices.InstancesOf("Win32_OperatingSystem") For Each wbemObject In wbemObjectSet WScript.Echo "TotalMemory = " & wbemObject.TotalVisibleMemorySize WScript.Echo "UsedMemory = " & wbemObject.TotalVisibleMemorySize - wbemObject.FreePhysicalMemory WScript.Echo "FreeMemory = " & wbemObject.FreePhysicalMemory Next Set wbemObjectSet = wbemServices.InstancesOf("Win32_Service") For Each wbemObject In wbemObjectSet if wbemObject.State = "Running" then count = count + 1 end if Next WScript.Echo "Service Count: " & count
VMwareゲスト | メモリ使用量 | サービス数 |
---|---|---|
WindowsXPSP3 | Total:1048048 / Used:204104 | 43 |
Windows7beta | Total:1047372 / Used:313536 | 43 |
結果Windows7beta版の方が、100MBほど使用量が多い結果になりました。無駄なデスクトップの視覚効果や自動起動するアプリケーションを削ればもう少し肉薄できる感じがします。サービスの数もあまり変わらないようです。Windowsはバージョンが上がるたびに知らないサービスが増えてて困ったものですが今回はそれほど違いはなさそうですね。
しかし、WMIで取得したTotalのメモリサイズの値がWindowsXPとWindows7で微妙に違うのが気になるところです。*1
*1:WMIに大幅な変更があったら嫌だな