In this book, we do not intend to delve into code-level detail on the internals of the page allocator. Having said that, here's the thing: in terms of data structures, the zone structure contains an array of free_area structures. This makes sense; as you've learned, there can be (and usually are) multiple page allocator freelists on the system, one per node:zone:
// include/linux/mmzone.h
struct zone {
[ ... ]
/* free areas of different sizes */
struct free_area free_area[MAX_ORDER];
[ ... ]
};
The free_area structure is the implementation of the doubly-linked circular lists (of free memory page frames within that node:zone) along with the number of page frames that are currently free:
struct free_area {
struct list_head free_list[MIGRATE_TYPES];
unsigned long nr_free;
};
Why is it an array of linked lists and not just one list? Without delving into the details, we'll mention that, in reality...