intTypePromotion=1
zunia.vn Tuyển sinh 2024 dành cho Gen-Z zunia.vn zunia.vn
ADSENSE

Bài giảng Lập trình Windows: Phần 2 - Đại học Hàng Hải

Chia sẻ: Ngocnga Ngocnga | Ngày: | Loại File: PDF | Số trang:49

101
lượt xem
5
download
 
  Download Vui lòng tải xuống để xem tài liệu đầy đủ

Bài giảng Lập trình Windows - Phần 2 cung cấp cho sinh viên những kiến thức chủ yếu về: Hệ thống cơ sở dữ liệu Registry, quản lý các tiến trình và luồng, các dịch vụ của Windows, lập trình mạng với Sockets, thư viện liên kết động. Mời các bạn cùng tham khảo để nắm bắt các nội dung chi tiết.

Chủ đề:
Lưu

Nội dung Text: Bài giảng Lập trình Windows: Phần 2 - Đại học Hàng Hải

  1. Bài giảng môn học: Lâ ̣p trin ̀ h Windows Chƣơng 3: Hê ̣thố ng CSDL Registry 1. Khái niệm và vai trò của CSDL Registry 1.1 Các khóa, các hive Registry là nơi lƣu trữ tất cả các các loại cấu trúc dữ liệu. Cấu hình hệ thống Windows, cấu hình phần cứng máy tính, cấu hình thông tin về các chƣơng trình ứng dụng dựa trên Win32, và các thiết lập ngƣời dùng khác đều đƣợc lƣu trong Registry. Ví dụ, bất cứ một phần cứng máy tính nào thay đổi đều làm chức năng Plug and Play (Cắm và chạy) khởi tạo ngay và làm thay đổi luôn cấu hình trong Registry. Registry lƣu trữ tất cả các thiết lập về cấu trúc bộ nhớ, phần cứng, thiết bị ngoại vi, và các thành phần liên quan đến mạng. Bạn sẽ tìm thấy ở đó nhiều hơn những thiết lập cần thiết trong các tệp khởi tạo ban đầu Từ Win98 về sau, Windows có sử dụng Registry Checker để tự quét Registry, nếu không thấy gì, nó tự lƣu backup một lần trong ngày, nếu tìm thấy lỗi sẽ sửa... có thể sửa bằng cách thay thế bản Registry đã backup gần nhất còn tốt. Registry Checker tối ƣu hoá và nén file backup thành công mỗi lần khởi động máy. Nó còn làm một loạt các việc linh tinh nhƣ loại bỏ những khoảng trống không dùng trong Registry, tối ƣu hoá... 41
  2. Bài giảng môn học: Lâ ̣p trin ̀ h Windows Các tệp Registry của Windows. Registry hiện tại bao gồm 3 tệp chính: 1. Tệp USER.DAT Dùng để lƣu trữ những xác lập ngƣời sử dụng đối với các phần mềm. 2. Tệp SYSTEM.DAT Dùng để lƣu trữ những xác lập liên quan tới máy tính và phần cứng. 3. Tệp Policy.pol System policies đƣợc thiết kế để chuẩn bị cho việc ghi đè bất cứ thiết lập đã đƣợc chứa trong 2 thành phần registry khác nhau. System policies có thể chứa dữ liệu bổ sung đặc trƣng tới mạng hay môi trƣờng tổ hợp nhƣ đã đƣợc cài đặt bởi network administrator. Bản thân System policies cũng đã đƣợc chứa trong tệp Policy.pol. Không nhƣ SYSTEM.DAT và USER.DAT, Policy.pol không phải là thành phần bắt buộc của phần cài đặt Windows. Các khóa chính trong một CSDL Registry: + HKEY_LOCAL_MACHINE chứa các thông tin về cấu hình vật lý của hệ thống cùng với các phần mềm đã đƣợc cài đặt trên hệ thống. + HKEY_USERS: chứa các thông tin cấu hình của tài khoản ngƣời dùng + HKEY_CURRENT_CONFIG: chứa các thông tin thiết lập của hệ thống hiện tại chẳng hạn nhƣ độ phân giải màn hình hay font chữ. + HKEY_CLASS_ROOT: chứa các thông tin ánh xạ từ các kiểu file sang các ứng dụng mở chúng. HKEY_CURRENT_USER: chứa các thông tin về các tài khoản trên hệ thống, chẳng hạn nhƣ các biến môi trƣờng, các máy in và các tùy chọn ứng dụng khác. 1.2 Các kiểu dữ liệu Lời khuyên của Microsoft về những công cụ xử lý registry 42
  3. Bài giảng môn học: Lâ ̣p trin ̀ h Windows Phƣơng pháp Thiết lập Phần lớn thiết lập hệ thống SYSTEM. Ví dụ bạn sử dụng Display Control Panel Properties để sửa các thành phần của mục appearance System Policy Editor Thiết lập ngƣời dùng, vài thiết lập hệ thống. Các chƣơng trình tiện ích thứ 3 Thiết lập chi tiết ứng dụng Bạn có thể đã sử dụng Registry Editor để thay đổi Registry bằng tay. Tôi thƣờng dùng Norton Registry Editor vì nó còn có thêm chức năng khác, ví dụ nhƣ tìm và thay thế đối với các thành phần của Registry. Từ các phần mềm Registry Editor trên, ta nhận thấy registry đƣợc bố trí thành các nhánh lớn. Tại mỗi nhánh có các khoá SUBKEY. Tại các SUBKEY dữ liệu đƣợc lƣu ở các dạng: 1. String (Dạng chuỗi) 2. Numeric (Dạng số) 3. Binary (Dạng nhị phân) 4. Expanded String (Dạng chuỗi mở rộng) 5. MultiString (Dạng chuỗi tổng hợp) (Nếu bạn dùng Registry Editor - REGEDIT. EXE thì sẽ gọi tên khác là DWORD) 2. Quản lý CSDL Registry Khi lập trình đối với Registry, bạn phải thực hiện hết sức thận trọng, sao lƣu các tệp này thƣờng xuyên để tránh lỗi đáng tiếc, phải mất công cài lại thì cũng rất mất thời gian.Sử dụng các hàm API đối với Registry cũng xin hết sức thận trọng. 2.1 Thay đổ i khóa Để thay đổi giá trị của một khóa trong CSDL Registry chúng ta sử dụng hàm LONG RegSetValueEx(HKEY hKey, LPCTSTR lpValueName, DWORD reserved, DWORD dwType, CONST BYTE * lpData, CONST cbData). 2.2 Thêm mới khóa Để làm việc với các khóa trong CSDL Registry đầu tiên chúng ta sẽ quan tâm tới các hàm thêm khóa mới: LONG RegOpenKeyEx(HKEY hKey, LPCTSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult). Trong đó tham số thứ nhất là handle trỏ tới khóa đang mở, tham số phkResult trỏ tới một biến có kiểu HKEY cho khóa có thể mớ mới, lpSubKey là tên của subkey mà chúng ta muốn mở, thông thƣờng có thể là một đƣờng dẫn chăng hạn nhƣ “Microsoft\WindowsNT\CurrentVersion”. Giá trị NULL cho biến này có nghĩa là một khóa bằng giá trị hKey sẽ đƣợc sinh ra. Biến ulOptions là biến dự trữ và có giá trị bằng 0. Biến samDesired là mặt nạ truy cập mô tả giá trị bảo mật cho khóa mới, có thể là kết hợp của các giá trị hằng số KEY_ALL_ACCESS, KEY_WRITE, KEY_QUERY_VALUE, KEY_ENUMERATE_SUBKEYS. Giá trị trả về của hàm thƣờng là ERROR_SUCCESS. Cũng có thể dùng hàm LONG RegCreateKeyEx( HKEY hKey, LPCTSTR lpSubKey, DWORD Reserved, LPTSTR lpClass, DWORD dwOptions, REGSAM samDesired, PSECURITY_ATTRIBUTES lpSecurityAttributes, PHKEY phkResult, LPDWORD lpdwDisposition) để tạo khóa mới. 43
  4. Bài giảng môn học: Lâ ̣p trin ̀ h Windows 2.3 Liêṭ kê các khóa Hàm liệt kê các khóa trong CSDL Registry là hàm LONG RegEnumKeyEx(HKEY hKey, DWORD dwIndex, LPTSTR lpName, LPDWORD lpcbName, LPDWORD lpReserved, LPTSTR lpClass, LPDWORD lpcbClass, PFILETIME lpftLastWriteTime). 3. Can thiêp̣ Windows qua Registry Hầu nhƣ tất cả các thay đổi, thiết lập của Windows đều có thể đƣợc thực hiện thông qua việc thiết lập các giá trị trong CSDL Registry, vấn đề cốt lõi là chúng ta cần nắm đƣợc khóa và giá trị cần thay đổi tƣơng ứng. 3.1 Thay đổ i giao diêṇ Để ngăn cấm không cho ngƣời dùng thay đổi Wallpaper chúng ta có thể thay đổi giá trị khóa:“HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows/policies/ActiveDeskto p” với giá trị DWORD là 1. Để chỉ định file Wallpaper của Windows ta có thể sửa các khóa “HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\ System” với các khóa là Wallpaper, WallpaperStyle và giá trị kiểu REG_SZ (String) là đƣờng dẫn tới file ảnh. 3.2 Thay đổ i các thiế t lâ ̣p đố i với các ổ điã Để thay đổi thiết lập với các ổ đĩa ta thực hiện với các khóa HKEY_LOCAL_MACHINE\SYSTEM\MountedDevices có tên là MountedDevices nhƣ hình sau: 3.3 Thay đổ i các thiế t lâ ̣p với ngƣời dùng Các biến môi trƣờng của một ngƣời dùng nằm trong phần “HKEY_CURRENT_USER\Environment”, còn cho cả hệ thống nằm trong phần “HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment”. Bài tập: Bài tập 1: Viết chƣơng trình thay đổi giao diện Windows bằng cách sử dụng can thiệp qua Registry. Bài tập 2: Viết chƣơng trình thay đổi các biến môi trƣờng của Windows bằng cách sử dụng can thiệp qua Registry. 44
  5. Bài giảng môn học: Lâ ̣p trin ̀ h Windows Chƣơng 4: Quản lý các tiế n trin ̀ h và luồ ng 1. Các tiến trình và luồng trên Windows Tất cả các tiến trình (process) của Windows đều có một hoặc nhiều luồng (thread) và luồng chính là đơn vị thực thi cơ sở nhất của Windows. Các luồng đƣợc lập lịch dựa trên các nhân tố: sự sẵn sàng của các tài nguyên nhƣ CPU và bộ nhớ vật lý, độ ƣu tiên. Windows hỗ trợ kiến trúc đa xử lý đối xứng SMP (Symmetric MultiProcessing) bắt đầu từ phiên bản NT4, do đó các luồng có thể chạy trên cac CPU riêng rẽ trong cùng một hệ thống. Trên quan điểm của lập trình viên mỗi tiến trình sẽ bao gồm các tài nguyên: + Một hoặc nhiều luồng + Một không gian bộ nhớ ảo riêng. + Một hoặc nhiều đoạn mã, bao gồm của các đoạn mã trong các file DLL. + Một hoặc nhiều phân đoạn dữ liệu chứa các dữ liệu toàn cục. + Các giá trị biến môi trƣờng + Vùng nhớ Heap + Các tài nguyên khác chẳng hạn nhƣ các handle và các heap đã mở sẵn. Mỗi luồng trong một tiến trình sẽ chia sẻ mã chƣơng trình, các biến toàn cục, các biến môi trƣờng, các tài nguyên. Mỗi luồng sẽ đƣợc lập lịch một cách riêng rẽ và có các thành phần sau: + Một ngăn xếp các lời gọi tới các thủ tục, các ngắt, các quản lý biệt lệ, và bộ nhớ + Một mảng TLS (Threa Local Storage) các con trỏ để có thể cấp phát bộ nhớ lƣu trữ dữ liệu cho luồng. + Một tham số trên stack, từ lúc bắt đầu tạo ra luồng, đƣợc sử dụng riêng cho mỗi luồng. + Một cấu trúc ngữ cảnh, đƣợc quản lý bởi nhân. 45
  6. Bài giảng môn học: Lâ ̣p trin ̀ h Windows 2. Các thao tác với tiến trình 2.1. Tạo tiến trình Hàm cơ bản để quản lý các tiến trình của Windows là hàm CreateProcess(), hàm này tạo ra một tiến trình với một luồng đơn. Tham số mà hàm cần là tên file chƣơng trình sẽ thực hiện. Chúng ta có thể thấy có nhiều đề cập tới khái niệm tiến trình cha, tiến trình con nhƣng thực sự thì quan hệ này không đƣợc quản lý bởi Windows. Windows đơn thuần chỉ tham chiếu tới các tiến trình tại ra một tiến trình con mà nó là tiến trình cha. Hàm CreateProcess() có 10 tham số: BOOL CreateProcess ( LPCTSTR lpApplicationName, LPTSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpsaProcess, LPSECURITY_ATTRIBUTES lpsaThread, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, 46
  7. Bài giảng môn học: Lâ ̣p trin ̀ h Windows LPCTSTR lpCurDir, LPSTARTUPINFO lpStartupInfo, LPPROCESS_INFORMATION lpProcInfo) 2.2. Kế t thúc và thoát khỏi mô ̣t tiế n trin ̀ h Sau khi tiến trình kết thúc, tiến trình, hay chính xác hơn là một luồng chạy trong tiến trình sẽ gọi tới hàm ExitProcess() để kết thúc tiến trình. Hàm này không trả về giá trị mà thay vào đó sẽ kết thúc tất cả các luồng của tiến trình. Hàm có thể gọi tới để lấy mã kết thúc một tiến trình là GetExitCodeProcess(). 2.3. Các thao tác với biến môi trƣờng của Windows Để thao tác với các biến môi trƣờng của Windows ta dùng hai hàm sau: DWORD GetEnvironmentVariable ( LPCTSTR lpName, LPTSTR lpValue, DWORD cchValue) BOOL SetEnvironmentVariable ( LPCTSTR lpName, LPCTSTR lpValue) 2.4. Ví dụ: Ghi nhâ ̣t ký thời gian thƣ ̣c hiêṇ của các tiế n trin ̀ h #include "EvryThng.h" int _tmain (int argc, LPTSTR argv []) { STARTUPINFO StartUp; PROCESS_INFORMATION ProcInfo; union { /* Structure required for file time arithmetic. */ LONGLONG li; FILETIME ft; } CreateTime, ExitTime, ElapsedTime; FILETIME KernelTime, UserTime; SYSTEMTIME ElTiSys, KeTiSys, UsTiSys, StartTimeSys, ExitTimeSys; LPTSTR targv = SkipArg (GetCommandLine ()); OSVERSIONINFO OSVer; BOOL IsNT; HANDLE hProc; OSVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); 47
  8. Bài giảng môn học: Lâ ̣p trin ̀ h Windows GetVersionEx (&OSVer); IsNT = (OSVer.dwPlatformId == VER_PLATFORM_WIN32_NT); /* NT (all versions) returns VER_PLATFORM_WIN32_NT. */ GetStartupInfo (&StartUp); GetSystemTime (&StartTimeSys); /* Execute the command line; wait for process to complete. */ CreateProcess (NULL, targv, NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS, NULL, NULL, &StartUp, &ProcInfo); /* Assure that we have all REQUIRED access to the process. */ DuplicateHandle (GetCurrentProcess (), ProcInfo.hProcess, GetCurrentProcess (), &hProc, PROCESS_QUERY_INFORMATION | SYNCHRONIZE, FALSE, 0); WaitForSingleObject (hProc, INFINITE); GetSystemTime (&ExitTimeSys); if (IsNT) { /* W NT. Elapsed, Kernel, & User times. */ GetProcessTimes (hProc, &CreateTime.ft, &ExitTime.ft, &KernelTime, &UserTime); ElapsedTime.li = ExitTime.li - CreateTime.li; FileTimeToSystemTime (&ElapsedTime.ft, &ElTiSys); FileTimeToSystemTime (&KernelTime, &KeTiSys); FileTimeToSystemTime (&UserTime, &UsTiSys); _tprintf (_T ("Real Time: %02d:%02d:%02d:%03d\n"), ElTiSys.wHour, ElTiSys.wMinute, ElTiSys.wSecond, ElTiSys.wMilliseconds); _tprintf (_T ("User Time: %02d:%02d:%02d:%03d\n"), UsTiSys.wHour, UsTiSys.wMinute, UsTiSys.wSecond, UsTiSys.wMilliseconds); _tprintf (_T ("Sys Time: %02d:%02d:%02d:%03d\n"), KeTiSys.wHour, KeTiSys.wMinute, KeTiSys.wSecond, KeTiSys.wMilliseconds); } else { 48
  9. Bài giảng môn học: Lâ ̣p trin ̀ h Windows /* Windows 9x and CE. Elapsed time only. */ ... } CloseHandle (ProcInfo.hThread); CloseHandle (ProcInfo.hProcess); CloseHandle (hProc); return 0; } 3. Quản lý luồng (thread) trên Windows 3.1. Các khái niệm cơ bản Trong phần trƣớc chúng ta đã xem xét cách thức một luồng thực hiện kết thúc một tiến trình. Các luồng trong một tiến trình chia sẻ chung dữ liệu và mã lệnh, vì thế về bản chất các luồng đó cũng có vùng nhớ riêng của chúng. Windows đáp ứng điều này bằng một số cách sau: + Mỗi luồng có một stack của riêng nó cho các lời gọi hàm và các xử lý khác + Lời gọi tiến trình có thể truyền một biến, con trò, tới thời gian tạo ra luồng. + Mỗi luồng có thể cấp phát TLS của riêng nó. 3.2. Mô hin ̀ h Boss/Worker và các mô hin ̀ h khác Lệnh grepMT minh họa cho mô hình Boss/Worker. Luồng boss (luồng chính) sẽ gán các tác vụ cho luồng worker để thực hiện. Mỗi luồng worker sẽ đƣợc cho một file để tìm kiếm và worker sẽ trả về giá trị của nó cho boss thread. Xem thêm ví dụ sắp xếp trộn để hiểu rõ mô hình này. 3.3. Bô ̣ nhớ dành cho luồ ng Các luồng có thể cần phải cấp phát và quản lý bộ nhớ của riêng nó và bảo vệ các vùng nhớ đó khỏi các luồng khác. Điều này đƣợc thực hiện qua các TLS, có thể minh họa bằng hình vẽ sau: 49
  10. Bài giảng môn học: Lâ ̣p trin ̀ h Windows 3.4. Độ ƣu tiên và các trạng thái của luồng Các luồng thuộc về nhân của Windows luôn có độ ƣu tiên cao nhất khi sẵn sàng để thực hiện. Một luồng đƣợc coi là không sẵn sàng để thực hiện nếu nó ở trạng thái chờ, treo, hay bị block bởi một lý do nào đó. 4. Mô ̣t số ví du ̣ về tiế n trin ̀ h và luồ ng 4.1. Tìm kiếm song song với các tiến trình #include "EvryThng.h" int _tmain (DWORD argc, LPTSTR argv []) /* Create a separate process to search each file on the command line. Each process is given a temporary file, in the current directory, to receive the results. */ { HANDLE hTempFile; SECURITY_ATTRIBUTES StdOutSA = /* SA for inheritable handle. */ {sizeof (SECURITY_ATTRIBUTES), NULL, TRUE}; TCHAR CommandLine [MAX_PATH + 100]; STARTUPINFO StartUpSearch, StartUp; PROCESS_INFORMATION ProcessInfo; DWORD iProc, ExCode; HANDLE *hProc; /* Pointer to an array of proc handles. */ typedef struct {TCHAR TempFile [MAX_PATH];} PROCFILE; PROCFILE *ProcFile; /* Pointer to array of temp file names. */ GetStartupInfo (&StartUpSearch); GetStartupInfo (&StartUp); ProcFile = malloc ((argc - 2) * sizeof (PROCFILE)); hProc = malloc ((argc - 2) * sizeof (HANDLE)); /* Create a separate "grep" process for each file. */ for (iProc = 0; iProc < argc - 2; iProc++) { _stprintf (CommandLine, _T ("%s%s %s"), _T ("grep "), argv [1], argv [iProc + 2]); GetTempFileName (_T ("."), _T ("gtm"), 0, ProcFile [iProc].TempFile); /* For search results. */ hTempFile = /* This handle is inheritable */ 50
  11. Bài giảng môn học: Lâ ̣p trin ̀ h Windows CreateFile (ProcFile [iProc].TempFile, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, &StdOutSA, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); StartUpSearch.dwFlags = STARTF_USESTDHANDLES; StartUpSearch.hStdOutput = hTempFile; StartUpSearch.hStdError = hTempFile; StartUpSearch.hStdInput = GetStdHandle (STD_INPUT_HANDLE); /* Create a process to execute the command line. */ CreateProcess (NULL, CommandLine, NULL, NULL, TRUE, 0, NULL, NULL, &StartUpSearch, &ProcessInfo); /* Close unwanted handles. */ CloseHandle (hTempFile); CloseHandle (ProcessInfo.hThread); hProc [iProc] = ProcessInfo.hProcess; } /* Processes are all running. Wait for them to complete. */ for (iProc = 0; iProc < argc - 2; iProc += MAXIMUM_WAIT_OBJECTS) WaitForMultipleObjects ( /* Allows a large # of processes */ min (MAXIMUM_WAIT_OBJECTS, argc - 2 - iProc), &hProc [iProc], TRUE, INFINITE); /* Result files sent to std output using "cat." */ for (iProc = 0; iProc < argc - 2; iProc++) { if (GetExitCodeProcess(hProc [iProc], &ExCode) && ExCode==0) { /* Pattern was detected -- List results. */ if (argc > 3) _tprintf (_T ("%s:\n"), argv [iProc + 2]); fflush (stdout); /* Multiple processes use stdout. */ _stprintf (CommandLine, _T ("%s%s"), _T ("cat "), ProcFile [iProc].TempFile); CreateProcess (NULL, CommandLine, NULL, NULL, TRUE, 0, NULL, NULL, &StartUp, &ProcessInfo); WaitForSingleObject (ProcessInfo.hProcess, INFINITE); CloseHandle (ProcessInfo.hProcess); 51
  12. Bài giảng môn học: Lâ ̣p trin ̀ h Windows CloseHandle (ProcessInfo.hThread); } CloseHandle (hProc [iProc]); DeleteFile (ProcFile [iProc].TempFile); } free (ProcFile); free (hProc); return 0; } 4.2. Thuâ ̣t toán sắ p xế p trô ̣n bằ ng đa luồ ng #include "EvryThng.h" #define DATALEN 56 /* Key: 8 bytes; Data: 56 bytes. */ #define KEYLEN 8 typedef struct _RECORD { CHAR Key [KEYLEN]; TCHAR Data [DATALEN]; } RECORD; #define RECSIZE sizeof (RECORD) typedef RECORD * LPRECORD; typedef struct _THREADARG { /* Thread argument */ DWORD iTh; /* Thread number: 0, 1, 2, ... */ LPRECORD LowRec; /* Low record */ LPRECORD HighRec; /* High record */ } THREADARG, *PTHREADARG; static int KeyCompare (LPCTSTR, LPCTSTR); static DWORD WINAPI ThSort (PTHREADARG pThArg); static DWORD nRec; /* Total number of records to be sorted. */ static HANDLE * ThreadHandle; int _tmain (int argc, LPTSTR argv []) { HANDLE hFile; LPRECORD pRecords = NULL; 52
  13. Bài giảng môn học: Lâ ̣p trin ̀ h Windows DWORD FsLow, nRead, LowRecNo, nRecTh, NPr, ThId, iTh; BOOL NoPrint; int iFF, iNP; PTHREADARG ThArg; LPTSTR StringEnd; iNP = Options (argc, argv, _T ("n"), &NoPrint, NULL); iFF = iNP + 1; NPr = _ttoi (argv [iNP]); /* Number of threads. */ hFile = CreateFile (argv [iFF], GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); FsLow = GetFileSize (hFile, NULL); nRec = FsLow / RECSIZE; /* Total number of records. */ nRecTh = nRec / NPr; /* Records per thread. */ /* Allocate thread args and handle array and space for the file. Read the complete file. */ ThArg = malloc (NPr * sizeof (THREADARG)); /* Thread args. */ ThreadHandle = malloc (NPr * sizeof (HANDLE)); pRecords = malloc (FsLow + sizeof (TCHAR)); ReadFile (hFile, pRecords, FsLow, &nRead, NULL); CloseHandle (hFile); LowRecNo = 0; /* Create the sorting threads. */ for (iTh = 0; iTh < NPr; iTh++) { ThArg [iTh].iTh = iTh; ThArg [iTh].LowRec = pRecords + LowRecNo; ThArg [iTh].HighRec = pRecords + (LowRecNo + nRecTh); LowRecNo += nRecTh; ThreadHandle [iTh] = (HANDLE) _beginthreadex (NULL, 0, ThSort, &ThArg [iTh], CREATE_SUSPENDED, &ThId); } 53
  14. Bài giảng môn học: Lâ ̣p trin ̀ h Windows for (iTh = 0; iTh < NPr; iTh++) /* Run all sort threads. */ ResumeThread (ThreadHandle [iTh]); WaitForSingleObject (ThreadHandle [0], INFINITE); for (iTh = 0; iTh < NPr; iTh++) CloseHandle (ThreadHandle [iTh]); StringEnd = (LPTSTR) pRecords + FsLow; *StringEnd = '\0'; if (!NoPrint) printf ("\n%s", (LPCTSTR) pRecords); free (pRecords); free (ThArg); free (ThreadHandle); return 0; } /* End of _tmain. */ static VOID MergeArrays (LPRECORD, LPRECORD); DWORD WINAPI ThSort (PTHREADARG pThArg) { DWORD GrpSize = 2, RecsInGrp, MyNumber, TwoToI = 1; LPRECORD First; MyNumber = pThArg->iTh; First = pThArg->LowRec; RecsInGrp = pThArg->HighRec - First; qsort (First, RecsInGrp, RECSIZE, KeyCompare); while ((MyNumber % GrpSize) == 0 && RecsInGrp < nRec) { /* Merge with the adjacent sorted array. */ WaitForSingleObject ( ThreadHandle [MyNumber + TwoToI], INFINITE); MergeArrays (First, First + RecsInGrp); RecsInGrp *= 2; GrpSize *= 2; TwoToI *= 2; } _endthreadex (0); 54
  15. Bài giảng môn học: Lâ ̣p trin ̀ h Windows return 0; /* Suppress a warning message. */ } static VOID MergeArrays (LPRECORD p1, LPRECORD p2) { DWORD iRec = 0, nRecs, i1 = 0, i2 = 0; LPRECORD pDest, p1Hold, pDestHold; nRecs = p2 - p1; pDest = pDestHold = malloc (2 * nRecs * RECSIZE); p1Hold = p1; while (i1 < nRecs && i2 < nRecs) { if (KeyCompare ((LPCTSTR) p1, (LPCTSTR) p2) = nRecs) memcpy (pDest, p2, RECSIZE * (nRecs - i2)); else memcpy (pDest, p1, RECSIZE * (nRecs - i1)); memcpy (p1Hold, pDestHold, 2 * nRecs * RECSIZE); free (pDestHold); return; } Bài tập: Bài tập 1: Viết chƣơng trình hiển thị tất cả các thông tin về tiến trình và luồng của một tiến trình đang chạy. 55
  16. Bài giảng môn học: Lâ ̣p trin ̀ h Windows Chƣơng 5: Các dịch vụ của Windows 1. Tổ ng quan về dich ̣ vu ̣ trên Windows Các dịch vụ của Windows, ban đầu đƣợc gọi là các dịch vụ NT, cung cấp khả năng quản lý đòi hỏi các chƣơng trình theo kiểu server phải đƣợc chạy trên dòng lệnh, hoặc vào thời điểm hệ thống khởi động, trƣớc khi bất cứ ngƣời dùng nào đăng nhập, và cũng có thể thực hiện tạm dừng, khôi phục, kết thúc. Các dịch vụ đƣợc đƣa ra nhằm đáp ứng yêu cầu này. Để quản lý các dịch vụ chúng ta có thể dùng công cụ Service Control Manager đƣợ cung cấp sẵn bởi Windows, công cụ này sẽ thực hiện ba bƣớc để quản lý một dịch vụ: + Gọi tới hàm main() của dịch vụ + Chuyển đổi từ hàm main() sang hàm ServiceMain() + Ghi các con trỏ quản lý để có thể đáp ứng lại các lệnh từ SCM 2. Các thành phần của một dịch vụ 2.1 Hàm main() Hàm này đƣợc gọi bởi SCM, có nhiệm vụ là khai báo dịch vụ với SCM và bắt đầu thực hiện công việc của một dịch vụ. 2.2 Hàm ServiceMain() Hàm ServiceMain() là một dạng tƣơng tự nhƣ hàm main() với các tham số tƣơng tự, nó thực hiện các tác vụ chính của một dịch vụ. 2.3 Kiể m soát dich ̣ vu ̣ qua các Handler Để kiểm soát dịch vụ, chúng ta sử dụng các hàm sau: DWORD WINAPI HandlerEx ( DWORD dwControl, DWORD dwEventType, 56
  17. Bài giảng môn học: Lâ ̣p trin ̀ h Windows LPVOID lpEventData, LPVOID lpContext) 3. Ví du: dịch vụ đơn giản trên Windows #include "EvryThng.h" #include "ClntSrvr.h" #define UPDATE_TIME 1000 /* One second between updates. */ VOID LogEvent (LPCTSTR, DWORD, BOOL); void WINAPI ServiceMain (DWORD argc, LPTSTR argv []); VOID WINAPI ServerCtrlHandlerEx(DWORD, DWORD, LPVOID, LPVOID); void UpdateStatus (int, int); /* Calls SetServiceStatus. */ int ServiceSpecific (int, LPTSTR *); /* Former main program. */ volatile static BOOL ShutDown = FALSE, PauseFlag = FALSE; static SERVICE_STATUS hServStatus; static SERVICE_STATUS_HANDLE hSStat; /* Handle to set status. */ static LPTSTR ServiceName = _T ("SocketCommandLineService"); static LPTSTR LogFileName = _T ("CommandLineServiceLog.txt"); /* Main routine that starts the service control dispatcher. */ VOID _tmain (int argc, LPTSTR argv []) { SERVICE_TABLE_ENTRY DispatchTable [] = { { ServiceName, ServiceMain }, { NULL, NULL } }; StartServiceCtrlDispatcher (DispatchTable); return 0; } /* ServiceMain entry point, called when the service is created. */ void WINAPI ServiceMain (DWORD argc, LPTSTR argv []) 57
  18. Bài giảng môn học: Lâ ̣p trin ̀ h Windows { DWORD i, Context = 1; /* Set the current directory and open a log file, appending to an existing file. */ /* Set all server status data members. */ hServStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; hServStatus.dwCurrentState = SERVICE_START_PENDING; hServStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_PAUSE_CONTINUE; hServStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIF0C_ERROR; hServStatus.dwServiceSpecificExitCode = 0; hServStatus.dwCheckPoint = 0; hServStatus.dwWaitHint = 2 * CS_TIMEOUT; hSStat = RegisterServiceCtrlHandlerEx (ServiceName, ServerCtrlHandler, &Context); SetServiceStatus (hSStat, &hServStatus); /* Start service-specific work; generic work is complete. */ if (ServiceSpecific (argc, argv) != 0) { hServStatus.dwCurrentState = SERVICE_STOPPED; hServStatus.dwServiceSpecificExitCode = 1; /* Server initialization failed. */ SetServiceStatus (hSStat, &hServStatus); return; } /* We will only return here when the ServiceSpecific function completes, indicating system shutdown. */ UpdateStatus (SERVICE_STOPPED, 0); return; } 58
  19. Bài giảng môn học: Lâ ̣p trin ̀ h Windows void UpdateStatus (int NewStatus, int Check) /* Set a new service status and checkpoint -- either specific value or increment. */ { if (Check < 0) hServStatus.dwCheckPoint++; else hServStatus.dwCheckPoint = Check; if (NewStatus >= 0) hServStatus.dwCurrentState = NewStatus; SetServiceStatus (hSStat, &hServStatus); return; } /* Control handler function, invoked by the SCM to run */ /* in the same thread as the main program. */ /* The last three parameters are not used, and the pre-NT5 */ /* handlers would also work in this example. */ VOID WINAPI ServerCtrlHandlerEx (DWORD Control, DWORD EventType, LPVOID lpEventData, LPVOID lpContext) { swsitch (Control) { case SERVICE_CONTROL_SHUTDOWN: case SERVICE_CONTROL_STOP: ShutDown = TRUE; /* Set the global shutdown flag. */ UpdateStatus (SERVICE_STOP_PENDING, -1); break; case SERVICE_CONTROL_PAUSE: PauseFlag = TRUE; /* Interrogated periodically. */ break; case SERVICE_CONTROL_CONTINUE: PauseFlag = FALSE; break; case SERVICE_CONTROL_INTERROGATE: break; default: if (Control > 127 && Control < 256) /* User defined. */ 59
  20. Bài giảng môn học: Lâ ̣p trin ̀ h Windows break; } UpdateStatus (-1, -1); /* Increment checkpoint. */ return; } /* This is the service-specific function, or "main," and is called from the more generic ServiceMain. In general, you can take any server, such as ServerNP.c, and rename "main" as "ServiceSpecific"; putting code right here. But some changes are required to update status. */ int ServiceSpecific (int argc, LPTSTR argv []) { UpdateStatus (-1, -1); /* Increment the checkpoint. */ /* ... Initialize system ... */ /* Be sure to update the checkpoint periodically. */ return 0; } 4. Quản lý các dịch vụ của Windows 4.1 Các phƣơng pháp kiểm soát các dịch vụ của Windows Để quản lý các dịch vụ của Windows ta có hai cách: một là dùng công cụ SCM, hai là gõ trực tiếp các lệnh trên dòng lệnh. 4.2 Ví dụ : Điề u khiể n các dich ̣ vu ̣ của Windows #include "EvryThng.h" static SC_HANDLE hScm; static BOOL Debug; int _tmain (int argc, LPTSTR argv []) { BOOL Exit = FALSE; TCHAR Command [MAX_COMMAND_LINE + 10], *pc; 60
ADSENSE

CÓ THỂ BẠN MUỐN DOWNLOAD

 

Đồng bộ tài khoản
2=>2