关于zone里面的wait_table相关的3个成员,注释已经说得很清楚了:/** wait_table-- the array holding the hash table* wait_table_hash_nr_entries-- the size of the hash table array* wait_table_bits-- wait_table_size == (1 << wait_table_bits)** The purpose of all these is to keep track of the people* waiting for a page to become available and make them* runnable again when possible. The trouble is that this* consumes a lot of space, especially when so few things* wait on pages at a given time. So instead of using* per-page waitqueues, we use a waitqueue hash table.** The bucket discipline is to sleep on the same queue when* colliding and wake all in that wait queue when removing.* When something wakes, it must check to be sure its page is* truly available, a la thundering herd. The cost of a* collision is great, but given the expected load of the* table, they should be so rare as to be outweighed by the* benefits from the saved space.** __wait_on_page_locked() and unlock_page() in mm/filemap.c, are the* primary users of these fields, and in mm/page_alloc.c* free_area_init_core() performs the initialization of them.*/下面来看看它们是怎样初始化的:static noinline __init_refokint zone_wait_table_init(struct zone *zone, unsignedlong zone_size_pages){int i;struct pglist_data *pgdat = zone->zone_pgdat;size_t alloc_size;/** The per-page waitqueue mechanism uses hashed waitqueues* per zone.*/zone->wait_table_hash_nr_entries =wait_table_hash_nr_entries(zone_size_pages);zone->wait_table_bits =wait_table_bits(zone->wait_table_hash_nr_entries);alloc_size = zone->wait_table_hash_nr_entries* sizeof(wait_queue_head_t);if (system_state == SYSTEM_BOOTING) {zone->wait_table = (wait_queue_head_t *)alloc_bootmem_node(pgdat, alloc_size);} else {/** This case means that a zone whose size was 0 gets new memory* via memory hot-add.* But it may be the case that a new node was hot-added.In* this case vmalloc() will not be able to use this new node's* memory - this wait_table must be initialized to use this new* node itself as well.* To use this new node's memory, further consideration will be* necessary.*/zone->wait_table = (wait_queue_head_t *)vmalloc(alloc_size);}if (!zone->wait_table)return -ENOMEM;for(i = 0; i < zone->wait_table_hash_nr_entries; ++i)init_waitqueue_head(zone->wait_table + i);return 0;}这里比较值得关注的是wait_table_hash_nr_entries的计算,它通过wait_table_hash_nr_entries函数来计算:/** Helper functions to size the waitqueue hash table.* Essentially these want to choose hash table sizes sufficiently* large so that collisions trying to wait on pages are rare.* But in fact, the number of active page waitqueues on typical* systems is ridiculously low, less than 200. So this is even* conservative, even though it seems large.** The constant PAGES_PER_WAITQUEUE specifies the ratio of pages to* waitqueues, i.e. the size of the waitq table given the number of pages.*/#define PAGES_PER_WAITQUEUE256staticinlineunsignedlong wait_table_hash_nr_entries(unsignedlong pages){unsignedlong size = 1;pages /= PAGES_PER_WAITQUEUE;while (size < pages)size <<= 1;/** Once we have dozens or even hundreds of threads sleeping* on IO we've got bigger problems than wait queue collision.* Limit the size of the wait table to a reasonable size.*/size = min(size, 4096UL);return max(size, 4UL);}在这里pages为内存区的总页数,对于64M内存(限制为60M),其值为0x3bff。此函数计算所得的结果将为0x40。即zone->wait_table_hash_nr_entries的值将为0x40,而zone->wait_table_bits的值将为6。