




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、重 慶 大 學學 生 實 驗 報 告實驗課程名稱 數據庫原理與設計 開課實驗室 DS1501 學 院 軟件學院 年級 2013級 專業班 學 生 姓 名 學 號 開 課 時 間 至 學年第 1 學期總 成 績教師簽名軟件學院 制 數據庫原理與設計 實驗報告 開課實驗室: 201年 月日學院軟件學院年級、專業、班姓名成績課程名稱數據庫原理與設計實驗項目名 稱數據完整性控制數據安全性控制指導教師一、實驗目的重點掌握如下知識點的相關操作:實驗6、數據完整性控制實驗9、數據庫安全性控制二、實驗環境PC一臺,操作系統為win8.1SQLServer2008 三、實驗內容主要實驗內容如下:實驗6 數據完整
2、性控制 6.1 實體完整性6.2 參照完整性6.3 用戶定義的完整性6.4 觸發器實驗9 數據庫安全性控制9.1 創建登錄賬戶9.2 創建數據庫用戶和角色9.3 權限管理9.4 刪除數據庫用戶和登錄賬戶四、實驗過程原始記錄(對每個實驗內容給出一兩個代表性圖片)實驗六、數據完整性控制 習題1.對Library中的表實現實體完整性并驗證。給各個表設置主鍵 對Book表填加主鍵,輸入T-SQL語句如下: use Library alter table Book add constraint pk_bno primary key(Bno) 執行成功,結果如下: 對Reader表填加主鍵,輸入T-SQL
3、語句如下: use Library alter table Reader add constraint PK_Reader primary key(Rno) 執行成功,結果如下: 對Borrow表填加主鍵,輸入T-SQL語句如下: use library alter table Borrow add constraint ab_Rno primary key(Rno,Bno)給各個表創建UNIQUE約束 在Book表中對書名創建UNIQUE約束,輸入T-SQL語句如下: use Library alter table Book add constraint Book_uni unique(Bt
4、itle) 執行成功,結果如下: 在Reader表中對讀者名創建UNIQUE約束,輸入T-SQL語句如下: use Library alter table Reader add constraint Reader_uni unique(Rname) 執行成功,結果如下: 習題2.實現各個表之間的參照完整性并驗證。 為Borrow表添加外鍵,輸入T-SQL語句如下: use Library alter table Borrow add constraint fk_borrow_book foreign key(bno)references Book (pk_bno) alter table Bo
5、rrow add constraint fk_borrow_reader foreign key(rno)references Reader (Rno) 執行成功,驗證結果如下: 習題3.實現下列約束并驗證。姓名不能為空值。輸入T-SQL語句如下: use Library alter table Reader with checkadd constraint ck_rname check (Rname)is not null) 執行成功,驗證結果如下:試圖向Reader表中插入姓名為空的一行記錄,失敗,結果如圖:性別應該為“男”或“女”。 輸入T-SQL語句如下: use Library al
6、ter table Reader with check add constraint ck_Rsex check (Rsex in (男,女) 執行成功,驗證結果如下: 測試,試圖向Reader中插入性別為“中”的記錄,執行失敗。如圖: 年齡必須在0100之間。 輸入T-SQL語句如下: use Library alter table Reader with checkadd constraint ck_Rage check (Rage0 and Rage0 ) 執行成功,驗證結果如下: 測試,試圖向Book表中插入價格為0的記錄,執行失敗。如圖:借閱日期默認為當前日期。 輸入T-SQL語句如
7、下: use Library alter table Borrow add constraint ck_BorrowDate default(GetDate()for BorrowDate執行成功,驗證結果如下:測試,試圖向Borrow表中插入BorrowDate為NULL的記錄,BorrowDate默認被設置為當前時間。如圖: use Libraryinsert into Borrow values(R06,B06, , )習題4.創建一個觸發器,當刪除Reader 表中讀者信息時,同時刪除Borrow表中該讀者的記錄。 輸入T-SQL語句如下: create trigger trigger
8、_ on Reader instead of delete as delete Borrow where Rno in(select Rno from deleted) 執行成功,驗證結果如下: 測試,在讀者表中刪除R05的信息,經驗證Borrow表中記錄被級聯刪除: 習題5.創建一個表BOOKCount,用來記錄每本書被借閱的次數。創建該表,并向其中加入數據。T-SQL語句如下: use Library create table Book_Count ( Bno char(8) not null primary key, BorrowTimes char(10) insert into Bo
9、ok_Count values (B01,3) insert into Book_Count values (B02,2) insert into Book_Count values (B03,2) insert into Book_Count values (B04,0) insert into Book_Count values (B05,1) insert into Book_Count values (B06,1)創建成功,結果如下: 創建兩個觸發器(BOOK中插入新書時更新Book_Count & Borrow 中插入更新時更新Book_Count),T-SQL語句如下: use L
10、ibrary go create trigger tg_insert on Book for insert as declare Bno1 char(8) select Bno1=pk_bno from inserted insert into Book_Count values(Bno1,0) create trigger tg_count on Borrow for insert as declare Bno char(8) select Bno=Bno from inserted update Book_Count set BorrowTimes=BorrowTimes+1where B
11、no=Bno向Borrow表中再插入3條數據,并查詢Book_Count 表。執行成功,結果如下: use Library insert into Borrow values(R02,B04,) insert into Borrow values(R02,B05,)insert into Borrow values(R02,B06,)向Book表中插入一條新記錄,同時查看Book_Count中是否有更新且初始借閱次數置為0,執行成功,結果如下:實驗九、 數據庫安全性控制習題1.創建一個Windows認證的登錄賬戶newreader,只允許該用戶對數據庫Library查詢添加名為newreade
12、r的新賬戶,并對其授予登錄權限,設置只能對Library進行訪問。 驗證可用WinTest賬戶登錄成功。 創建數據庫用戶newreader: 在對象資源管理器中驗證,已成功創建名為nesreader的用戶: 使用newreader賬戶登錄,可以展開Library數據庫,說明創建用戶成功。 向用戶newreader授予查詢Library數據庫權限: 使用賬戶newreader登錄,驗證可以查詢Library數據庫中內容: 習題2.創建一個Windows認證的登陸賬戶Student,并將其設置為系統管理員賬戶。 習題3.創建SQL Sever 認證的登錄賬戶SQL Teacher,并將其設置允許使
13、用Library進行查詢,對 表Book的列Bauthor 進行插入、修改和刪除操作。 新建查詢輸入T-SQL語句如下: use Library go sp_addlogin SQLTeacher,12345 驗證可以成功登錄。 使用如下T-SQL語句為登陸賬號SQLTeacher創建數據庫用戶: use Library gosp_grantdbaccess SQLTeacher,SQLTeacher執行成功,可以正常展開數據庫,驗證已成功添加用戶SQLTeacher: 對用戶SQLTeacher授予查詢數據庫Library的權限:新建查詢來對BOOK的列執行相應的操作。 本應該是這樣的: u
14、se Library grant insert,update,delete on Book(Bauthor) to SQLTeacher 但我認為不能單獨對表中一列信息執行插入或刪除操作,只能修改其中內容。 而事實證明也確實無法執行: 若只授予更新權限,則順利執行: 執行成功,測試更新操作。 習題4.創建SQL Sever認證的登陸賬戶SQLAdmin,并將其設置為允許使用數據庫Library進行查 詢,對表Reader進行插入、修改和刪除操作。創建SQL Server登陸賬戶并成功登陸:使用如下T-SQL語句為登陸賬號SQLTeacher創建數據庫用戶: use Library gosp_g
15、rantdbaccess SQLAdmin,SQLAdmin執行成功,可以正常展開數據庫,驗證已成功添加用戶SQLTeacher: 對用戶SQLTeacher授予查詢數據庫Library的權限:使用以下T-SQL語句對Reader表授予插入、修改和刪除的操作: use Library go grant insert,update,delete on Readerto SQLAdmin 執行成功,為了驗證,輸入以下T-SQL語句視圖插入一行數據: use Libraryinsert into Reader values(R09,何夕,女,22,研究生)插入成功,查詢結果如下:習題5.創建一個新角
16、色Newstudent,使其具有對數據庫Library進行任何操作的權限,并將上面創 建的用戶全部添加到此角色中。 使用圖形界面為newreader創建新角色Newstudent,并將架構設置為db_owner(可執行數據 庫所有配置和維護活動) 或使用如下T-SQL語句將SQLAdmin和SQLTeacher加入該角色: use Library go sp_addrolemember Newstudent,SQLAdmin use Library go sp_addrolemember Newstudent,SQLTeacher驗證,已成功創建該角色。 出現問題和解決方案(列出遇到的問題和解
17、決方案,列出沒有解決的問題)實驗九中的習題3執行出現問題,描述如下: 新建查詢對BOOK的列執行相應的操作時發生問題: 本應該是這樣的: use Library grant insert,update,delete on Book(Bauthor) to SQLTeacher 但我認為不能單獨對表中一列信息執行插入或刪除操作,只能修改其中內容。 而事實證明也確實無法執行: 若只授予更新權限,則順利執行: 附錄資料:不需要的可以自行刪除C語言中如何獲取時間?精度如何?1 使用time_t time( time_t * timer ) 精確到秒2 使用clock_t clock() 得到的是CPU
18、時間精確到1/CLOCKS_PER_SEC秒3 計算時間差使用double difftime( time_t timer1, time_t timer0 )4 使用DWORD GetTickCount() 精確到毫秒5 如果使用MFC的CTime類,可以用CTime:GetCurrentTime() 精確到秒6 要獲取高精度時間,可以使用BOOL QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency)獲取系統的計數器的頻率BOOL QueryPerformanceCounter(LARGE_INTEGER *lpPerformanceCoun
19、t)獲取計數器的值然后用兩次計數器的差除以Frequency就得到時間。7 Multimedia Timer FunctionsThe following functions are used with multimedia timers.timeBeginPeriod/timeEndPeriod/timeGetDevCaps/timeGetSystemTime/*/用標準C實現獲取當前系統時間的函數一.time()函數time(&rawtime)函數獲取當前時間距1970年1月1日的秒數,以秒計數單位,存于rawtime 中。#include time.hvoid main ()time_t
20、 rawtime;struct tm * timeinfo;time ( &rawtime );timeinfo = localtime ( &rawtime );printf ( 007The current date/time is: %s, asctime (timeinfo) );exit(0);=#include - 必須的時間函數頭文件time_t - 時間類型(time.h 定義是typedef long time_t; 追根溯源,time_t是long)struct tm - 時間結構,time.h 定義如下:int tm_sec;int tm_min;int tm_hour;
21、int tm_mday;int tm_mon;int tm_year;int tm_wday;int tm_yday;int tm_isdst;time ( &rawtime ); - 獲取時間,以秒計,從1970年1月一日起算,存于rawtimelocaltime ( &rawtime ); - 轉為當地時間,tm 時間結構asctime ()- 轉為標準ASCII時間格式:星期 月 日 時:分:秒 年-二.clock()函數,用clock()函數,得到系統啟動以后的毫秒級時間,然后除以CLOCKS_PER_SEC,就可以換成“秒”,標準c函數。clock_t clock ( void );
22、#includeclock_t t = clock();long sec = t / CLOCKS_PER_SEC;他是記錄時鐘周期的,實現看來不會很精確,需要試驗驗證;-三.gettime(&t); 據說tc2.0的time結構含有毫秒信息#include#includeint main(void)struct time t;gettime(&t);printf(The current time is: -:d:d.dn,t.ti_hour, t.ti_min, t.ti_sec, t.ti_hund);return 0;time 是一個結構體, 其中成員函數 ti_hund 是毫秒。-四.
23、GetTickCount(),這個是windows里面常用來計算程序運行時間的函數;DWORD dwStart = GetTickCount();/這里運行你的程序代碼DWORD dwEnd = GetTickCount();則(dwEnd-dwStart)就是你的程序運行時間, 以毫秒為單位這個函數只精確到55ms,1個tick就是55ms。-五.timeGetTime()t,imeGetTime()基本等于GetTickCount(),但是精度更高DWORD dwStart = timeGetTime();/這里運行你的程序代碼DWORD dwEnd = timeGetTime();則(d
24、wEnd-dwStart)就是你的程序運行時間, 以毫秒為單位雖然返回的值單位應該是ms,但傳說精度只有10ms。=/*Unix#unix時間相關,也是標準庫的/*1.timegm函數只是將struct tm結構轉成time_t結構,不使用時區信息;time_t timegm(struct tm *tm);2.mktime使用時區信息time_t mktime(struct tm *tm);timelocal 函數是GNU擴展的與posix函數mktime相當time_t timelocal (struct tm *tm);3.gmtime函數只是將time_t結構轉成struct tm結構,
25、不使用時區信息;struct tm * gmtime(const time_t *clock);4.localtime使用時區信息struct tm * localtime(const time_t *clock);1.time獲取時間,stime設置時間time_t t;t = time(&t);2.stime其參數應該是GMT時間,根據本地時區設置為本地時間;int stime(time_t *tp)3.UTC=true 表示采用夏時制;4.文件的修改時間等信息全部采用GMT時間存放,不同的系統在得到修改時間后通過localtime轉換成本地時間;5.設置時區推薦使用setup來設置;6.
26、設置時區也可以先更變/etc/sysconfig/clock中的設置再將ln -fs /usr/share/zoneinfo/xxxx/xxx /etc/localtime 才能重效time_t只能表示68年的范圍,即mktime只能返回1970-2038這一段范圍的time_t看看你的系統是否有time_t64,它能表示更大的時間范圍/*windows#Window里面的一些不一樣的/*一.CTime () 類VC編程一般使用CTime類 獲得當前日期和時間CTime t = GetCurrentTime();SYSTEMTIME 結構包含毫秒信息typedef struct _SYSTEM
27、TIME WORD wYear;WORD wMonth;WORD wDayOfWeek;WORD wDay;WORD wHour;WORD wMinute;WORD wSecond;WORD wMilliseconds; SYSTEMTIME, *PSYSTEMTIME;SYSTEMTIME t1;GetSystemTime(&t1)CTime curTime(t1);WORD ms = t1.wMilliseconds;SYSTEMTIME sysTm;:GetLocalTime(&sysTm);在time.h中的_strtime() /只能在windows中用char t11;_strti
28、me(t);puts(t);/*獲得當前日期和時間CTime tm=CTime:GetCurrentTime();CString str=tm.Format(%Y-%m-%d);在VC中,我們可以借助CTime時間類,獲取系統當前日期,具體使用方法如下:CTime t = CTime:GetCurrentTime(); /獲取系統日期,存儲在t里面int d=t.GetDay(); /獲得當前日期int y=t.GetYear(); /獲取當前年份int m=t.GetMonth(); /獲取當前月份int h=t.GetHour(); /獲取當前為幾時int mm=t.GetMinute()
29、; /獲取當前分鐘int s=t.GetSecond(); /獲取當前秒int w=t.GetDayOfWeek(); /獲取星期幾,注意1為星期天,7為星期六二.CTimeSpan類如果想計算兩段時間的差值,可以使用CTimeSpan類,具體使用方法如下:CTime t1( 1999, 3, 19, 22, 15, 0 );CTime t = CTime:GetCurrentTime();CTimeSpan span=t-t1; /計算當前系統時間與時間t1的間隔int iDay=span.GetDays(); /獲取這段時間間隔共有多少天int iHour=span.GetTotalHou
30、rs(); /獲取總共有多少小時int iMin=span.GetTotalMinutes();/獲取總共有多少分鐘int iSec=span.GetTotalSeconds();/獲取總共有多少秒-三._timeb()函數_timeb定義在SYSTIMEB.H,有四個fieldsdstflagmillitmtimetimezonevoid _ftime( struct _timeb *timeptr );struct _timeb timebuffer;_ftime( &timebuffer );取當前時間:文檔講可以到ms,有人測試,好象只能到16ms!四.設置計時器定義TIMER ID#
31、define TIMERID_JISUANFANGSHI 2在適當的地方設置時鐘,需要開始其作用的地方;SetTimer(TIMERID_JISUANFANGSHI,200,NULL);在不需要定時器的時候的時候銷毀掉時鐘KillTimer(TIMERID_JISUANFANGSHI);對應VC程序的消息映射void CJisuan:OnTimer(UINT nIDEvent)switch(nIDEvent)-#如何設定當前系統時間-windowsSYSTEMTIME m_myLocalTime,*lpSystemTime;m_myLocalTime.wYear=2003;m_myLocalT
32、ime.wM;m_myLocalTime.wDay=1;m_myLocalTime.wHour=0;m_myLocalTime.wMinute=0;m_myLocalTime.wSec;m_myLocalTime.wMillisec;lpSystemTime=&m_myLocalTime;if( SetLocalTime(lpSystemTime) ) /此處換成 SetSystemTime( )也不行MessageBox(OK !);elseMessageBox(Error !);SYSTEMTIME m_myLocalTime,*lpSystemTime;m_myLocalTime.wYe
33、ar=2003;m_myLocalTime.wM;m_myLocalTime.wDay=1;lpSystemTime=&m_myLocalTime;if( SetDate(lpSystemTime) ) /此處換成 SetSystemTime( )也不行MessageBox(OK !);elseMessageBox(Error !);本文來自CSDN博客,轉載請標明出處:HYPERLINK /khuang2008/archive/2008/12/09/3483274.aspx/khuang2008/archive/2008/12/09/3483274.aspx一種制作微秒級精度定時器的方法當使
34、用定時器時,在很多情況下只用到毫秒級的時間間隔,所以只需用到下面的兩種常用方式就滿足要求了。一是用SetTimer函數建立一個定時器后,在程序中通過處理由定時器發送到線程消息隊列中的WM_TIMER消息,而得到定時的效果(退出程序時別忘了調用和SetTimer配對使用的KillTimer函數)。二是利用GetTickCount函數可以返回自計算機啟動后的時間,通過兩次調用GetTickCount函數,然后控制它們的差值來取得定時效果,此方式跟第一種方式一樣,精度也是毫秒級的。用這兩種方式取得的定時效果雖然在許多場合已經滿足實際的要求,但由于它們的精度只有毫秒級的,而且在要求定時時間間隔小時,實
35、際定時誤差大。下面介紹一種能取得高精度定時的方法。在一些計算機硬件系統中,包含有高精度運行計數器(high-resolution performance counter),利用它可以獲得高精度定時間隔,其精度與CPU的時鐘頻率有關。采用這種方法的步驟如下:1、首先調用QueryPerformanceFrequency函數取得高精度運行計數器的頻率f。單位是每秒多少次(n/s),此數一般很大。2、在需要定時的代碼的兩端分別調用QueryPerformanceCounter以取得高精度運行計數器的數值n1,n2。兩次數值的差值通過f換算成時間間隔,t=(n2-n1)/f。下面舉一個例子來演示這種方
36、法的使用及它的精確度。在VC 6.0 下用MFC建立一個對話框工程,取名為HightTimer.在對話框面板中控件的布局如下圖:其中包含兩個靜態文本框,兩個編輯框和兩個按紐。上面和下面位置的編輯框的ID分別為IDC_E_TEST和IDC_E_ACTUAL,通過MFC ClassWizard添加的成員變量也分別對應為DWORD m_dwTest和DWORD m_dwAct. “退出”按紐的ID為IDOK,“開始測試”按紐ID為IDC_B_TEST,用MFC ClassWizard添加此按紐的單擊消息處理函數如下:void CHightTimerDlg:OnBTest()/ TODO: Add y
37、our control notification handler code hereUpdateData(TRUE); /取輸入的測試時間值到與編輯框相關聯的成員變量m_dwTest中LARGE_INTEGER frequence;if(!QueryPerformanceFrequency( &frequence) /取高精度運行計數器的頻率,若硬件不支持則返回FALSEMessageBox(Your computer hardware doesnt support the high-resolution performance counter,Not Support, MB_ICONEXCL
38、AMATION | MB_OK);LARGE_INTEGER test, ret;test.QuadPart = frequence.QuadPart * m_dwTest / 1000000; /通過頻率換算微秒數到對應的數量(與CPU時鐘有關),1秒=1000000微秒ret = MySleep( test ); /調用此函數開始延時,返回實際花銷的數量m_dwAct = (DWORD)(1000000 * ret.QuadPart / frequence.QuadPart ); /換算到微秒數UpdateData(FALSE); /顯示到對話框面板其中上面調用的MySleep函數如下:L
39、ARGE_INTEGER CHightTimerDlg:MySleep(LARGE_INTEGER Interval)/ 功能:執行實際的延時功能 / 參數:Interval 參數為需要執行的延時與時間有關的數量 / 返回值:返回此函數執行后實際所用的時間有關的數量 / LARGE_INTEGER privious, current, Elapse;QueryPerformanceCounter( &privious );current = privious;while( current.QuadPart - privious.QuadPart Interval.QuadPart )Query
40、PerformanceCounter( t );Elapse.QuadPart = current.QuadPart - privious.QuadPart;return Elapse;注:別忘了在頭文件中為此函數添加函數聲明。至此,可以編譯和執行此工程了,結果如上圖所示。在本人所用的機上(奔騰366, 64M內存)測試,當測試時間超過3微秒時,準確度已經非常高了,此時機器執行本身延時函數代碼的時間對需要延時的時間影響很小了。上面的函數由于演示測試的需要,沒有在函數級封裝,下面給出的函數基本上可以以全局函數的形式照搬到別的程序中。BOOL MySleep(DWORD dwInterval)/
41、功能:執行微秒級的延時功能 / 參數:Interval 參數為需要的延時數(單位:微秒) / 返回值:若計算機硬件不支持此功能,返回FALSE,若函數執行成功,返回TRUE / BOOL bNormal = TRUE;LARGE_INTEGER frequence, privious, current, interval;if(!QueryPerformanceFrequency( &frequence):MessageBox(NULL, Your computer hardware doesnt support the high-resolution performance counter,
42、Not Support, MB_ICONEXCLAMATION | MB_OK); /或其它的提示信息return FALSE;interval.QuadPart = frequence.QuadPart * dwInterval / 1000000;bNormal = bNormal & QueryPerformanceCounter( &privious );current = privious;while( current.QuadPart - privious.QuadPart interval.QuadPart )bNormal = bNormal & QueryPerformanc
43、eCounter( t );return bNormal;需要指出的是,由于在此函數中的代碼很多,機器在執行這些代碼所花費的時間也很長,所以在需要幾個微秒的延時時,會影響精度。實際上,讀者在熟悉這種方法后,只要使用QueryPerformanceFrequency和QueryPerformanceCounter這兩個函數就能按實際需要寫出自己的延時代碼了。使用CPU時間戳進行高精度計時對關注性能的程序開發人員而言,一個好的計時部件既是益友,也是良師。計時器既可以作為程序組件幫助程序員精確的控制程序進程,又是一件有力的調試武器,在有經驗的程序員手里可以盡快的確定程序的性能瓶頸,或者對不同的算法作
44、出有說服力的性能比較。在Windows平臺下,常用的計時器有兩種,一種是timeGetTime多媒體計時器,它可以提供毫秒級的計時。但這個精度對很多應用場合而言還是太粗糙了。另一種是QueryPerformanceCount計數器,隨系統的不同可以提供微秒級的計數。對于實時圖形處理、多媒體數據流處理、或者實時系統構造的程序員,善用QueryPerformanceCount/QueryPerformanceFrequency是一項基本功。本文要介紹的,是另一種直接利用Pentium CPU內部時間戳進行計時的高精度計時手段。以下討論主要得益于Windows圖形編程一書,第15頁17頁,有興趣的讀
45、者可以直接參考該書。關于RDTSC指令的詳細討論,可以參考Intel產品手冊。本文僅僅作拋磚之用。在Intel Pentium以上級別的CPU中,有一個稱為“時間戳(Time Stamp)”的部件,它以64位無符號整型數的格式,記錄了自CPU上電以來所經過的時鐘周期數。由于目前的CPU主頻都非常高,因此這個部件可以達到納秒級的計時精度。這個精確性是上述兩種方法所無法比擬的。在Pentium以上的CPU中,提供了一條機器指令RDTSC(Read Time Stamp Counter)來讀取這個時間戳的數字,并將其保存在EDX:EAX寄存器對中。由于EDX:EAX寄存器對恰好是Win32平臺下C+
46、語言保存函數返回值的寄存器,所以我們可以把這條指令看成是一個普通的函數調用。像這樣:inline unsigned _int64 GetCycleCount() _asm RDTSC 但是不行,因為RDTSC不被C+的內嵌匯編器直接支持,所以我們要用_emit偽指令直接嵌入該指令的機器碼形式0X0F、0X31,如下:inline unsigned _int64 GetCycleCount() _asm _emit 0 x0F _asm _emit 0 x31 以后在需要計數器的場合,可以像使用普通的Win32 API一樣,調用兩次GetCycleCount函數,比較兩個返回值的差,像這樣: u
47、nsigned long t; t = (unsigned long)GetCycleCount(); /Do Something time-intensive . t -= (unsigned long)GetCycleCount(); Windows圖形編程第15頁編寫了一個類,把這個計數器封裝起來。有興趣的讀者可以去參考那個類的代碼。作者為了更精確的定時,做了一點小小的改進,把執行RDTSC指令的時間,通過連續兩次調用GetCycleCount函數計算出來并保存了起來,以后每次計時結束后,都從實際得到的計數中減掉這一小段時間,以得到更準確的計時數字。但我個人覺得這一點點改進意義不大。在我
48、的機器上實測,這條指令大概花掉了幾十到100多個周期,在Celeron 800MHz的機器上,這不過是十分之一微秒的時間。對大多數應用來說,這點時間完全可以忽略不計;而對那些確實要精確到納秒數量級的應用來說,這個補償也過于粗糙了。 這個方法的優點是: 1.高精度。可以直接達到納秒級的計時精度(在1GHz的CPU上每個時鐘周期就是一納秒),這是其他計時方法所難以企及的。 2.成本低。timeGetTime 函數需要鏈接多媒體庫winmm.lib,QueryPerformance* 函數根據MSDN的說明,需要硬件的支持(雖然我還沒有見過不支持的機器)和KERNEL庫的支持,所以二者都只能在Win
49、dows平臺下使用(關于DOS平臺下的高精度計時問題,可以參考圖形程序開發人員指南,里面有關于控制定時器8253的詳細說明)。但RDTSC指令是一條CPU指令,凡是i386平臺下Pentium以上的機器均支持,甚至沒有平臺的限制(我相信i386版本UNIX和Linux下這個方法同樣適用,但沒有條件試驗),而且函數調用的開銷是最小的。 3.具有和CPU主頻直接對應的速率關系。一個計數相當于1/(CPU主頻Hz數)秒,這樣只要知道了CPU的主頻,可以直接計算出時間。這和QueryPerformanceCount不同,后者需要通過QueryPerformanceFrequency獲取當前計數器每秒的計數次數才能換算成時間。 這個方法的缺點是: 1.現有的C/C+編譯器多數不直接支持使用RDTSC指令,需要用直接嵌入機器碼的方式編程,比較麻煩。 2.數據抖動比較厲害。其實對任何計量手段而言,精度和穩定
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
評論
0/150
提交評論