顯示具有 Computer 標籤的文章。 顯示所有文章
顯示具有 Computer 標籤的文章。 顯示所有文章

星期日, 4月 12, 2009

What is the sleep state when Windows suspend?

參照ACPI Sleeping State Definitions

S1 and S3 是ACPI 定義的Sleep State, 分別代表不同程度的省電模式。BIOS會提供ACPI table 提供Sleep State method (\_Sx),所以ACPI 作業系統就可以知道這台機器是否符合ACPI規範,可以支援省電模式。所以如果BIOS只提供\_S1 method, 那Windows就會suspend就會進S1,如果只提供\_S3 method,那Windows就會進S3。那如果兩個都提供呢?

我無從得知Windows喜歡進那個作業系統,Microsoft另外有釋放一支程式dumppo.exe (XD,沒教人怎麼寫這種程式...)。


C:\tmp>dumppo admin
Admin policy overrides
Min sleep state......: S1
Max sleep state......: S4 - hibernate
Min video timeout....: 0
Max video timeout....: -1
Min spindown timeout.: 0
Max spindown timeout.: -1

執行dumppo admin minsleep=s3,則可設定Windows suspend進入s3。

C:\tmp>dumppo admin minsleep=s3
Admin policy overrides
Min sleep state......: S3
Max sleep state......: S4 - hibernate
Min video timeout....: 0
Max video timeout....: -1
Min spindown timeout.: 0
Max spindown timeout.: -1


另外,插上USB Keyboard or USB mouse, 讓Windows XP進入Suspend, 此時會發覺Windows 會進入S3,但是無法從USB keyboard或是USB mouse按鈕讓系統回復工作狀態。如果要讓USB裝置能夠喚醒系統,就要在裝置管理員裡特別選擇允許此裝置能夠喚醒系統。

allow_device_wakeup

可是一旦設定好讓USB裝置能夠喚醒,就會發覺Windows只能進入S1了(這從外觀上無法得知,如果沒有儀器,大概只能從有風扇有沒轉來猜測)。

繼續參考Description of how to enable the S3 system power state for standby when USB devices are armed for wake。這篇有提到這是因為早期很多機器並沒有提供正確的\_SxD device Power state, 所以一旦Windows進入S3,USB Host Controller通常又位於南橋,是當S3時會被切掉電源的那一塊,又允許USB裝置喚醒系統,此時很容易出問題,為了避免這問題,所以XP乾脆只要有USB裝置允許喚醒系統,就強置進入S1。如果要讓系統進入S3,請手動更Registry,參照連結文章建立一個USBBIOSx Key,就可以同時讓USB裝置喚醒系統而且進入S3節電模式了。





星期一, 3月 09, 2009

WinIo Library 如何突破2GB限制?

要在Windows下任意存取記憶體如Rw-Everything之類的程式大多需要一個kernel driver來幫你突破Windows的保護機制。其中還是open source我所知就只有WinIo了。

不幸的WinIo Library因為採用memory section object method,如果要mapping的位址位於2GB之後(0x80000000)就會失敗,這時請採用MmMapIoSpace method。詳細請參考How To Map Adapter RAM into Process Address Space

星期二, 8月 19, 2008

Identify USB/IDE/SD Mass Storage Device (Disk Drivers)

Mass Storage Device會被認成是一個Disk,如果要知道這顆Disk是屬於USB或是SATA/IDE Interface,透過標準C Library或是File Management或是Disk Management都無法得知,這些資訊被隱藏起來了。

我寫了一個C++ Class利用Windows Setup API取得系統內有幾個USB Type的Disk。如要判斷是否為Secure Digital或是IDE可自行另行判斷。

massstorage.h

#pragma once

/**
This is the Mass Storage Device Class Library.

Support Help Function to Mass Storage Class.
*/
class CMassStorage
{
public:
CMassStorage(void);
~CMassStorage(void);
/**
Identify a volumn name is exist or not.
\param volname input volumn name
\return true if exist, 0 do not exist.
*/
int isVolumnNameExist(const CString & volname);
/**
Overloaded help function, to supply more argument
\param volman to be identify
\param drv driver letter if the identified voluman exist.
\return true if exist, 0 do not exist.
*/
int isVolumnNameExist(const CString & volname, CString & drv);
int getUSBMsc(void);
};




