今回はbuild_all_zonelists関数から呼び出している「__build_all_zonelists」を見てみます。その名の通りすべてのノードのzonelistをビルドするのですが、「ノードをビルドする」とはなんなのか?と。
実体はbuild_all_zonelistsと同じmm/page_alloc.cにあります
========
static int __build_all_zonelists(void *dummy)
{
int nid;
for_each_online_node(nid) {
pg_data_t *pgdat = NODE_DATA(nid);
build_zonelists(pgdat);
build_zonelist_cache(pgdat);
}
return 0;
}
========
ノードリストから一つ一つゾーンリストを取り出してbuild_zonelists、build_zonelist_cacheしています。
「pg_dat_t」というのはノードごとにメモリを管理するための構造体です。
詳しくは「LinuxKernelHackJapan」の解説をどうぞ。
次にここから呼び出している「build_zonelists」を見てみます。
実体は同じファイルにあります。
======
static void build_zonelists(pg_data_t *pgdat)
{
~(変数宣言)~
/* ゾーンリストを初期化する */
for (i = 0; i < MAX_ZONELISTS; i++) {
zonelist = pgdat->node_zonelists + i;
zonelist->_zonerefs[0].zone = NULL;
zonelist->_zonerefs[0].zone_idx = 0;
}
/* used_maskをゼロ埋め */
local_node = pgdat->node_id;
load = num_online_nodes();
prev_node = local_node;
nodes_clear(used_mask);
/* 色々初期化 */
memset(node_load, 0, sizeof(node_load));
memset(node_order, 0, sizeof(node_order));
j = 0;
/* ゾーンリストに追加する最適なノードを探す */
while ((node = find_next_best_node(local_node, &used_mask)) >= 0) {
/* local_nodeとnodeが同じノードを指しているかどうか(違っていれば1) */
int distance = node_distance(local_node, node);
/* 異なるノードで再利用するのに十分に離れたノードであった場合 */
if (distance > RECLAIM_DISTANCE)
zone_reclaim_mode = 1;
/* ノードの割り当てが局所化しないように、注意しながらloadするノードを格納 */
if (distance != node_distance(local_node, prev_node))
node_load[node] = load;
prev_node = node;
load--;
/* ノードの順序に従って格納してやる */
if (order == ZONELIST_ORDER_NODE)
build_zonelists_in_node_order(pgdat, node);
else
node_order[j++] = node; /* remember order */
}
if (order == ZONELIST_ORDER_ZONE) {
/* calculate node order -- i.e., DMA last! */
build_zonelists_in_zone_order(pgdat, j);
}
/* 自ノードのゾーンリストを構築する */
build_thisnode_zonelists(pgdat);
}
======
長かったのだけど、いまいちチンプンカンプンなのだ。。
ページの管理はゾーンという単位でおこなっていて、ノードごとにどのゾーンからページを確保するかという順番を決めるゾーンリストがあります。そのゾーンリストがノードごとにあって、ここではゾーンリストを構築している、という処理になります。
ここから呼び出している関数はまた次回から順に見ていきます。
start_kernelに戻る日はいつなのだろう。。
0 件のコメント:
コメントを投稿