Windows one time initialization

Using One-Time Initialization

The following examples demonstrate the use of the one-time initialization functions.

Synchronous Example

In this example, the g_InitOnce global variable is the one-time initialization structure. It is initialized statically using INIT_ONCE_STATIC_INIT.

The OpenEventHandleSync function returns a handle to an event that is created only once. It calls the InitOnceExecuteOnce function to execute the initialization code contained in the InitHandleFunction callback function. If the callback function succeeds, OpenEventHandleSync returns the event handle returned in lpContext; otherwise, it returns INVALID_HANDLE_VALUE.

The InitHandleFunction function is the one-time initialization callback function. InitHandleFunction calls the CreateEvent function to create the event and returns the event handle in the lpContext parameter.

Asynchronous Example

In this example, the g_InitOnce global variable is the one-time initialization structure. It is initialized statically using INIT_ONCE_STATIC_INIT.

The OpenEventHandleAsync function returns a handle to an event that is created only once. OpenEventHandleAsync calls the InitOnceBeginInitialize function to enter the initializing state.

If the call succeeds, the code checks the value of the fPending parameter to determine whether to create the event or simply return a handle to the event created by another thread. If fPending is FALSE, initialization has already completed so OpenEventHandleAsync returns the event handle returned in the lpContext parameter. Otherwise, it calls the CreateEvent function to create the event and the InitOnceComplete function to complete the initialization.

If the call to InitOnceComplete succeeds, OpenEventHandleAsync returns the new event handle. Otherwise, it closes the event handle and calls InitOnceBeginInitialize with INIT_ONCE_CHECK_ONLY to determine whether initialization failed or was completed by another thread.

If the initialization was completed by another thread, OpenEventHandleAsync returns the event handle returned in lpContext. Otherwise, it returns INVALID_HANDLE_VALUE.

One-Time Initialization

Components are often designed to perform initialization tasks when they are first called, rather than when they are loaded. The one-time initialization functions ensure that this initialization occurs only once, even when multiple threads may attempt the initialization.

Windows ServerВ 2003 and WindowsВ XP: Applications must provide their own synchronization for one-time initialization by using the interlocked functions or other synchronization mechanism. The one-time initialization functions are available starting with WindowsВ Vista and Windows ServerВ 2008.

The one-time initialization functions provide significant advantages to ensure that only one thread performs the initialization:

  • They are optimized for speed.
  • They create the appropriate barriers on processor architectures that require them.
  • They support both locked and parallel initialization.
  • They avoid internal locking so the code can operate asynchronously or synchronously.

The system manages the initialization process through an opaque INIT_ONCE structure that contains data and state information. The caller allocates this structure and initializes it by either calling InitOnceInitialize (to initialize the structure dynamically) or assigning the constant INIT_ONCE_STATIC_INIT to the structure variable (to initialize the structure statically). Initially, the data stored in the one-time initialization structure is NULL and its state is uninitialized.

One-time initialization structures cannot be shared across processes.

The thread that performs the initialization can optionally set a context that is available to the caller after initialization is complete. The context can be a synchronization object or it can be a value or data structure. If the context is a value, its low-order INIT_ONCE_CTX_RESERVED_BITS must be zero. If the context is a data structure, the data structure must be DWORD-aligned. The context is returned to the caller in the lpContext output parameter of the InitOnceBeginInitialize or InitOnceExecuteOnce function.

One-time initialization can be performed synchronously or asynchronously. An optional callback function can be used for synchronous one-time initialization.

Synchronous One-time Initialization

The following steps describe synchronous one-time initialization that does not use a callback function.

  1. The first thread to call the InitOnceBeginInitialize function successfully causes one-time initialization to begin. For synchronous one-time initialization, InitOnceBeginInitialize must be called without the INIT_ONCE_ASYNC flag.
  2. Subsequent threads that attempt initialization are blocked until the first thread either completes initialization or fails. If the first thread fails, the next thread is allowed to attempt the initialization, and so on.
  3. When initialization is finished, the thread calls the InitOnceComplete function. The thread can optionally create a synchronization object (or other context data) and specify it in the lpContext parameter of the InitOnceComplete function.
  4. If the initialization succeeds, the state of the one-time initialization structure is changed to initialized and the lpContext handle (if any) is stored in the initialization structure. Subsequent initialization attempts return this context data. If the initialization fails, the data is NULL.