massstroage.cpp

#include "StdAfx.h"
#include "MassStorage.h"

#include
#include
#include

CMassStorage::CMassStorage(void)
{
}

CMassStorage::~CMassStorage(void)
{
}


int CMassStorage::isVolumnNameExist(const CString & volname)
{
CString dummyDrv;
return isVolumnNameExist(volname, dummyDrv);
}

int CMassStorage::isVolumnNameExist(const CString & volname, CString & drv)
{
TCHAR disk[MAX_PATH]= _T("C:\\");
TCHAR drvltr; // driver letter
TCHAR buf[MAX_PATH];

// scan the disk from C to Z
for (drvltr = 'C'; drvltr <= 'Z'; drvltr++) {
disk[0] = drvltr;
DWORD dummy;
if (GetVolumeInformation(disk, buf, MAX_PATH, &dummy, &dummy, &dummy, NULL, 0)) {
// the driver exist, check the logical volname.
if (volname.CompareNoCase(buf) == 0) {
drv = disk;
return TRUE;
}
}
}
return FALSE;
}

/**
Return the USB mass storage device number
If there are any errors, the returned USB number is still 0.
This function check the device identify if prefixed by "USBSTOR"
\return number of USB mass storage device.
*/

/**
For other GuidClass, search Microsoft for "System-Supplied Device Setup Classes"
*/
DEFINE_GUID(driverGuidConst, 0x4d36e967, 0xe325, 0x11ce, 0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18);


int CMassStorage::getUSBMsc(void)
{
HDEVINFO hdevinfo;
GUID driverGuid = driverGuidConst;
int nousb = 0;
const static WCHAR USB_MASS[]=_T("USBSTORE");

// Get the device setup class handler, for disk driver.
if (INVALID_HANDLE_VALUE != (hdevinfo = SetupDiGetClassDevs(&driverGuid, NULL, NULL, DIGCF_PRESENT ))) {
// Retrieve every instance of this class.
int index = 0;
SP_DEVINFO_DATA data;
data.cbSize = sizeof(SP_DEVINFO_DATA);

while (SetupDiEnumDeviceInfo(hdevinfo, index, &data)) {
ULONG buflen;
// Get the size of device ID buffer.
if (CR_SUCCESS == CM_Get_Device_ID_Size(&buflen, data.DevInst, 0)) {
// if the device is exist, then buflen > 0.
if (buflen > 0) {
WCHAR * buf = new WCHAR[buflen];
CM_Get_Device_ID(data.DevInst, buf, buflen, 0);
if (0 == wcsncmp(USB_MASS, buf, sizeof(USB_MASS)/sizeof(WCHAR))) {
nousb++;
}
delete buf;
}
}
index++;
}
// must free the handle to device information.
SetupDiDestroyDeviceInfoList(hdevinfo);
}

return nousb;
}


星期三, 8月 13, 2008

如何在Blogger裡內嵌程式碼

忘了那裡看到的,原始程式的出處在http://code.google.com/p/google-code-prettify/

使用方法很簡單,可以參考http://google-code-prettify.googlecode.com/svn/trunk/README.html

簡略介紹如下:< >
  1. Download source code, 放在一個固定伺服器,目前我有一個Hinet Myweb 伺服空間,在可預見的未來我大概都不會取消,所以你可以直接使用,位置在http://double.myweb.hinet.net/web/prettify.css and http://double.myweb.hinet.net/web/prettify.js
  2. 在你的Google Template裡,加上


  3. <link href="http://double.myweb.hinet.net/web/prettify.css"
    type="text/css" rel="stylesheet" />
    <script type="text/javascript"
    src="http://double.myweb.hinet.net/web/prettify.js">
    </script>


    在你template裡,尋找<body>,改成

    <body onload="prettyPrint()"> ......</body>


  4. 當要post code時,直接使用以下格式,其中的lang-html可以為lang-cpp, lang-html....等格式。


  5. <pre class="prettyprint lang-html">...</pre>



