Udostępnij przez


Zwalnianie dostawcy

WMI zwalnia dostawcę z pamięci po zakończeniu pracy z nim. Podstawowym powodem, dla którego WMI zwalnia dostawcę, jest oszczędzanie zasobów systemowych. W związku z tym należy dodać kod, który umożliwia WMI odciążanie dostawcy w wydajny sposób. Trwa to w dowolnym miejscu od interwału określonego w kontrolce pamięci podręcznej do dwukrotnego tego interwału, aby usługa WMI zwolniła dostawcę.

Usługa WMI zwalnia dostawcę w jeden z następujących sposobów:

  • Zwolnij dostawcę po zakończeniu zadań nadanych mu do wykonania.
  • Szybko zwolnij wszystkich dostawców, gdy użytkownik zamknie system. Należy pamiętać, że WMI rozładowuje dostawców działających w procesie, gdy usługa WMI jest zamykana z wiersza polecenia.

Chociaż pierwszy scenariusz jest bardziej typowy, musisz napisać dostawcę, aby uzyskać obie możliwości.

W tym temacie omówiono następujące sekcje:

Rozładowanie nieaktywnego dostawcy

Usługa WMI wykonuje następujące akcje, gdy zwalnia nieaktywnego dostawcę:

  • Określa, czy dostawca jest bezczynny.

    Usługa WMI używa właściwości ClearAfter, aby określić, jak długo dostawca może pozostać bezczynny, zanim zostanie zwolniony. Aby uzyskać więcej informacji, zobacz Uzyskiwanie dostępu do czasu bezczynności dostawcy.

  • Wywołuje metodęreleasedostawcy.

    Jeśli dostawca był czystym dostawcą, Release całkowicie usuwa dostawcę z pamięci operacyjnej. Jednak dostawca nieczysty może nadal działać po wywołaniach WMI Release.

Uzyskiwanie dostępu do czasu bezczynności dostawcy

Minimalny czas, przez jaki dostawca pozostaje aktywny, jest określany przez właściwość ClearAfter. ClearAfter można znaleźć w wystąpieniach klas pochodnych z klasy systemu WMI __CacheControl w przestrzeni nazw \root.

Na poniższej liście opisano klasy pochodzące z __CacheControl, które sterują zwalnianiem dostawcy:

Możesz zmienić minimalny czas bezczynności dostawcy, który usługa WMI dopuszcza, edytując właściwość ClearAfter w instancji kontroli pamięci podręcznej dla określonego typu dostawcy. Aby na przykład ograniczyć czas, przez jaki dostawca właściwości może pozostać bezczynny, należy edytować właściwość ClearAfter wystąpienia __PropertyProviderCacheControl w przestrzeni nazw \root.

Zwalnianie dostawcy, który jest również klientem WMI

Dostawca może potrzebować pozostać klientem WMI po ukończeniu funkcji dostawcy, do których został wezwany. Na przykład dostawca push może wymagać wysyłania zapytań do usługi WMI. Aby uzyskać więcej informacji, zobacz Określanie stanu wypychania lub ściągania. W takim przypadku właściwość Pure wystąpienia __Win32Provider, które reprezentuje dostawcę, powinna być ustawiona na wartość true. Jeśli właściwość Pure jest ustawiona na wartość FALSE, dostawca przygotowuje się do zwolnienia, wywołując IUnknown::Release na wszystkich nierozliczonych punktach interfejsu, gdy WMI wywołuje metodę Release swojego interfejsu podstawowego. Aby uzyskać więcej informacji, zobacz sekcję Uwagi w __Win32Provider.

Poniższa procedura opisuje sposób implementowania metody wydania dla podstawowego interfejsu dostawcy.

Aby zwolnić dostawcę

  1. Zwolnij wszystkie wskaźniki interfejsu przechowywane względem usługi WMI, gdy usługa WMI wywołuje metodę Release podstawowego interfejsu dostawcy.

    Zazwyczaj dostawca przechowuje wskaźniki do IWbemServices i IWbemContext interfejsów dostarczonych w IWbemProviderInit::Initialize.

  2. Jeśli właściwość Pure w skojarzonym wystąpieniu __Win32Provider jest ustawiona na wartość FALSE, dostawca może przejść do roli aplikacji klienckiej po wywołaniu przez WMI Release. Jednak usługa WMI nie może zwolnić dostawcy, który działa jako system kliencki, co zwiększa obciążenie systemu.

    Dostawca z Pure ustawiony na TRUE istnieje tylko do żądań obsługi. W związku z tym ten typ dostawcy nie może przejąć roli aplikacji klienckiej, a usługa WMI może go odciążyć.

Zwalnianie dostawcy podczas zamykania