The following steps describe synchronous one-time initialization that uses a callback function.

  1. The first thread to successfully call the InitOnceExecuteOnce function passes a pointer to an application-defined InitOnceCallback callback function and any data required by the callback function. If the call succeeds, the InitOnceCallback callback function executes.
  2. Subsequent threads that attempt initialization are blocked until the first thread either completes initialization or fails. If the first thread fails, the next thread is allowed to attempt the initialization, and so on.
  3. When initialization is finished, the callback function returns. The callback function can optionally create a synchronization object (or other context data) and specify it in its Context output parameter.
  4. If the initialization succeeds, the state of the one-time initialization structure is changed to initialized and the Context handle (if any) is stored in the initialization structure. Subsequent initialization attempts return this context data. If the initialization fails, the data is NULL.
Читайте также:  Как обновлять выпуск windows

Asynchronous One-time Initialization

The following steps describe asynchronous one-time initialization.

  1. If multiple threads simultaneously attempt to begin initialization by calling InitOnceBeginInitialize with INIT_ONCE_ASYNC, the function succeeds for all of the threads with the fPending parameter set to TRUE. Only one thread will actually succeed at initialization; other concurrent attempts do not change the initialization state.
  2. When InitOnceBeginInitialize returns, the fPending parameter indicates the initialization status:
    • If fPending is FALSE, one thread has succeeded at initialization. Other threads should clean up any context data they have created and use the context data in the lpContext output parameter of InitOnceBeginInitialize.
    • If fPending is TRUE, initialization has not yet completed and other threads should continue.
  3. Each thread calls the InitOnceComplete function. The thread can optionally create a synchronization object (or other context data) and specify it in the lpContext parameter of InitOnceComplete.
  4. When InitOnceComplete returns, its return value indicates whether the calling thread succeeded at initialization.
    • If InitOnceComplete succeeds, the calling thread has succeeded at initialization. The state of the one-time initialization structure is changed to initialized and the lpContext handle (if any) is stored in the initialization structure.
    • If InitOnceComplete fails, another thread has succeeded at initialization. The calling thread should clean up any context data it has created and call InitOnceBeginInitialize with INIT_ONCE_CHECK_ONLY to retrieve any context data stored in the one-time initialization structure.

Calling One-Time Initialization from multiple sites

One-time initialization guarded by a single INIT_ONCE structure may be performed from mutiple sites; different callback may be passed from each site, and synchronization with and without callback may be mixed. Initialization is still guaranted to perform sucesfully just once.

However, asynchronous and synchronous initialization cannot be mixed: once asynchronous initialization is attempted, attempts to start synchronous initialization would fail.

InitOnceExecuteOnce function (synchapi.h)

Executes the specified function successfully one time. No other threads that specify the same one-time initialization structure can execute the specified function while it is being executed by the current thread.

Syntax

Parameters

A pointer to the one-time initialization structure.

A pointer to an application-defined InitOnceCallback function.

A parameter to be passed to the callback function.

A parameter that receives data stored with the one-time initialization structure upon success. The low-order INIT_ONCE_CTX_RESERVED_BITS bits of the data are always zero.

Return value

If the function succeeds, the return value is nonzero.

If the function fails, the return value is zero. To get extended error information, call GetLastError.

Remarks

This function is used for synchronous one-time initialization. For asynchronous one-time initialization, use the InitOnceBeginInitialize function with the INIT_ONCE_ASYNC flag.

Only one thread at a time can execute the callback function specified by InitFn. Other threads that specify the same one-time initialization structure block until the callback finishes.

To compile an application that uses this function, define _WIN32_WINNT as 0x0600 or later. For more information, see Using the Windows Headers.

Examples

For an example that uses this function, see Using One-Time Initialization.

InitOnceBeginInitialize function (synchapi.h)

Begins one-time initialization.

Syntax

Parameters

A pointer to the one-time initialization structure.

This parameter can have a value of 0, or one or more of the following flags.

Value Meaning
INIT_ONCE_ASYNC 0x00000002UL Enables multiple initialization attempts to execute in parallel. If this flag is used, subsequent calls to this function will fail unless this flag is also specified.
INIT_ONCE_CHECK_ONLY 0x00000001UL This function call does not begin initialization. The return value indicates whether initialization has already completed. If the function returns TRUE, the lpContext parameter receives the data.

If the function succeeds, this parameter indicates the current initialization status.

If this parameter is TRUE and dwFlags contains INIT_ONCE_CHECK_ONLY, the initialization is pending and the context data is invalid.