目前支援的語言格式有"c", "cc", "cpp", "cs", "cyc", "java", "bsh", "csh", "sh", "cv", "py", "perl", "pl", "pm", "rb", "js", "html", "html", "xhtml", "xml", "xsl"。 對我來說已經相當夠用了。

星期一, 6月 23, 2008

nop? 為什麼程式裡有nop?

今天心情不太好,就多寫一些。

常寫Firmware(韌體)的人應該很常看到這個指令。不是以組合語言的指令nop,就是以c函數_nop_()的方式存在。nop望文生義,是no operation的縮寫。可是電腦的存在就是要來計算的,什麼時候要用到nop呢?

第一個情況是用來做短暫的delay,尤於這種delay在不同時脈上很難計算,所以通常適用於短期的等候上,這種情形不在今天的討論內。

我想要提的是,尤於firmware經常要存取硬體暫存器(register),其實通常在先人或前輩的慘痛教訓之後,你會看到如下的程式。

int rega _at_ 0x800; // 這是fixed address hardware register
rega = 0x55;
_nop_();
rega = 0x80;


這程式是要對某個register下一連串的指令,但是為什麼會中間加一段nop?
先人慘痛教訓千萬不能隨意修改,看不懂的code決對不要去動,你如果覺得這段code毫無義意就輕易拿掉你就會發覺原本會跑的程式不會動了。甚至你拿起LA仔細量起timing都不會發覺為什麼有需要在兩行指令內加上delay,硬體的速度並沒有那麼慢,那這是為什麼呢?


rega = 0x55;
rega = 0x80;


大部份的原因是因為compiler是optimize過的,它認為rega一個記憶體變數,你先寫0x55, 下一行指令又直接設成0x80,夠聰明的編譯器就自動省略第一行指令。變成

rega = 0x80;


那當然不會運作,於是工程師就加上nop指令,讓不是那麼聰明的編譯器不要將這行指令優化省略掉。就是你看到的結果。

故事到這裡還沒有結束

對於解決這種問題加上nop並不是正解,那怎麼辦呢?你會碰到的問題聰明的工程師早就有人跟你遇到同樣的問題。C/C++ 為語言設計了volatile modifier。這是修飾data storage的保留字,宣告變數為volatile就是宣稱此變數為揮發性的,也就是它的值是有可能隨外在環境改變,相對一般變數,你只要一存入,不去改它它會一直保持住,這種變數是non-volatile,編譯器可以任意優化不用怕出錯。而針對這種可能會隨著時間變動的register,你可以宣告成volatile,強制編譯器每次看到此變數一定要去做動作,這樣才不會出錯。

所以我們的程式最終的結果變成如此

volatile int rega _at_ 0x800; // 這是fixed address hardware register
rega = 0x55;
rega = 0x80;


volatile modifier不只用在硬體變數,只要有變數在你的thread內執行期間內有可能被改變(或者是被另一個thread),都適用加上這個volatile關鍵字來確保你程式的正確執行。

星期四, 5月 29, 2008

C++ programming language constant type

可以宣告一個data type為constant


const int bufSize = 512;


但是不能宣告一個沒有初始值的const data type,這很合理,因為宣告後就不能再改了。


const int bufSize; //compiler error here


那也不能宣告一個pointer指到const data type, 否則就可以經由pointer 修改constant data type.


const int minSalary; // 什麼都漲,只有薪水是固定的
int * pSalary = &minSalary; // error here.
*pSalary+=100000; // 如果可以的話多好


但是可以宣告一個const pointer type指向data, pointer的值本身可變動,也就是可以指向任何data value,但是你無法經由這個pointer去改變指向的data value, 因為pointer本身是constant type的。


const int * pConstInt; // pointer is constant
pConstInt = minSalary; // OK, can point to a constant value
int maxSalary; // this is not a constant value
pConstInt = &maxSalary; // OK too, can be point to a non-constant value.
*pConstInt += 5000; // 哈哈,不要妄想。你不能從這個pointer去改值。


利用這個特性,const pointer data type所指向的東西無法經由pointer修改。這在C++這種基本上所有的function call都是call by value的方式很好用。有時想要傳一整個structure, 但是又不想函式更改structure裡的內容,這時就可以將pointer 加以const 宣告。


