0

From this question, I can conclude that the page entry size is usually 4 bytes for 32-bit systems.

But looking at the source code of Linux to see how pages are represented, here, I can see that the size of the struct is way bigger than 4 bytes.

The code for the page struct:

struct page {
    unsigned long flags;        /* Atomic flags, some possibly
                     * updated asynchronously */
    /*
     * Five words (20/40 bytes) are available in this union.
     * WARNING: bit 0 of the first word is used for PageTail(). That
     * means the other users of this union MUST NOT use the bit to
     * avoid collision and false-positive PageTail().
     */
    union {
        struct {    /* Page cache and anonymous pages */
            /**
             * @lru: Pageout list, eg. active_list protected by
             * pgdat->lru_lock.  Sometimes used as a generic list
             * by the page owner.
             */
            struct list_head lru;
            /* See page-flags.h for PAGE_MAPPING_FLAGS */
            struct address_space *mapping;
            pgoff_t index;      /* Our offset within mapping. */
            /**
             * @private: Mapping-private opaque data.
             * Usually used for buffer_heads if PagePrivate.
             * Used for swp_entry_t if PageSwapCache.
             * Indicates order in the buddy system if PageBuddy.
             */
            unsigned long private;
        };
        struct {    /* page_pool used by netstack */
            /**
             * @dma_addr: might require a 64-bit value even on
             * 32-bit architectures.
             */
            dma_addr_t dma_addr;
        };
        struct {    /* slab, slob and slub */
            union {
                struct list_head slab_list;
                struct {    /* Partial pages */
                    struct page *next;
#ifdef CONFIG_64BIT
                    int pages;  /* Nr of pages left */
                    int pobjects;   /* Approximate count */
#else
                    short int pages;
                    short int pobjects;
#endif
                };
            };
            struct kmem_cache *slab_cache; /* not slob */
            /* Double-word boundary */
            void *freelist;     /* first free object */
            union {
                void *s_mem;    /* slab: first object */
                unsigned long counters;     /* SLUB */
                struct {            /* SLUB */
                    unsigned inuse:16;
                    unsigned objects:15;
                    unsigned frozen:1;
                };
            };
        };
        struct {    /* Tail pages of compound page */
            unsigned long compound_head;    /* Bit zero is set */

            /* First tail page only */
            unsigned char compound_dtor;
            unsigned char compound_order;
            atomic_t compound_mapcount;
            unsigned int compound_nr; /* 1 << compound_order */
        };
        struct {    /* Second tail page of compound page */
            unsigned long _compound_pad_1;  /* compound_head */
            atomic_t hpage_pinned_refcount;
            /* For both global and memcg */
            struct list_head deferred_list;
        };
        struct {    /* Page table pages */
            unsigned long _pt_pad_1;    /* compound_head */
            pgtable_t pmd_huge_pte; /* protected by page->ptl */
            unsigned long _pt_pad_2;    /* mapping */
            union {
                struct mm_struct *pt_mm; /* x86 pgds only */
                atomic_t pt_frag_refcount; /* powerpc */
            };
#if ALLOC_SPLIT_PTLOCKS
            spinlock_t *ptl;
#else
            spinlock_t ptl;
#endif
        };
        struct {    /* ZONE_DEVICE pages */
            /** @pgmap: Points to the hosting device page map. */
            struct dev_pagemap *pgmap;
            void *zone_device_data;
            /*
             * ZONE_DEVICE private pages are counted as being
             * mapped so the next 3 words hold the mapping, index,
             * and private fields from the source anonymous or
             * page cache page while the page is migrated to device
             * private memory.
             * ZONE_DEVICE MEMORY_DEVICE_FS_DAX pages also
             * use the mapping, index, and private fields when
             * pmem backed DAX files are mapped.
             */
        };

        /** @rcu_head: You can use this to free a page by RCU. */
        struct rcu_head rcu_head;
    };

    union {     /* This union is 4 bytes in size. */
        /*
         * If the page can be mapped to userspace, encodes the number
         * of times this page is referenced by a page table.
         */
        atomic_t _mapcount;

        /*
         * If the page is neither PageSlab nor mappable to userspace,
         * the value stored here may help determine what this page
         * is used for.  See page-flags.h for a list of page types
         * which are currently stored here.
         */
        unsigned int page_type;

        unsigned int active;        /* SLAB */
        int units;          /* SLOB */
    };

    /* Usage count. *DO NOT USE DIRECTLY*. See page_ref.h */
    atomic_t _refcount;

#ifdef CONFIG_MEMCG
    union {
        struct mem_cgroup *mem_cgroup;
        struct obj_cgroup **obj_cgroups;
    };
#endif

    /*
     * On machines where all RAM is mapped into kernel address space,
     * we can simply calculate the virtual address. On machines with
     * highmem some memory is mapped into kernel virtual memory
     * dynamically, so we need a place to store that address.
     * Note that this field could be 16 bits on x86 ... ;)
     *
     * Architectures with slow multiplication can define
     * WANT_PAGE_VIRTUAL in asm/page.h
     */
#if defined(WANT_PAGE_VIRTUAL)
    void *virtual;          /* Kernel virtual address (NULL if
                       not kmapped, ie. highmem) */
#endif /* WANT_PAGE_VIRTUAL */

#ifdef LAST_CPUPID_NOT_IN_PAGE_FLAGS
    int _last_cpupid;
#endif
} _struct_page_alignment;

Does the kernel maintain an another representation for the pages other than the page table? What is the relationship between this struct and the page table entries?

Does the kernel use this struct to represent only used pages? What is this struct used for?

The picture is not so clear to me.

Acorn
  • 24,970
  • 5
  • 40
  • 69
StackExchange123
  • 1,871
  • 9
  • 24
  • 1
    Lots of questions. Sounds like you need recommendations for some good books, or such...? – ryyker Aug 24 '20 at 20:26
  • This is really kind of circular. You are linking another question/answer, (which in turn links another question/answer,) that discuss the topic in detail. What makes this question unique, i.e. what is new here that you could not learn from the link you provided (and its links.)? – ryyker Aug 24 '20 at 20:37
  • I'm only linking the question to indicate that PTE size is 4 bytes. nothing less, nothing more. – StackExchange123 Aug 24 '20 at 20:42
  • I'm asking about something specific in linux whereas that question asks about some general concept about OSs. – StackExchange123 Aug 24 '20 at 20:43
  • Fair enough. Lets see where it goes :) It still seems like you have questions enough that reading a good book on Linux architecture would probably be more satisfying. – ryyker Aug 24 '20 at 20:47
  • @ryyker If the questions need a lot of reading to get an answer for them, then a book would probably be a good solution. But if there is a short convincing answer, I'd be thankful. If you have any recommendation, I'd also be thankful. – StackExchange123 Aug 24 '20 at 20:58
  • Here is a link to what looks like a pretty good write up specific to [Linux page management](https://www.kernel.org/doc/gorman/html/understand/understand006.html). It seems like a good read, but I would search around to corroborate what it says. – ryyker Aug 24 '20 at 21:51

1 Answers1

1

Page table entries store the address of the next page table in the hierarchy, along with some other flags, depending on the architecture. Look at Paging - OSDev

enter image description here


The comments are pretty clear to what struct page is.

/*
 * Each physical page in the system has a struct page associated with
 * it to keep track of whatever it is we are using the page for at the
 * moment.
 */

To conclude, it simply stores information on frames.

Tony Tannous
  • 14,154
  • 10
  • 50
  • 86