If this parameter is FALSE, initialization has already completed and the caller can retrieve the context data from the lpContext parameter.

If this parameter is TRUE and dwFlags does not contain INIT_ONCE_CHECK_ONLY, initialization has been started and the caller can perform the initialization tasks.

An optional parameter that receives the data stored with the one-time initialization structure upon success. The low-order INIT_ONCE_CTX_RESERVED_BITS bits of the data are always zero.

Return value

If INIT_ONCE_CHECK_ONLY is not specified and the function succeeds, the return value is TRUE.

If INIT_ONCE_CHECK_ONLY is specified and initialization has completed, the return value is TRUE.

Otherwise, the return value is FALSE.

To get extended error information, call GetLastError.

Remarks

This function can be used for either synchronous or asynchronous one-time initialization. For asynchronous one-time initialization, use the INIT_ONCE_ASYNC flag. To specify a callback function to execute during synchronous one-time initialization, see the InitOnceExecuteOnce function.

If this function succeeds, the thread can create a synchronization object and specify in the lpContext parameter of the InitOnceComplete function.

To compile an application that uses this function, define _WIN32_WINNT as 0x0600 or later. For more information, see Using the Windows Headers.

A one-time initialization object cannot be moved or copied. The process must not modify the initialization object, and must instead treat it as logically opaque. Only use the one-time initialization functions to manage one-time initialization objects.

Examples

For an example that uses this function, see Using One-Time Initialization

Мгновенная инициализация файлов базы данных Database Instant File Initialization

Применимо к: Applies to: SQL Server SQL Server (все поддерживаемые версии) SQL Server SQL Server (all supported versions) Применимо к: Applies to: SQL Server SQL Server (все поддерживаемые версии) SQL Server SQL Server (all supported versions)

Читайте также:  Girls on windows live

В этой статье вы узнаете о быстрой инициализации файлов и о том, как включить ее для ускорения роста файлов базы данных SQL Server. In this article, you learn about instant file initialization, and how to enable it to speed up growth for your SQL Server database files.

По умолчанию файлы данных и журналов инициализируются, чтобы перезаписать все существующие данные на диске, оставшиеся после удаленных файлов. By default, data and log files are initialized to overwrite any existing data left on the disk from previously deleted files. Файлы данных и журналов сначала инициализируются путем обнуления (заполнения нулями) при выполнении следующих операций: Data and log files are first initialized by zeroing the files (filling with zeros) when you perform the following operations:

  • создавать базу данных; Create a database.
  • Добавление файлов данных и журналов к существующей базе данных. Add data or log files, to an existing database.
  • Увеличение размера существующего файла (включая операции автоувеличения). Increase the size of an existing file (including autogrow operations).
  • Восстановление базы данных или файловой группы. Restore a database or filegroup.

В SQL Server SQL Server мгновенная инициализация файлов (IFI) позволяет быстрее выполнять ранее упомянутые файловые операции, так как она освобождает занятое место на диске, не заполняя его нулями. In SQL Server SQL Server , instant file initialization (IFI) allows for faster execution of the previously mentioned file operations, since it reclaims used disk space without filling that space with zeros. Вместо этого содержимое диска перезаписывается, поскольку в файлы записываются новые данные. Instead, disk content is overwritten as new data is written to the files. Файлы журналов не могут быть инициализированы мгновенно. Log files cannot be initialized instantaneously.

Включить мгновенную инициализацию файлов Enable instant file initialization

Мгновенная инициализация файлов доступна, только если стартовой учетной записи службы SQL Server SQL Server предоставлено разрешение SE_MANAGE_VOLUME_NAME. Instant file initialization is only available if the SQL Server SQL Server service startup account has been granted SE_MANAGE_VOLUME_NAME. Участники группы администраторов Windows обладают этим правом и могут предоставить его другим пользователям, добавив их в политику безопасности Выполнение задач обслуживания томов . Members of the Windows Administrator group have this right and can grant it to other users by adding them to the Perform Volume Maintenance Tasks security policy.

Некоторые условия, например прозрачное шифрование данных, могут не допускать мгновенную инициализацию файлов. Some feature usage, such as Transparent Data Encryption (TDE), can prevent Instant File Initialization.

Начиная с SQL Server 2016 (13.x); SQL Server 2016 (13.x) , это разрешение можно предоставлять учетной записи службы во время установки. Starting with SQL Server 2016 (13.x); SQL Server 2016 (13.x) , this permission can be granted to the service account at install time, during setup.