func(const largestruct * pVeryLargeStructure) {
... do something you want here...
... 10000 lines of code below,
... but the sturcture pointed by VeryLargeStructure will not be changed.
}

你可以宣告一個const pointer,pointer本身值不能改變,但是指向的data type可以被改變,我沒有想到什麼時候會用到這樣的特性來解決問題。


int * const ptrNotChanged = &minSalary;
ptrNotChanged = &maxSalary; // error here.


其實寫程式寫了這幾年,雖然使用const這樣的keyword看起來微不足道,但是確可以減少debug的時間,一但養成良好的習慣,在你一開始定義的函數的同時就知道不可能改變傳進去的參數時,就加上const modifier,不但可以防止自己出錯的機會,對於將來自己或是別人來維護你的程式時,更是有很大的幫助。

星期五, 5月 16, 2008

好用的網路備份方式 - Mozy (a EMC company service)

參照我的備份方法 ,這裡的備份主要還是備份到外接式硬碟機。再佐以燒錄成光碟的方式,可是用久了(我一年才備份一次光碟),我光碟還是跑出好多張不曉得怎麼處理的光碟。況且以這樣的方式其實沒有異地備份。萬一出亂子的時候(備份就是要預防出了亂子的時候)還真是麻煩。

EMC是一間非常有名的儲存備份公司,他推出了網路備份的服務,你只要申請一個帳號,它就先給你2GB的網路儲存空間,下載安裝好它的備份程式後,它就默默的在背後幫你備份。不只這樣,這間公司的備份軟體使用介面極佳,很多細節都有考慮到給一般的人使用。


舉例來說,備份不是使用檔案夾的關念來選擇,而是檔案類型。
mozy_backupset

或是平常資料已經整理的很好了,你覺得類型不好用,想用自行檔案的方式來選擇。
mozy_filesystem

至於什麼時候備份的選項也是很聰明,可以自動選擇在電腦不忙的時候自動備份。
mozy_schedule

一旦裝好之後,只要電腦有寛頻,基本就可以不用理會,它會自動備份,完全不用操心。至於復原的方法也很方便從手冊上讀來也是很方便,基本上這是一家備份軟體做的非常好的解決方案,加上有EMC加持,我覺得沒有什麼理由不用,更加上如果你只備份2GB,它還不用錢。

如果你覺得不錯,想要申請,也覺得我這篇介紹不錯,申請帳候麻煩點一下我的連結https://mozy.com/?code=3SDB5A或是在建立帳號時,填入referral(介紹人)3SDB5 這個代號。被介紹人以及介紹人都可以增加250MB的儲存空間。

星期二, 4月 22, 2008

Borland C++ 3.1 link with c startup module and default link library

最近重操舊業,寫起早期的DOS程式,有很多技巧都已經忘光了,所以也吃了不少苦頭。找到原因後,趕緊記錄下來,希望下次再遇到時就不用再摸索一次了。

在IDE的環境,只要將CPP or C 的Source Code加入Prj內,Borland C++會自動將你處理後續的動作。如果要能更有彈性一點,就要自己做了。尤於我要與組合語言撰寫的library連結,所以內建的project management不怎麼適用,所以只好自行撰寫makefile。以command line bcc 先行以 -c 只編譯不 link,最後再一起與assembly object code連結。但是就算只有單純的一個空的main()函式,單純只compiler, link 時仍然需要link C startup module 與run time library。但是怎麼知道startup module 與 run time library 是那一個就有點麻煩了。早期的lanuguage help system 都寫的不太多,總是要猜一下,這樣一猜又猜掉我一天的時間.....

DOS program 有一件事很重要,要注意memory model, 這在32 bit programming 是連聽都沒聽過的事。所以compiler時,就要先指定memory model。以BC++來人說,即是


接下來要Link指明連結link large starup code and run time library, 分別是c0l.obj 與 cl.lib。


其中Link 時切記注意有順序關係的,我因為偷懶,一開始沒有將c0l.obj放在Link裡的第一項,Link雖然沒有錯誤訊息,但是執行是會發生異常現像,為此又搞了一段的時間來解決此問題。

