Home Backend Development PHP Tutorial nginx source code study notes (20) - event module 1 - initialization

nginx source code study notes (20) - event module 1 - initialization

Jul 29, 2016 am 09:11 AM
conf cycle event nbsp

After reading the previous study notes, I believe that I have a certain understanding of the startup process of nginx. From this section on, we want to go deep into each module and learn the main operations within each module.

This article comes from: http://blog.csdn.net/lengzijian/article/details/7598996

Today we will learn about the event module. In the previous startup, we mentioned calling each module many times. The hook function of

This method mainly creates an ngx_event_conf_t structure and allocates memory space. nginx 源码学习笔记(二十)—— event 模块一 ——初始化

2. Read the configuration file:

For example, the read file has the following lines:

[cpp] view plaincopyprint?

events

{

use epoll;

  1. worker_connections 10240; }
  2. The events in this place are a block instruction. Many instructions can be configured within the brackets. These instructions are defined in src/event/ngx_event.c
  3. [cpp] view plaincopyprint?
static
ngx_command_t ngx_event_core_commands[] = {

{ ngx_string(
    "worker_ connections"
  1. ), NGX_EVENT_CONF|NGX_CONF_TAKE1,
  2. ngx_event_connections,
  3. 0, 0,
  4. NULL },
  5. ...(omitted here)
  6.                                                                                     
  7. NGX_EVENT_CONF|NGX_CONF_TAKE1,
  8. ngx_event_connections,
  9. 0,
  10. 0,
  11. NULL },
  12. {ngx_string(
  13. "use" ),
  14. NGX_EVENT_CONF|NGX_CONF_TAKE1,
  15. ngx_event_use,
  16. 0,
  17. 0,
  18. NULL },
  19. ngx_null_command
  20. };
  21. When events are parsed, the following function will be called back:
  22. [cpp] view plaincopyprint?
    1. src/event/ngx_event.c  
    2. static char *  
    3. ngx_events_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)  
    4. {  
    5.     char                 *rv;  
    6.     void               ***ctx;  
    7.     ngx_uint_t            i;  
    8.     ngx_conf_t            pcf;  
    9.     ngx_event_module_t   *m;  
    10.   
    11.     /* count the number of the event modules and set up their indices */  
    12.     //计算event模块数量,并且记录  
    13.     ngx_event_max_module = 0;  
    14.     for (i = 0; ngx_modules[i]; i++) {  
    15.         if (ngx_modules[i]->type != NGX_EVENT_MODULE) {  
    16.             continue;  
    17.         }  
    18.   
    19.         ngx_modules[i]->ctx_index = ngx_event_max_module++;  
    20.     }  
    21.   
    22.     ctx = ngx_pcalloc(cf->pool, sizeof(void *));  
    23.     if (ctx == NULL) {  
    24.         return NGX_CONF_ERROR;  
    25.     }  
    26.     //为每一个event模块分配空间,用来保存响应配置结构的地址  
    27.     //共分配了ngx_event_max_module个空间  
    28.     *ctx = ngx_pcalloc(cf->pool, ngx_event_max_module * sizeof(void *));  
    29.     if (*ctx == NULL) {  
    30.         return NGX_CONF_ERROR;  
    31.     }  
    32.   
    33.     *(void **) conf = ctx;  
    34.   
    35.     for (i = 0; ngx_modules[i]; i++) {  
    36.         if (ngx_modules[i]->type != NGX_EVENT_MODULE) {  
    37.             continue;  
    38.         }
    39. m = ngx_modules[i]->ctx;
    40. ​​​​​
    41. if
    42. (m->create_conf) { (*ctx)[ngx_modules[i]->ctx_index] = m->create_conf(cf->cycle);
    43.                                                                     
    44. ((*ctx)[ngx_modules[i]->ctx_index] == NULL) {
    45.                                                                                                                                                  
    46. pcf = *cf; cf->ctx = ctx;
    47. cf->module_type = NGX_EVENT_MODULE;
    48. cf->cmd_type = NGX_EVENT_CONF;
    49. //Since events is a block instruction, many other instructions can be configured in the events domain,
    50. //For example, the use mentioned before, etc., now start to parse the instructions in the events block and complete the initialization Work.
    51. rv = ngx_conf_parse(cf, NULL);
    52. *cf = pcf;
    53. if (rv != NGX_CONF_OK)
    54.                                                                             
    55. ​​​​​​​​​​​
    56. if​(ngx_modules[i]-> ;type != NGX_EVENT_MODULE) {
    57.                                                        m = ngx_modules[i]->ctx;
    58. //Loop to execute each event The init_conf function of the module, the initialization configuration structure
    59. (m-& gt; init_conf) {
    60. RV = m-& gt; init_conf (CF-& GT; cycle, (*ctx) [ngx_modules[i]->ctx_index]); return
    61. rv;                          
    62. }
    63. return
    64. NGX_CONF_OK;
    65. }

      The most important process in the ngx_events_block() function is to call ngx_conf_parse(cf, NULL). The function of calling ngx_conf_parse() here is to complete the parsing of the events{} block in the configuration file, thereby calling all configurations under it. The callback function of the instruction completes the initialization of parsing the configuration file. But here I have a personal question. After asking the seniors, I will specify the question and answer******.

      2. Initialize conf (init_conf)

      ngx_event_init_conf()

      This method mainly initializes the ngx_event_conf_t structure.

      3.ngx_event_module_init

      As the name suggests, it is the initialization operation of the module, but looking at the source code of each module, it is found that many modules do not have init callback functions. I am also struggling with why here, hoping to find the answer after learning all the code.

      [cpp] view plaincopyprint?

      1. src/event/ngx_event.c  
      2. static ngx_int_t  
      3. ngx_event_module_init(ngx_cycle_t *cycle)  
      4. {  
      5.     void              ***cf;  
      6.     u_char              *shared;  
      7.     size_t               size, cl;  
      8.     ngx_shm_t            shm;  
      9.     ngx_time_t          *tp;  
      10.     ngx_core_conf_t     *ccf;  
      11.     ngx_event_conf_t    *ecf;  
      12.       
      13.     //判断ngx_events_module是否调用过初始化conf操作  
      14.     cf = ngx_get_conf(cycle->conf_ctx, ngx_events_module);  
      15.   
      16.     if (cf == NULL) {  
      17.         ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,  
      18.                       "no "events" section in configuration");  
      19.         return NGX_ERROR;  
      20.     }  
      21.       
      22.     //获取ngx_event_core_module模块的配置结构  
      23.     ecf = (*cf)[ngx_event_core_module.ctx_index];  
      24.       
      25.     //查看是否是event中的模块,例如use 。。。。
      26. if (!ngx_test_config && ngx_process <= NGX_PROCESS_MASTER) {
      27. ngx_log_error(NGX _LOG_NOTICE, cycle->log, 0,
      28.                                                                              "event method", ecf->name);
      29. }
      30. //Get the configuration structure of the ngx_core_module module
      31. ccf = (ngx_core_conf_t *) ngx_get_conf(cycle- >conf_ctx, ngx_core_module);
      32. //Get the timer_resolution parameter from the configuration structure of the ngx_core_module module ngx_timer_resolution = ccf->timer_resolution;
      33. #if !(NGX_WIN32)
      34. { ngx_int_t limit;
      35. rlimit rlmt;
      36. //Get the ability of the current process The maximum number of open files man getrlimit
      37. (getrlimit(RLIMIT_NOFILE, &rlmt) == -1) { x_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
      38.                                                                                                                                                                                                                        else{
      39. _The maximum number of connections to a module is unlimited​​
      40. ​​​​​/ /Or ngx_event_core_module connection is greater than ngx_core_module maximum number of connections
      41. (ECF-& GT; Connections & GT; (ngx_uint_t) rlmt.rlim_cur
      42. (ccf-& gt; _NOFILE == ngx_conf_unset
      43.                                                                limit = (ccf->rlimit_nofile == NGX_CONF_UNSET) ?
      44. ( ngx_int_t) rlmt.rlim_cur: ccf- & gt; rlimit_nofile;
      45.                                                                                 " open file resource limit: %i" ); endif /* !(NGX_WIN32) */
      46. //If the master process is closed, return
      47. //Because closing the master process means single-process work Method,
      48. //The subsequent operations create shared memory to implement locks and other work, which is not required for a single process.
    66. if (ccf->master == 0) {
    67. NGX_OK; }
    68. // If the accept mutex already exists, there is no need to create it again.
    69. NGX_OK;
    70. }
    71. /* cl should be equal or bigger than cache line size */
    72. cl = 128;
    73. //Create size here Shared memory, this shared memory will be divided into three equal segments
    74. size = cl                                      + cl                                                       
    75.                                                                                                       ,
    76. shm.size = size;
    77.  shm.name.len = sizeof("nginx_shared_zone"
    78. );
    79.  shm.name.data = (u_char *) "nginx_share d_zone"
    80. ;
    81. shm.log = cycle->log;
    82. (ngx_shm_alloc(&shm) ! = NGX_OK) { NGX_ERROR;
    83. NGX_ERROR;
    84. shared = shm.addr;
    85. //Accept mutex gets the first cl size memory of shared memory
    86. ngx_accept_mutex_ptr = (ngx_atomic_t *) shared; ngx_accept_mutex.spin = (ngx_uint_t) -1;
    87. /*Create accept mutex
    88. The implementation of accept mutex depends on whether it supports atomic operations, if there are corresponding atomic operations;
    89. That’s it Use the obtained shared memory to implement the accept mutex; otherwise, the file lock will be used to implement the accept mutex.
    90. The function of the accept mutex is to avoid panic groups and achieve load balancing of worker processes.
  23. ngx_accept_mutex, shared, cycle->lock_file.data)
  24. != NGX_OK)
  25.                                                                                     
  26. //Get the cl-sized address of the second segment of memory
  27. ngx_connection_counter = (ngx_atomic_t *) (shared + 1 * cl);
  28. (
  29. void
  30. ) ngx_atomic_cmp_set(ngx_connection_counter, 0, 1);
  31. ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle- >log, 0,
  32.                                                                                                         x_connection_counter);
  33. //Get the size of the third segment of memory cl Address
  34. ngx_temp_number = (ngx_atomic_t *) (shared + 2 * cl);
  35. tp = ngx_timeofday() ;
  36. ngx_random_number = (tp-> ;msec << 16) + ngx_pid;
  37. return
  38. NGX_OK;
  39. 4.ngx_event_process_init in the previous worker process As mentioned in the analysis, when a worker process is created, the worker process will first initialize the process, and at this time the ngx_event_process_init function will be called.
  40. [cpp] view plaincopyprint?
    1. src/event/ngx_event.c
    2. staticngx_int_t
    3. ngx_event_process_init(ngx_cycle_t *cycle)
    4. {
    5. ngx_uint_t m, i;
    6. ngx_event_t *rev, *wev;
    7. ngx_listening_t *ls;
    8. ngx_connection_t *c, *next, *old;
    9. ngx_core_conf_t *ccf;
    10. ngx_event_conf_t *ecf;
    11. ngx_event_module_t *module;
    12. //As before, get the configuration structure of the response module
    13. ccf = (ngx_core_conf_t *) ngx_get_conf( cycle->conf_ctx, ngx_core_module);
    14.  ecf = ngx_event_get_conf(cycle->conf_ctx, ngx_event_core_module);
    15. //Master process is open, worker process is greater than 1, accept_mutex has been created
    16. //cai Open the accept mutex
    17. if (ccf->master &&ccf->worker_processes > 1 &&ecf->accept_mutex) {
    18. ngx_use_accept_mutex = 1; / /Use mutex
    19. ngx_accept_mutex_held = 0; //Whether to get accept mutex
    20. ngx_accept_mutex_delay = ecf->accept_mutex_delay;//After failure to compete for the mutex , waiting for the next scramble time interval
    21. } else {
    22. ngx_use_accept_mutex = 0 ;
    23. }
    24. #if (NGX_THREADS)
    25. //Threads aside
    26. #endif
    27. //Initialize counter, a red will be created here Black Tree, to maintain the timer, will explain in detail later
    28. if (ngx_event_timer_init(cycle->log) == NGX_ERROR) {
    29. return NGX_ERROR;
    30. }
    31. for (m = 0; ngx_modules[m]; m++) {
    32. //As mentioned here before, skip non-NGX_EVENT_MODULE modules
    33.                                                                                                                                                               
    34. }
    35.                                      // Modules specified by non-use configuration instructions are skipped, Linux default epoll                                              ->use) { module = ngx_modules[m]->ctx;
    36. /*Call the init function of the specific time module ( These modules are located in the src/event/modules directory), so nginx A layer of abstraction has been made to the time module, which makes it easier for different systems to use different event models and expands new time models. Our focus should be on epoll.
    37.                                                                                                                                                                                                                 The init callback here actually calls the ngx_epoll_init function. The module->actions structure encapsulates all interface functions of epoll. nginx registers epoll into the event abstraction layer through the actions structure.
    38. The type of actions is ngx_event_action_t, located in src/event/ngx_event.h
    39. These specific contents will be explained in the next section.
    40.                                        module->actions.init(cycle, ngx_timer_resolution) != NGX_OK) {
    41. *fatal */
    42. exit(2); break
    43. ;
    44. }
    45. //Omitted here Part of the content
    46. //Create a global ngx_connection_t array to save all connections
    47. //Since this process is executed in each worker process, each worker has Own connection array
    48. cycle->connections = ngx_alloc(sizeof
    49. (ngx_connection_t) *cycle->connection_n, cycle->log);
    50. if
    51. (cycle->connections == NULL) {
    52. c = cycle->connections;
    53. //Create an array of read events
    54. cycle->read_events = ngx_alloc(sizeof
    55. (ngx_event_t) * cycle->connection_n,                                                                                                                                                                                                                                                                        ​;log);
    56. if
    57. (cycle->read_events == NULL) {
    58. NGX_ERROR;
    59. }
    60. rev = cycle->read_events;
    61. for (i = 0; i < cycle->connection_n; i++) {
    62. rev[i].closed = 1 ;
    63.                                  [i].instance = 1;
    64. #if (NGX_THREADS)
    65. rev[i].lock = &c[i].lock;
    66. rev[i].own_lock = &c[i].lock;
    67. #endif
    68. }  
    69.     //创建一个写事件数组  
    70.     cycle->write_events = ngx_alloc(sizeof(ngx_event_t) * cycle->connection_n,  
    71.                                     cycle->log);  
    72.     if (cycle->write_events == NULL) {  
    73.         return NGX_ERROR;  
    74.     }  
    75.   
    76.     wev = cycle->write_events;  
    77.     for (i = 0; i < cycle->connection_n; i++) {  
    78.         wev[i].closed = 1;  
    79. #if (NGX_THREADS)  
    80.         wev[i].lock = &c[i].lock;  
    81.         wev[i].own_lock = &c[i].lock;  
    82. #endif  
    83.     }  
    84.   
    85.     i = cycle->connection_n;  
    86.     next = NULL;  
    87.     //初始化整个connection数组  
    88.     do {  
    89.         i--;  
    90.   
    91.         c[i].data = next;  
    92.         c[i].read = &cycle->read_events[i];  
    93.         c[i].write = &cycle->write_events[i];  
    94.         c[i].fd = (ngx_socket_t) -1;  
    95.   
    96.         next = &c[i];  
    97.   
    98. #if (NGX_THREADS)  
    99.         c[i].lock = 0;  
    100. #endif  
    101.     }while (i);
    102. cycle->free_connections = next;
    103. cycle->free_connection_n = cycle-> connection_n;
    104. /* for each listening socket */
    105. //Assign a connection from the connection array for each listening socket, that is, a slot
    106. ls = cycle->listening .els; Connect to solt
    107. _ C = ngx_get_connection (ls [i] .fd, cycle-& gt; log); NGX_ERROR; }  
    108.   
    109.         c->log = &ls[i].log;  
    110.   
    111.         c->listening = &ls[i];  
    112.         ls[i].connection = c;  
    113.   
    114.         rev = c->read;  
    115.   
    116.         rev->log = c->log;  
    117.         rev->accept = 1; //读时间发生,调用accept  
    118.   
    119. #if (NGX_HAVE_DEFERRED_ACCEPT)  
    120.         //省略  
    121. #endif  
    122.   
    123.         if (!(ngx_event_flags & NGX_USE_IOCP_EVENT)) {  
    124.             if (ls[i].previous) {  
    125.   
    126.                 /* 
    127.                  * delete the old accept events that were bound to 
    128.                  * the old cycle read events array 
    129.                  */  
    130.   
    131.                 old = ls[i].previous->connection;  
    132.   
    133.                 if (ngx_del_event(old->read, NGX_READ_EVENT, NGX_CLOSE_EVENT)  
    134.                     == NGX_ERROR)  
    135.                 {  
    136.                     return NGX_ERROR;  
    137.                 }  
    138.   
    139.                 old->fd = (ngx_socket_t) -1;  
    140.             }  
    141.         }
    142. //Register the callback function ngx_event_accept
    143. rev->handler = ngx_even t_accept;
    144.                                    , do not put the listening socket into epoll for the time being, but
    145.                                                                                                                          {
    146.                                                                                                                                                                                                                                     
    147. }
    148. } else{
    149.      //If the accept mutex is not used, then put this listening socket into epoll.
    150.                                                                                                                                                                             
    151. #endif
    152. }
    153. return
    154. NGX_OK;
    155. }
    156. Until now , event-driven initialization has been completed.
    157. The above introduces the nginx source code study notes (20) - event module 1 - initialization, including IOC and counter content. I hope it will be helpful to friends who are interested in PHP tutorials.
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Article

R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)
3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Best Graphic Settings
3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. How to Fix Audio if You Can't Hear Anyone
3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25: How To Unlock Everything In MyRise
4 weeks ago By 尊渡假赌尊渡假赌尊渡假赌

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Solution: Your organization requires you to change your PIN Solution: Your organization requires you to change your PIN Oct 04, 2023 pm 05:45 PM

The message "Your organization has asked you to change your PIN" will appear on the login screen. This happens when the PIN expiration limit is reached on a computer using organization-based account settings, where they have control over personal devices. However, if you set up Windows using a personal account, the error message should ideally not appear. Although this is not always the case. Most users who encounter errors report using their personal accounts. Why does my organization ask me to change my PIN on Windows 11? It's possible that your account is associated with an organization, and your primary approach should be to verify this. Contacting your domain administrator can help! Additionally, misconfigured local policy settings or incorrect registry keys can cause errors. Right now

How to adjust window border settings on Windows 11: Change color and size How to adjust window border settings on Windows 11: Change color and size Sep 22, 2023 am 11:37 AM

Windows 11 brings fresh and elegant design to the forefront; the modern interface allows you to personalize and change the finest details, such as window borders. In this guide, we'll discuss step-by-step instructions to help you create an environment that reflects your style in the Windows operating system. How to change window border settings? Press + to open the Settings app. WindowsI go to Personalization and click Color Settings. Color Change Window Borders Settings Window 11" Width="643" Height="500" > Find the Show accent color on title bar and window borders option, and toggle the switch next to it. To display accent colors on the Start menu and taskbar To display the theme color on the Start menu and taskbar, turn on Show theme on the Start menu and taskbar

How to change title bar color on Windows 11? How to change title bar color on Windows 11? Sep 14, 2023 pm 03:33 PM

By default, the title bar color on Windows 11 depends on the dark/light theme you choose. However, you can change it to any color you want. In this guide, we'll discuss step-by-step instructions for three ways to change it and personalize your desktop experience to make it visually appealing. Is it possible to change the title bar color of active and inactive windows? Yes, you can change the title bar color of active windows using the Settings app, or you can change the title bar color of inactive windows using Registry Editor. To learn these steps, go to the next section. How to change title bar color in Windows 11? 1. Using the Settings app press + to open the settings window. WindowsI go to "Personalization" and then

OOBELANGUAGE Error Problems in Windows 11/10 Repair OOBELANGUAGE Error Problems in Windows 11/10 Repair Jul 16, 2023 pm 03:29 PM

Do you see "A problem occurred" along with the "OOBELANGUAGE" statement on the Windows Installer page? The installation of Windows sometimes stops due to such errors. OOBE means out-of-the-box experience. As the error message indicates, this is an issue related to OOBE language selection. There is nothing to worry about, you can solve this problem with nifty registry editing from the OOBE screen itself. Quick Fix – 1. Click the “Retry” button at the bottom of the OOBE app. This will continue the process without further hiccups. 2. Use the power button to force shut down the system. After the system restarts, OOBE should continue. 3. Disconnect the system from the Internet. Complete all aspects of OOBE in offline mode

How to enable or disable taskbar thumbnail previews on Windows 11 How to enable or disable taskbar thumbnail previews on Windows 11 Sep 15, 2023 pm 03:57 PM

Taskbar thumbnails can be fun, but they can also be distracting or annoying. Considering how often you hover over this area, you may have inadvertently closed important windows a few times. Another disadvantage is that it uses more system resources, so if you've been looking for a way to be more resource efficient, we'll show you how to disable it. However, if your hardware specs can handle it and you like the preview, you can enable it. How to enable taskbar thumbnail preview in Windows 11? 1. Using the Settings app tap the key and click Settings. Windows click System and select About. Click Advanced system settings. Navigate to the Advanced tab and select Settings under Performance. Select "Visual Effects"

Display scaling guide on Windows 11 Display scaling guide on Windows 11 Sep 19, 2023 pm 06:45 PM

We all have different preferences when it comes to display scaling on Windows 11. Some people like big icons, some like small icons. However, we all agree that having the right scaling is important. Poor font scaling or over-scaling of images can be a real productivity killer when working, so you need to know how to customize it to get the most out of your system's capabilities. Advantages of Custom Zoom: This is a useful feature for people who have difficulty reading text on the screen. It helps you see more on the screen at one time. You can create custom extension profiles that apply only to certain monitors and applications. Can help improve the performance of low-end hardware. It gives you more control over what's on your screen. How to use Windows 11

10 Ways to Adjust Brightness on Windows 11 10 Ways to Adjust Brightness on Windows 11 Dec 18, 2023 pm 02:21 PM

Screen brightness is an integral part of using modern computing devices, especially when you look at the screen for long periods of time. It helps you reduce eye strain, improve legibility, and view content easily and efficiently. However, depending on your settings, it can sometimes be difficult to manage brightness, especially on Windows 11 with the new UI changes. If you're having trouble adjusting brightness, here are all the ways to manage brightness on Windows 11. How to Change Brightness on Windows 11 [10 Ways Explained] Single monitor users can use the following methods to adjust brightness on Windows 11. This includes desktop systems using a single monitor as well as laptops. let's start. Method 1: Use the Action Center The Action Center is accessible

How to Fix Activation Error Code 0xc004f069 in Windows Server How to Fix Activation Error Code 0xc004f069 in Windows Server Jul 22, 2023 am 09:49 AM

The activation process on Windows sometimes takes a sudden turn to display an error message containing this error code 0xc004f069. Although the activation process is online, some older systems running Windows Server may experience this issue. Go through these initial checks, and if they don't help you activate your system, jump to the main solution to resolve the issue. Workaround – close the error message and activation window. Then restart the computer. Retry the Windows activation process from scratch again. Fix 1 – Activate from Terminal Activate Windows Server Edition system from cmd terminal. Stage – 1 Check Windows Server Version You have to check which type of W you are using

See all articles