При использовании установки из командной строки добавьте аргумент /SQLSVCINSTANTFILEINIT либо установите флажок Предоставить право на выполнение задач обслуживания тома службе ядра СУБД SQL Server в мастере установки. If using the command prompt install, add the /SQLSVCINSTANTFILEINIT argument, or check the box Grant Perform Volume Maintenance Task privilege to SQL Server Database Engine Service in the installation wizard.

Предоставление учетной записи разрешения Perform volume maintenance tasks . To grant an account the Perform volume maintenance tasks permission:

На компьютере, где будет создан файл данных, откройте приложение Локальная политика безопасности ( secpol.msc ). On the computer where the data file will be created, open the Local Security Policy application ( secpol.msc ).

Разверните на левой панели узел Локальные политики, а затем щелкните пункт Назначение прав пользователей. In the left pane, expand Local Policies, and then click User Rights Assignment.

На правой панели дважды щелкните Выполнение задач по обслуживанию томов. In the right pane, double-click Perform volume maintenance tasks.

Выберите пункт Добавить пользователя или группу и добавьте учетную запись, от имени которой запущена служба SQL Server. Click Add User or Group and add the account that runs the SQL Server service.

Нажмите кнопку Применить и закройте все диалоговые окна Локальная политика безопасности . Click Apply, and then close all Local Security Policy dialog boxes.

Перезапустите службу SQL Server. Restart the SQL Server service.

Проверьте журнал ошибок SQL Server SQL Server при запуске. Check the SQL Server SQL Server error log at startup.

Применимо к: SQL Server SQL Server (начиная с версии SQL Server 2012 (11.x) SQL Server 2012 (11.x) с пакетом обновления 4 (SP4), SQL Server 2014 (12.x) SQL Server 2014 (12.x) с пакетом обновления 2 (SP2) и версий SQL Server 2016 (13.x); SQL Server 2016 (13.x) и выше). Applies to: SQL Server SQL Server (Starting with SQL Server 2012 (11.x) SQL Server 2012 (11.x) SP4, SQL Server 2014 (12.x) SQL Server 2014 (12.x) SP2 and SQL Server 2016 (13.x); SQL Server 2016 (13.x) and later).

Если учетной записи запуска службы SQL Server SQL Server предоставлено разрешение SE_MANAGE_VOLUME_NAME, регистрируется подобное информационное сообщение: If the SQL Server SQL Server service startup account is granted SE_MANAGE_VOLUME_NAME, an informational message that resembles the following is logged:

Database Instant File Initialization: enabled. For security and performance considerations see the topic ‘Database Instant File Initialization’ in SQL Server Books Online. This is an informational message only. No user action is required.

Если учетной записи запуска службы SQL Server SQL Server не предоставлено разрешение SE_MANAGE_VOLUME_NAME, регистрируется подобное информационное сообщение: If the SQL Server SQL Server service startup account has not been granted SE_MANAGE_VOLUME_NAME, an informational message that resembles the following is logged:

Database Instant File Initialization: disabled. For security and performance considerations see the topic ‘Database Instant File Initialization’ in SQL Server Books Online. This is an informational message only. No user action is required.

Вы можете использовать столбец instant_file_initialization_enabled в динамическом административном представлении sys.dm_server_services для определения того, включена ли мгновенная инициализация файлов. You can also use the column instant_file_initialization_enabled in the sys.dm_server_services DMV to identify if instant file initialization is enabled.

Читайте также:  Как удалить касперский linux

Вопросы безопасности Security considerations

Мы советуем включить мгновенную инициализацию файлов, так как преимущества перевешивают риски безопасности. We recommend enabling instant file initialization as the benefits can outweigh the security risk.

При использовании мгновенной инициализации файлов удаленное содержимое диска перезаписывается только по мере того, как в файлы записываются новые данные. When using instant file initialization, the deleted disk content is overwritten only as new data is written to the files. Поэтому доступ к удаленному содержимому может получить неавторизованный субъект, пока в эту область файла данных не будут записаны другие данные. For this reason, the deleted content might be accessed by an unauthorized principal, until some other data writes on that specific area of the data file.