如果不是很確定makefile要怎麼寫,borland++的bin folder內有提供prj2mak.exe 提供將project 檔轉換成makefile。雖然是borland C++ 內附的make utility 在使用的,不過大同小異,參考一下總是有幫助的。

星期五, 1月 25, 2008

ACPI Sleeping State Definitions

ACPI 針對系統、Device等定義了各種不同的Power management。其中對於Sleep State的描述如下。其中Definition的欄位是我從ACPI specification 3.0b裡抄下來的。最右邊的"意思是..."欄位是我的註解。







StateDefinition意思是...
S1The S1 sleeping state is a low wake latency sleeping state. In this state, no system context is lost (CPU or chip set) and hardware maintains all system context.CPU 停止執行,Cache內容已經清掉,但是仍然維持供電,所以CPU的內容仍然都在(register)。
S2The S2 sleeping state is a low wake latency sleeping state. This state is similar to the S1 sleeping state except that the CPU and system cache context is lost (the OS is responsible for maintaining the caches and CPU context). Control starts from the processor’s reset vector after the wake event.CPU暫存器以及Cache的內容會丟失,所以當小睡片刻後,再被人叫醒時,OS需要將之前CPU各個暫存器(也就是程式執行到什麼地方)的內容恢復,然後繼續工作。
S3The S3 sleeping state is a low wake latency sleeping state where all system context is lost except system memory. CPU, cache, and chip set context are lost in this state. Hardware maintains memory context and restores some CPU and L2 configuration context. Control starts from the processor’s reset vector after the wake event.這個階段睡的更死了,CPU的內容不但已經不見了,連南北橋的設定值一併都關閉,週邊幾乎除了只剩下記憶體仍舊持續供電外幾乎全數關閉。所以在被叫醒時,BIOS要負責再重新初始化南北橋晶片組,回復CPU睡著前的狀態。這在Windows叫"待命"(Suspend, Suspend to RAM)
S4The S4 sleeping state is the lowest power, longest wake latency sleeping state supported by ACPI. In order to reduce power to a minimum, it is assumed that the hardware platform has powered off all devices. Platform context is maintained.這是更進階的睡覺模式,基本上跟關機是一樣的狀態。所以的工作狀態全數關閉。記憶體、週邊全數進入關機模式,但是系統的狀態仍然還需要存在。可是既然所有的電都關閉了,那工作狀態要存在什麼地方?當然是Non Volatile Memory,也就是HDD之類不需要供電仍然能儲存資料的儲存設備。這在Windows裡叫"休眠"(Hibernation or Suspend to Disk)。
S5The S5 state is similar to the S4 state except that the OS does not save any context. The system is in the “soft” off state and requires a complete boot when it wakes. Software uses a different state value to distinguish between the S5 state and the S4 state to allow for initial boot operations within the BIOS to distinguish whether or not the boot is going to wake from a saved memory image.這基本上已經是關機了,因為系統沒有儲存跟工作有關的任何資訊,要再重新工作唯有開機一途。

星期二, 12月 04, 2007

整合Jira與Active Directory

Jira 是一個 Project Management, Issue Tracking Software.

要使用這類的Service之前,我一向都很吹毛求疵,一定要與某種的Directory Service作整合,否則新的Service 不斷導入,user 所要記的使用者名稱和密碼越來越多,不但繁雜,而且容易產生安全漏動。

同樣的,介紹Jira與LDAP整合的文章,在Atlassian有專文介紹。可是要使用於Active Direcotry上,參考如何使用LDAP Browser 連上Active Directory Server,一樣要注意active directory credential的問題。在這裡Jira uidSearchName可以使用sAMAccountName,就可以使用與Windows Active Directory 同樣的使用者名稱來登入啦。


如何使用LDAP Browser 連上Active Directory Server

雖然早就知道這是可行的,可是還是試了好久才試出來,趕快做一下筆記。

環境:
Active Directory 為 Windows 2003 Server內建。

下載任一個LDAP client, 在這裡我用的是Softerra LDAP Browswer。其中Base DN為 "DC=a-trust,DC=com,DC=tw",Port Number 為標準的389。