W normalnych okolicznościach stosowanie się do wytycznych w usuwanie dostawcy będącego również klientem WMI umożliwia usłudze WMI prawidłowe usunięcie dostawcy. Mogą jednak wystąpić sytuacje, w których usługa WMI nie może zainicjować normalnych procedur zwalniania, takich jak wtedy, gdy użytkownik zdecyduje się zamknąć system. Korzystając z modelu transakcji magazynu danych, oprócz zaimplementowania dobrej strategii oczyszczania, możesz upewnić się, że dostawca jest prawidłowo zwolniony.

Użytkownik może w dowolnym momencie zatrzymać usługę WMI. W takiej sytuacji usługa WMI nie zwalnia żadnych dostawców ani nie wywołuje DllCanUnloadNow punktu wejścia dla dowolnego dostawcy w procesie. Ponadto jeśli dostawca w procesie znajduje się w trakcie wywołania metody w momencie zamknięcia, usługa WMI może zakończyć wykonywanie wątku w środku wywołania. W tej sytuacji usługa WMI nie wywołuje procedur, które zwykle zarządzają oczyszczaniem, takich jak destruktor obiektów. Co najwyżej WMI wywoła tylko DllMain.

Po zamknięciu usługi WMI system operacyjny automatycznie zwalnia całą pamięć przydzieloną do dostawcy procesów. System operacyjny zamyka również większość zasobów utrzymywanych przez dostawcę, takich jak uchwyty plików, uchwyty okien itd. Dostawca nie musi podejmować żadnych konkretnych działań, aby to się stało.

Ponieważ usługa WMI może zostać wyłączona w środku wywołania, dostawca nie powinien pozostawiać źródeł danych w niespójnym stanie. Pozostawienie danych w niespójnym stanie nie jest problemem dla dostawców danych tylko do odczytu. Jednak dostawcy z funkcjami zapisu mogą chcieć zaimplementować jakiś model transakcji, aby umożliwić bezpieczne wycofywanie po nagłym zakończeniu.

Mimo że system operacyjny może zwolnić niektóre ogólne zasoby systemowe, system nie zwalnia automatycznie wszystkich zasobów. Na przykład system operacyjny może nie zwolnić gniazda lub połączenia z bazą danych. Zamiast tego dostawca może wymagać ręcznego wyczyszczenia takich zasobów. Aby uniknąć tych problemów, możesz zaimplementować dostawcę poza procesem lub dodać kod oczyszczania.

Najprostszym rozwiązaniem jest zaimplementowanie dostawcy usług poza procesem. Dostawca out-of-process nie jest zabity, gdy usługa WMI zostanie zamknięta, chociaż usługa WMI zwolni dostawcę po przekroczeniu limitu czasu com. Dostawcy, dla których niezawodność czyszczenia i zakończenia procesów jest ważniejsza niż wydajność, mogą działać poza głównym procesem.

Jeśli musisz umieścić kod oczyszczania u dostawcy, masz dwie opcje. Jednym z miejsc, w których można wykonać tego rodzaju oczyszczanie, jest DllMain, funkcja punktu wejścia do biblioteki DLL, którą wywołuje system operacyjny podczas zwalniania biblioteki DLL. Kod oczyszczania można dodać bezpośrednio do DllMain, wykonując go jako reakcja na DLL_PROCESS_DETACH. Implementowanie kodu oczyszczania w DllMain może być dość trudne do wykonania, szczególnie w środowiskach programowania, takich jak MFC lub ATL. Aby uzyskać więcej informacji, zobacz artykuł z bazy wiedzy Microsoft Knowledge Base Q148791, "Jak zapewnić własną funkcję DllMain w standardowej bibliotece DLL MFC." (Ten zasób może nie być dostępny w niektórych językach i regionach).

Alternatywnie można również umieścić kod oczyszczania w destruktorze klasy globalnej. Aby uzyskać więcej informacji, zobacz Zwalnianie dostawcy. System operacyjny Windows nie przydziela obiektów globalnych na stercie. Zamiast tego system operacyjny wywołuje destruktory podczas zwalniania bibliotek DLL.

Poniżej przedstawiono prostą procedurę oczyszczania, która może mieścić się wewnątrz obiektu globalnego dla usługi WMI.

class CMyCleanup
{
    ~CMyCleanup()
    {
        CloseHandle(m_hOpenFile);
        CloseDatabaseConnection(g_hDatabase);
    }
} g_Cleanup;

Istnieje wiele ograniczeń co do tego, co można zrobić w kodzie oczyszczania przy użyciu dowolnego podejścia. Na przykład żadne wątki ani biblioteki DLL, które nie są niejawnie połączone, nie mogą być w żaden sposób dostępne. Ponadto nie można wykonywać wywołań COM w żadnych okolicznościach.

konfigurowanie deskryptorów zabezpieczeń przestrzeni nazw

Zabezpieczanie Dostawcy Usług

Tworzenie dostawcy WMI