По мере подключения файла базы данных к экземпляру SQL Server SQL Server риск раскрытия информации уменьшается благодаря списку управления доступом на уровне пользователей (DACL) в файле. While the database file is attached to the instance of SQL Server SQL Server , this information disclosure risk is reduced by the discretionary access control list (DACL) on the file. DACL разрешает доступ к файлу только учетной записи службы SQL Server SQL Server и локальному администратору. This DACL allows file access only to the SQL Server SQL Server service account and the local administrator. Но при отсоединении файла доступ к нему может получить пользователь или служба, которым не предоставлено разрешение SE_MANAGE_VOLUME_NAME. However, when the file is detached, it may be accessed by a user or service that does not have SE_MANAGE_VOLUME_NAME.

Аналогичные соображения существуют в следующих случаях. Similar considerations exist when:

Создается резервная копия базы данных. The database is backed up. Если файл резервной копии не защищен с помощью соответствующего DACL, удаленное содержимое может стать доступным неавторизованному пользователю или службе. If the backup file is not protected with an appropriate DACL, the deleted content can become available to an unauthorized user or service.

Файл расширяется с помощью IFI. A file is grown using IFI. Администратор SQL Server потенциально может получить доступ к содержимому необработанных страниц и просматривать ранее удаленное содержимое. A SQL Server administrator could potentially access the raw page contents and see the previously deleted content.

Файлы базы данных размещаются в сети хранения. The database files are hosted on a storage area network. Она может всегда представлять новые страницы в виде предварительно инициализированных, что способно создавать излишнюю нагрузку, так как операционной системе требуется инициализировать эти страницы повторно. It is also possible that the storage area network always presents new pages as pre-initialized, and having the operating system re-initialize the pages might be unnecessary overhead.

Если вероятность раскрытия удаленного содержимого является серьезной проблемой, необходимо выполнить одно следующее действие или оба. If the potential for disclosing deleted content is a concern, you should take one or both of the following actions:

Всегда проверяйте, что все отсоединенные файлы данных и резервные копии имеют ограничивающие DACL. Always make sure that any detached data files and backup files have restrictive DACLs.

Отключите быструю инициализацию для экземпляра SQL Server SQL Server . Disable instant file initialization for the instance of SQL Server SQL Server . Для этого отмените SE_MANAGE_VOLUME_NAME из стартовой учетной записи службы SQL Server SQL Server . To do so, revoke SE_MANAGE_VOLUME_NAME from the SQL Server SQL Server service startup account.

Отключение увеличивает время выделения файлов для файлов данных и влияет только на создаваемые или увеличивающиеся в размере файлы после отзыва прав пользователя. Disabling will increase allocation times for data files, and only affects files that are created or increased in size after the user right is revoked.

Право пользователя SE_MANAGE_VOLUME_NAME SE_MANAGE_VOLUME_NAME user right

Право пользователя SE_MANAGE_VOLUME_NAME можно назначить в средствах администрирования Windows с помощью приложения Локальная политика безопасности. The SE_MANAGE_VOLUME_NAME user privilege can be assigned in Windows Administrative Tools, Local Security Policy applet. В разделе Локальные политики выберите Назначение прав пользователя и измените свойство Выполнение задач по обслуживанию томов. Under Local Policies select User Right Assignment and modify the Perform volume maintenance tasks property.

Вопросы производительности Performance considerations

Процесс инициализации файла базы данных записывает нули в новые регионы файла при инициализации. The Database File initialization process writes zeros to the new regions of the file under initialization. Длительность этого процесса зависит от размера инициализированной части файла и времени отклика и емкости системы хранения. The duration of this process depends on size of file portion that is initialized and on the response time and capacity of the storage system. Если инициализация занимает много времени, могут отобразиться следующие сообщения, записанные в журнал ошибок SQL Server и в журнал приложения. If the initialization takes a long time, you may see the following messages recorded in the SQL Server Errorlog and the Application Log.

Длительное автоматическое увеличение размера базы данных или файла журнала транзакций может привести к проблемам с производительностью запросов. A long autogrow of a database and/or transaction log file may cause query performance problems. Это обусловлено тем, что операция, требующая автоматического увеличения размера файла, будет приостановлена на ресурсах, таких как блокировки или кратковременные блокировки, по мере увеличения размера файла. This is because an operation that requires the autogrowth of a file will hold on to resources such as locks or latches during the duration of the file grow operation. Длительные ожидания кратковременных блокировок могут отображаться для страниц распределения. You may see long waits on latches for allocation pages. Для операции, требующей длительного автоматического увеличения размера, будет показан тип ожидания PREEMPTIVE_OS_WRITEFILEGATHER. The operation that requires the long autogrow will show a wait type of PREEMPTIVE_OS_WRITEFILEGATHER.

Оцените статью