另外,Active Directory預設值不允許Anonymous binding, 也就是無法讓任一人查詢,所以如果要使用一個使用者名稱來登入。這裡的登入要記得要使用Display Name,我就是敗在這裡,一直使用Windows Login name (sAMAccountName) 。換了使用display name之後就可以正確查詢了。

星期日, 12月 10, 2006

我的備份方法

我電腦的資料來說對我可是非常重要的,家裡的電腦存滿了以往的照片,每一張都相當珍貴。公司的筆記型電腦內,也存放了各式各樣以前寫的程式,還有download 下來精彩的圖片....(啊,我在說什麼?)

不論如何,我記得有句話說的不錯,沒有備份的資料就不叫資料。

我為了保存這些重要的資料,特別去買了一個外接式的硬碟盒,裝上160GB的HDD。平當就靜靜的躺在電腦旁,一段時間(可以使用XP內附的排程管理,在附屬應用程式->系統工具->排定的工作來自動執行),我就用同步程式來將工作電腦同步到外接盒的電腦裡。想到時再用燒錄的方式再備份一份光碟拿回老家。這裡有一點要注意,平常沒事是要保持外接硬碟是在離線狀態,否則一旦中毒,會將你的外接硬資料一併破壞。

原先一開始用的同步程式是用公事包,不過用了一段時間後發覺功能有點不足。主要是有錯誤時無法觀察為什麼會產生錯誤,後來找了找,採用Good Sync這套免費的程式,用了一段時間還是覺得沒那麼好用,最近看到Microsoft推出一套Sync Toy。試用了一陣子之後,果然覺得相當好用,除了可以選擇同步的方法,也可以採用不同的方式,例如Echo的方式就是所有Target目標都不管,只要source 有變更就會跟著變更。更重要的是,除了Sync Toy是正版的Microsoft Windows XP就可以下載的之外,其餘的都算是免費的。

星期五, 12月 23, 2005

NSIS, 免費的 Install System

終於找到一個free, 而且還是open source的install System.
可以拿來取代InstallShield了。

NSIS 全名是Nullsoft Scriptable Install System,是一個幫你製做安裝程式的開源軟體。基本上的製作方式是一段script file, 交由NSIS compiler 幫你製成installation executable.

Script file對於software development 當然是重點。
基本上的script file由幾個主要要件組成,包含
  1. Installer Attribute: 這是這個Installer的主要屬性,例如這個installer 是什麼名稱。
  2. Pages: 控制Installer執行時,要顯示幾個頁面,可以做成Install Wizard安裝精靈。
  3. Sections: 區段,script file 至少要含個section, 每一個section就代表一個component, 可以在Component Pages裡被選擇是否要被安裝。UnInstaller 的section會在section name加上"un."的prefix。
  4. Function: 可分為User function 與Callback function。User function就是自行定義的function,寫好後自行呼叫,Callback function是定義好後有特定event可被系統呼叫執行。




底下是因為太久沒用,所以又K了好久的Document所寫基本的功能。可以用來當成Template。

#----------------- Attribute Start ---------------------

Outfile install.exe ; Generated setup file
Name "ProductName" ; Name your module here
InstallDir $PROGRAMFILES\Productname ; The destination folder.

; Request application privileges for Windows Vista
RequestExecutionLevel admin

Page directory
Page instfiles
UninstPage instfiles

#----------------- Section Start ---------------------
Section "Installer Section"
CreateDirectory $INSTDIR
SetOutPath $INSTDIR
File "..\Release\Product.exe" ; The program file you really want to install, use "file" command to install it.
WriteUninstaller $INSTDIR\uninstaller.exe
SectionEnd

; Delete Installed file plus the uninstaller
Delete $INSTDIR\*.exe
RMDir $INSTDIR

#----------------- Function Section Start ---------------------
# Call back function
Function .onInit

# Prevent execute the installer at second time.
# Create MutexA 3rd arguemnt should be changed to a uniquie value
System::Call 'kernel32::CreateMutexA(i 0, i 0, t "Atrust") i .r1 ?e'
Pop $R0

StrCmp $R0 0 +3
MessageBox MB_OK|MB_ICONEXCLAMATION "The installer is already running."
Abort
FunctionEnd





Tag: 介紹, Open Source, Installation System, InstallShield.