<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Linux Kernel]]></title><description><![CDATA[This blog is to discuss various topics about Linux kernel. The content is based on Kernel version 6.17]]></description><link>https://linux-kernel.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Fri, 18 Sep 2026 01:20:04 GMT</lastBuildDate><atom:link href="https://linux-kernel.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Memory Management]]></title><description><![CDATA[Page Cache
A part of the disk is maintained in physical RAM known as Page Cache. This cache is used to improve the performance of the system. A read or write from the physical memory is faster than from the disk.

The page cache consists of actual ph...]]></description><link>https://linux-kernel.hashnode.dev/memory-management</link><guid isPermaLink="true">https://linux-kernel.hashnode.dev/memory-management</guid><category><![CDATA[memory-management]]></category><category><![CDATA[linux kernel]]></category><category><![CDATA[caching]]></category><dc:creator><![CDATA[Datta Prabhu M]]></dc:creator><pubDate>Wed, 03 Dec 2025 03:22:45 GMT</pubDate><content:encoded><![CDATA[<h2 id="heading-page-cache">Page Cache</h2>
<p>A part of the disk is maintained in physical RAM known as Page Cache. This cache is used to improve the performance of the system. A read or write from the physical memory is faster than from the disk.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764729938257/e5ca8e8c-acf5-4da6-88bb-0a6fce531d2e.png" alt class="image--center mx-auto" /></p>
<p>The page cache consists of actual physical pages in RAM(not virtual), the contents of which correspond to the blocks on a disk. The size of this cache can grow dynamically, increases if more memory is available or shrinks for any memory pressure.</p>
<p>Whenever a read() call is performed by the process, the data is read from the Page cache. If required pages are found, then its called a <strong><em>cache-hit,</em></strong> otherwise its a <strong><em>cache-miss,</em></strong> during which block I/O operations are performed and the data is copied from the disk to the cache and read again.</p>
<p>When the process does a write() call, there are three strategies available.</p>
<ul>
<li><em>A write() operation directly writes data to the disk. This strategy is called</em> <strong>no-write,</strong> <em>as shown below. If the data need to be read, it needs to be fetched into the cache first and then perform a read operation. This is not efficient strategy and is rarely used.</em></li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764731560672/47a78d4e-2c93-4b8c-8740-dd7865dbf092.png" alt class="image--center mx-auto" /></p>
<ul>
<li>In the second strategy, the data is written to both the cache and the disk. This way, a further read operation will get a cache-hit. Though this is good, the overall time to copy to the disk undermines having a cache in the first place.</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764731739655/e890c820-d007-4bab-b770-46724e82f352.png" alt class="image--center mx-auto" /></p>
<ul>
<li>In the third case, data is written to the cache first. The backing store is not updated yet. Instead, the written to pages are marked as dirty and are added to the dirty list. Periodically, dirty pages are written back to the disk in a process called <em>writeback</em>, bringing the on-disk copy in line with the on-cache copy. The pages are no longer dirty after this happens. This strategy is used in Linux.</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764732088630/6772d2d7-8c3d-44ce-a307-e1ff0fca4e34.png" alt class="image--center mx-auto" /></p>
]]></content:encoded></item><item><title><![CDATA[Process Management]]></title><description><![CDATA[This blog will discuss process creation and termination from the programmer’s point of view.
Process creation
Init is the first process that gets spawned during the boot process and this process gets process Id 1. All the other processes are created ...]]></description><link>https://linux-kernel.hashnode.dev/process-management</link><guid isPermaLink="true">https://linux-kernel.hashnode.dev/process-management</guid><dc:creator><![CDATA[Datta Prabhu M]]></dc:creator><pubDate>Thu, 20 Nov 2025 01:24:50 GMT</pubDate><content:encoded><![CDATA[<p>This blog will discuss process creation and termination from the programmer’s point of view.</p>
<h2 id="heading-process-creation">Process creation</h2>
<p>Init is the first process that gets spawned during the boot process and this process gets process Id 1. All the other processes are created using a system call called, fork().</p>
<p>The process which calls the fork is called the parent process and the process which gets created as a result of the fork call is called a child process. A child process will get the parent process Id (PPID) that of the parent process which created it.</p>
<p>A new <em>task_struct</em> data structure gets created, every time a new process gets created. The memory requirements are handled by the SLAB cache.</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">task_struct has been discussed in another blog <a target="_self" href="https://hashnode.com/post/cmh9g1f8g000002l50rzi3wqv">here</a>.</div>
</div>

<p>Let’s see how a process is created.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763241892194/c8d77534-3f01-47a2-9ea9-aae5fd9e1a19.png" alt /></p>
<ul>
<li><p>A parent process calls fork() system call.</p>
</li>
<li><p>The fork() call is intercepted in ‘./kernel/fork.c’ and calls kernel_clone(). The later takes a parameter called <em>flags. Flags</em> help decide which resources can be shared between the child and the parent process.</p>
</li>
</ul>
<blockquote>
<p>flags have been explained later in this blog.</p>
</blockquote>
<ul>
<li><p>In kernel_clone(), a call to copy_process() creates a new process( say p), but not activated or scheduled yet. This step involves copying the relevant resources as per the <em>flags defined.</em></p>
</li>
<li><p>Process ‘p’ is scheduled and it starts running.</p>
</li>
</ul>
<p>Different flags that decide how the child process will be created as below:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>CLONE_VM</td><td>Parent and Child share address space</td></tr>
</thead>
<tbody>
<tr>
<td>CLONE_FILES</td><td>Parent and Child share open files</td></tr>
<tr>
<td>CLONE_FS</td><td>Parent and Child share file system information</td></tr>
<tr>
<td>CLONE_SIGHAND</td><td>Parent and Child share the signal handlers and blocked signals</td></tr>
<tr>
<td>CLONE_PIDFD</td><td>If pidfd of the child should be placed in the parent process</td></tr>
<tr>
<td>CLONE_PTRACE</td><td>Continue tracing the child too</td></tr>
<tr>
<td>CLONE_VFORK</td><td>Used when vfork() is used instead of the fork(). Parent process will be forced to sleep until the child process returns</td></tr>
<tr>
<td>CLONE_PARENT</td><td>Child enforces to have the same parent which created it</td></tr>
<tr>
<td>CLONE_THREAD</td><td>Parent and child are in the same thread group</td></tr>
<tr>
<td>CLONE_NEWNS</td><td>Create a new namespace for the child process</td></tr>
<tr>
<td>CLONE_SYSVSEM</td><td>Parent and child share the system-V semantics</td></tr>
<tr>
<td>CLONE_SETTLS</td><td>Create a new TLS for the child process</td></tr>
<tr>
<td>CLONE_PARENT_SETTID</td><td>Set the TID in the parent</td></tr>
<tr>
<td>CLONE_CHILD_CLEARTID</td><td>Clear the TID in the child</td></tr>
<tr>
<td>CLONE_CHILD_SETTID</td><td>Set the TID of the child</td></tr>
<tr>
<td>CLONE_DETACHED</td><td>Detach and ignore the child process</td></tr>
<tr>
<td>CLONE_UNTRACED</td><td>Ignore the CLONE_PTRACE on the child</td></tr>
<tr>
<td>CLONE_NEWCGROUP</td><td>Create a new cgroup namespace</td></tr>
<tr>
<td>CLONE_NEWUTS</td><td>Create a new utsname namespace</td></tr>
<tr>
<td>CLONE_NEWIPC</td><td>Create a new ipc namespace</td></tr>
<tr>
<td>CLONE_NEWUSER</td><td>Create a new user namespace</td></tr>
<tr>
<td>CLONE_NEWPID</td><td>Create a new pid namespace</td></tr>
<tr>
<td>CLONE_NEWNET</td><td>Create a new network namespace</td></tr>
<tr>
<td>CLONE_IO</td><td>Clone the IO context</td></tr>
</tbody>
</table>
</div><p><strong>copy_process()</strong></p>
<ul>
<li><p>Make a call to dup_task_struct(), which creates a new kernel stack, thread_info and task_struct structure for the new process. The new values are identical to those of the current task. At this point, the child and parent process descriptors are identical.</p>
</li>
<li><p>It then checks that the new child will not exceed the resource limits on the number of processes for the current user.</p>
</li>
<li><p>The child needs to differentiate itself from the parent. Various members of the process descriptor are cleared or set to initial values. Members of the process descriptor not inherited are primarily statistically information. The bulk of the values in task_struct remain unchanged.</p>
</li>
<li><p>The child’s state is set to TASK_UNINTERRUPTIBLE to ensure that it does not yet run.</p>
</li>
<li><p>copy_process() calls copy_flags() to update the flags member of he task_struct.</p>
</li>
<li><p>It calls alloc_pid() to assign an available PID to the new task.</p>
</li>
<li><p>Depending on the flags passed to kernel_clone(), copy_process() either duplicates or shares open files, filesystem information, signal handlers, process address space and namespace. These resources are typically shared between threads in the same process, otherwise they are unique and thus copied here.</p>
</li>
<li><p>Finally, copy_process() cleans up and returns to the caller a pointer to the new child.</p>
</li>
</ul>
<p><strong>Process states</strong></p>
<p>Each process goes through the below states, through its life time.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764350143856/5fad2a20-2436-49fb-89de-1addc830f07d.png" alt class="image--center mx-auto" /></p>
<ul>
<li><p>When the process gets created, it gets the TASK_RUNNING(ready) status. In this state, the process is ready to be run by the scheduler.</p>
</li>
<li><p>Once the scheduler puts the process to run, its state is moved to TASK_RUNNING(running) status.</p>
</li>
<li><p>When the process is pre-emptied by the scheduler for another higher priority one, it moves back from TASK_RUNNING(running) to TASK_RUNNING(ready) state.</p>
</li>
<li><p>When a process waits for any event(like IO), its moved to TASK_INTERRUPTABLE(waiting) state.</p>
</li>
<li><p>When the event is full-filled, the process is moved back to TASK_RUNNING(ready) state.</p>
</li>
<li><p>When a process calls exit() or receives any signal or exception, it is moved to TASK_STOPPPED state and is terminated.</p>
</li>
</ul>
<hr />
<h2 id="heading-process-address-space">Process address space</h2>
<blockquote>
<p>Linux is a virtual memory operating system, meaning the physical memory is virtualized for each process. Meaning, each process’s view of memory is as if it has the entire physical memory to access.</p>
</blockquote>
<p>The process address space consists of the virtual memory addressable by a process and the address within the virtual memory that the process is allowed to use. Each process is given a flat 32-bit or 64-bit address space, with the size dependent on the architecture.</p>
<p>A memory address is a given value in the given address space, <strong>0X5012E300</strong>. This value identifies a byte in a process’s 32-bit address space. A process address applicable for a particular process can be represented as a range, for ex, <strong>0X0400A000 - 0X0400AFFF</strong>. These intervals are usually called memory areas. The process, through the kernel, can add or remove memory areas to its address space.</p>
<blockquote>
<p>Each memory area is associated with permissions like readable, writable and executable.If a process accesses any address which it doesn’t have permission to, it results in segmentation fault.</p>
</blockquote>
<p>Each process is associated with the below memory areas:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764286582632/718a3652-2676-456d-9d7e-b3db211ce3eb.png" alt class="image--center mx-auto" /></p>
<ul>
<li><p>A memory map of the executable file’s code, called a <strong><em>text</em></strong> section.</p>
</li>
<li><p>A memory map of the executable file’s initialized global variables, called the <strong><em>data</em></strong> section.</p>
</li>
<li><p>A memory map of the executable file’s uninitialized global variables, called the <strong>bss</strong> section.</p>
</li>
<li><p>A memory map for the process’s user space stack.</p>
</li>
<li><p>An additional text, data and bss section for each of the shared library( such as glibc, dynamic linker etc) loaded into the process’s address space.</p>
</li>
<li><p>Any memory mapped files.</p>
</li>
<li><p>Any shared memory segments(ipc related).</p>
</li>
<li><p>Any anonymous memory mappings, such as those associated with malloc().</p>
</li>
</ul>
<hr />
<h2 id="heading-virtual-memory-areas">Virtual memory areas</h2>
<p>Each of the color coded segment in the above process address space is called a virtual memory area(VMA). This is represented by a data structure called <strong>vm_area_struct,</strong> which is defined in the file ./linux/mm_types.h.</p>
<p>The above process address space may look like below with VMAs</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764288773551/89c55694-6836-4a65-a9c5-8c793600a0e0.png" alt class="image--center mx-auto" /></p>
<p>Programmatically, each process is represented by a data structure of type ‘struct task_struct’. This data structure has a field called ‘struct mm_struct’ which maintains a linked list of type ‘struct vm_area_struct’.</p>
<p>Each of the VMA has a start address (vm_start) and ending address(vm_end). All the address ranges being held by the process are virtual in nature. We will learn later that each of the VMA points to the physical memory through <strong>pages</strong>.</p>
<p>System calls like mmap(), mmap2(), do_mmap() can be used to add VMAs. System calls like munmap() and do_munmap() can be used to remove them.</p>
<blockquote>
<p>More about memory management will be covered in another blog</p>
</blockquote>
<hr />
<p><strong>Process address space in real life…</strong></p>
<p>Let’s create some simple and sample programs and check practically how the process address space looks like by running some commands.</p>
<details><summary>Commands</summary><div data-type="detailsContent">We can use commands like ‘pmap &lt;pid&gt;’ or ‘cat /proc/&lt;pid&gt;/maps’ to read the process address map of a process. The first command gives a more user friendly output. We can use these commands only when the process is running.</div></details>

<ol>
<li><p>A program with no global, static or local variables. I am using C but the program language shouldn’t matter.</p>
<pre><code class="lang-c"> <span class="hljs-meta">#<span class="hljs-meta-keyword">include</span><span class="hljs-meta-string">&lt;unistd.h&gt;</span></span>

 <span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">(<span class="hljs-keyword">int</span> argc, <span class="hljs-keyword">char</span> *argv[])</span> </span>{ 
   <span class="hljs-meta"># without this sleep() command, the process doesnt persists for </span>
   <span class="hljs-meta"># enough time to get the details</span>
   sleep(<span class="hljs-number">100</span>);
   <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
 }
</code></pre>
</li>
</ol>
<p>The process address space is as below. The memory range may be different each time. Also, the memory ranges may not be contiguous, as the kernel assigns the memory as per the availability.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764447784300/b200874b-517a-499d-8bcf-93499a7bd46d.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764447806856/4542c0f3-9fd2-4b25-bd7a-a5651f333ef3.png" alt class="image--center mx-auto" /></p>
<p>Let’s try to understand what each of the above attributes mean:</p>
<ul>
<li><p>[vdso]: <strong>V</strong>irtual <strong>D</strong>ynamically Linked <strong>S</strong>hared <strong>O</strong>bjects. This is a mechanism through which the interaction between the user space and kernel space is optimized for better performance.</p>
</li>
<li><p>[vsyscall]: This is a static allocation (each process uses the same vma), used to optimize the system call performance. The output of the system call is stored here for future reference. Very similar to cache used in other places.</p>
</li>
<li><p>[vvar]: Not much information is available about this vma.</p>
</li>
<li><p>[stack]: This vma is the user space stack. We have read and write permissions on this vma.</p>
</li>
<li><p>[ anon ]: vma for anonymous memory. This memory is usually assigned to the process by the kernel which is not backed by a file on the file system. Mostly for internal purposes.</p>
</li>
<li><p>[libc.so.6]: This is the C library(glibc), which is required to interpret the code.There are 5 entries, as below:</p>
<ul>
<li><p>r——: This is a vma of type ‘rodata’(read only) for the C library(libc.so.6)</p>
</li>
<li><p>r-x—: This is a vma with read and execute permissions, meaning this hold the actual code of text of libc.so.6</p>
</li>
<li><p>r——: Another ‘rodata’ vma</p>
</li>
<li><p>r——: Another ‘rodata’ vma</p>
</li>
<li><p>rw—-: A read and write vma(rwdata) for the variables which allows reads and writes.</p>
</li>
</ul>
</li>
<li><p>[ld-linux-x86-64.so.2]: This is a dynamic linker which is required to link the code with other shared libraries. We have similar ‘rodata ‘and ‘rwdata’ vmas for this library, similar to glibc.</p>
</li>
<li><p>[p1]: This is my actual C code file name. Kernel has assigned 5 vma’s for this code too, similar to above entries.</p>
</li>
</ul>
<p>As you might have noted, a minimum of 4K has been assigned for each vma. This is the page size on my machine. All the memory assignments are in multiples of this pagesize.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764449199544/bdb53473-ab2b-43a7-b07b-4a878265d4d2.png" alt class="image--center mx-auto" /></p>
<p>Also, a total of 2616K (2.6 MB) has been assigned even to a simple program like this.</p>
<ol start="2">
<li><p>Process address map for all the below scenarios were same as above.</p>
<ul>
<li><p>A program with an uninitialized global variable.</p>
</li>
<li><p>A program with initialized or uninitialized local variables.</p>
</li>
<li><p>A program with static variables.</p>
</li>
</ul>
</li>
</ol>
<p>    This means that the kernel assigns a minimum of one page size memory to each vma irrespective of whether the program needs it or not.</p>
<ol start="3">
<li><p>A program makes a call to malloc() for dynamic memory allocation.</p>
<pre><code class="lang-c"> <span class="hljs-meta">#<span class="hljs-meta-keyword">include</span><span class="hljs-meta-string">&lt;unistd.h&gt;</span></span>
 <span class="hljs-meta">#<span class="hljs-meta-keyword">include</span><span class="hljs-meta-string">&lt;cstdlib&gt;</span></span>
 <span class="hljs-meta">#<span class="hljs-meta-keyword">include</span><span class="hljs-meta-string">&lt;cstring&gt;</span></span>

 <span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">emp_det</span> {</span>
         <span class="hljs-keyword">long</span> emp_id;
         <span class="hljs-keyword">char</span> name[<span class="hljs-number">100</span>];
 };

 <span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">(<span class="hljs-keyword">int</span> argc, <span class="hljs-keyword">char</span> *argv[])</span> </span>{
   <span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">emp_det</span>* <span class="hljs-title">ep</span> = (<span class="hljs-title">struct</span> <span class="hljs-title">emp_det</span> *)<span class="hljs-title">malloc</span>(<span class="hljs-title">sizeof</span>(<span class="hljs-title">struct</span> <span class="hljs-title">emp_det</span>));</span>
   ep-&gt;emp_id = <span class="hljs-number">1234</span>;
   <span class="hljs-built_in">strcpy</span>(ep-&gt;name, <span class="hljs-string">"citika"</span>);

   sleep(<span class="hljs-number">100</span>);
   <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
 }
</code></pre>
</li>
</ol>
<p>The process address space in this case as shown below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764455619727/005ba035-bcbd-4ede-9da7-ac0145ac6fa4.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764455645685/509088b6-52d5-4d94-ae66-db0457cc54c4.png" alt class="image--center mx-auto" /></p>
<p>As you can see, there is an extra 132K of memory assignment to a [heap] region. This is for the dynamic allotments for the call to malloc().</p>
<ol start="4">
<li><p>Two processes which are running the same code.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764456256545/4b745828-db5c-4869-bc0b-5345fc489085.png" alt class="image--center mx-auto" /></p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764456271404/ac4d032f-846f-46fe-a23d-7947cb3943ed.png" alt class="image--center mx-auto" /></p>
<p> Both the process address maps look similar. Also, note that though they use the same glibc and linker’s, they are mapped to different vmas. This is an interesting finding, as the expectation was all the processes which use the same shared libraries point to the same memory areas.</p>
</li>
<li><p>A child process created using the fork() system call. The goal is to check the process memory space for both the child and parent.</p>
<pre><code class="lang-c"> <span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;stdio.h&gt;</span></span>
 <span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;unistd.h&gt;</span></span>
 <span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;sys/types.h&gt;</span></span>
 <span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;sys/wait.h&gt;</span></span>

 <span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span> </span>{
     <span class="hljs-keyword">pid_t</span> pid = fork();

     <span class="hljs-keyword">if</span> (pid &lt; <span class="hljs-number">0</span>) {
         <span class="hljs-comment">// fork() failed</span>
         perror(<span class="hljs-string">"fork failed"</span>);
         <span class="hljs-keyword">return</span> <span class="hljs-number">1</span>;
     }
     <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (pid == <span class="hljs-number">0</span>) {
         <span class="hljs-comment">// Child process</span>
         <span class="hljs-built_in">printf</span>(<span class="hljs-string">"Child process: PID = %d, Parent PID = %d\n"</span>,
                getpid(), getppid());

         <span class="hljs-comment">// Simulate some work</span>
         sleep(<span class="hljs-number">100</span>);

         <span class="hljs-built_in">printf</span>(<span class="hljs-string">"Child exiting...\n"</span>);
     }
     <span class="hljs-keyword">else</span> {
         <span class="hljs-comment">// Parent process</span>
         <span class="hljs-built_in">printf</span>(<span class="hljs-string">"Parent process: PID = %d, waiting for child PID = %d\n"</span>,
                getpid(), pid);

         <span class="hljs-keyword">int</span> status;
         wait(&amp;status);   <span class="hljs-comment">// Wait for child to finish</span>

         <span class="hljs-built_in">printf</span>(<span class="hljs-string">"Parent: child exited with status %d\n"</span>, WEXITSTATUS(status));
     }

     <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
 }
</code></pre>
<p> Process address map of the parent is:</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764458043288/57bc61db-57e0-46a3-99ca-1e8b43aa263b.png" alt class="image--center mx-auto" /></p>
<p> Process address map of the child is:</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764458060874/385cf0b5-b272-4465-ab2b-2293c658acf8.png" alt class="image--center mx-auto" /></p>
<p> As you see, the parent and child are sharing the same process address space.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764458400164/da558475-aa6e-4fa5-8c4d-20d3455b4701.png" alt class="image--center mx-auto" /></p>
<p> This is as per the design technique called Copy-On-Write(CoW) in which the kernel delays assigning the child to new address space until it is required. In this case, child process was not doing anything and hence was sharing the parent address space. This technique allows faster process execution.</p>
</li>
<li><p>Let’s see a case where a child process is created and executes a new program. Here we are making the child process run ‘ls’ program.</p>
</li>
</ol>
<pre><code class="lang-c"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;stdio.h&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;unistd.h&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;sys/types.h&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;sys/wait.h&gt;</span></span>

<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">pid_t</span> pid = fork();

    <span class="hljs-keyword">if</span> (pid &lt; <span class="hljs-number">0</span>) {
        perror(<span class="hljs-string">"fork failed"</span>);
        <span class="hljs-keyword">return</span> <span class="hljs-number">1</span>;
    }
    <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (pid == <span class="hljs-number">0</span>) {
        <span class="hljs-comment">// Child process</span>
        <span class="hljs-built_in">printf</span>(<span class="hljs-string">"Child: PID = %d, Parent PID = %d\n"</span>, getpid(), getppid());
        <span class="hljs-built_in">printf</span>(<span class="hljs-string">"Child: sleeping for 100 seconds inside exec...\n"</span>);

        <span class="hljs-comment">// exec: run "sleep 100; ls -l"</span>
        execl(<span class="hljs-string">"/bin/sh"</span>, <span class="hljs-string">"sh"</span>, <span class="hljs-string">"-c"</span>, <span class="hljs-string">"sleep 100; ls -l"</span>, <span class="hljs-literal">NULL</span>);

        <span class="hljs-comment">// Only reached if exec fails</span>
        perror(<span class="hljs-string">"exec failed"</span>);
        <span class="hljs-keyword">return</span> <span class="hljs-number">1</span>;
    }
    <span class="hljs-keyword">else</span> {
        <span class="hljs-comment">// Parent process</span>
        <span class="hljs-built_in">printf</span>(<span class="hljs-string">"Parent: PID = %d, Child PID = %d\n"</span>, getpid(), pid);
        <span class="hljs-built_in">printf</span>(<span class="hljs-string">"Parent: waiting for child to finish...\n"</span>);

        <span class="hljs-keyword">int</span> status;
        wait(&amp;status);

        <span class="hljs-built_in">printf</span>(<span class="hljs-string">"Parent: child exited with status %d\n"</span>, WEXITSTATUS(status));
    }

    <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
</code></pre>
<p>The parent process address map is as shown below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764459949091/ceefe4a8-5d46-4719-9728-3d2f8efa41ba.png" alt class="image--center mx-auto" /></p>
<p>The child process address map is as shown below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764459970204/500b6211-12c4-4968-a809-7f4576b1b9b3.png" alt class="image--center mx-auto" /></p>
<p>As you can see, both parent and child are using different process address spaces.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764460445054/086e30f7-2c58-4e2e-ac46-b40e252b847c.png" alt class="image--center mx-auto" /></p>
<p>Again, its CoW feature working behind the scenes.</p>
<hr />
<h2 id="heading-process-termination">Process Termination</h2>
<p>A Process is terminated in the below ways:</p>
<ul>
<li><p>A voluntary termination when the process calls exit() call or just a ‘return’ statement.</p>
</li>
<li><p>An involuntary termination happens when the process receives a signal or exception which it cannot handle or ignore.</p>
</li>
</ul>
<p>When a process exits, a series of actions happen, which might be the reverse of the actions during the process creation. Process runs do_exit() call which takes care of the process termination.</p>
<ul>
<li><p>Set the PF_EXITING flag in the flags member of task_struct.</p>
</li>
<li><p>Call del_timer_sync() to remove any kernel timers, which might have been activated for this process.</p>
</li>
<li><p>Flush out the accounting information, when it is set.</p>
</li>
<li><p>Calls the exit_mm() to release the mm_struct held by the process. If no other process is using this address space, then release the memory from the slab cache.</p>
</li>
<li><p>Calls exit_sem(), to release any IPC related semaphore’s from the waiting queues.</p>
</li>
<li><p>Calls exit_files() and exit_fs() to decrement the usage count of the objects related to file descriptors and file system data. If this count is zero, then remove the entries from the slab cache too.</p>
</li>
<li><p>Set the exit_code in the task_struct construct as volunteered by the exit process.</p>
</li>
<li><p>Calls exit_notify() to send signals to the parent process. This process children are de-parented to any other process in the same thread group or to the init process. The exit_state in the task_struct is set to EXIT_ZOMBIE.</p>
</li>
<li><p>Send communication to the scheduler to schedule another process. This happens as the final step in the do_exit() and this call never returns.</p>
</li>
</ul>
<p>At this stage, the process is not in runnable state and doesn’t have any process address space of its own and is in EXIT_ZOMBIE state. The only memory associated is with the task_struct, thread_info in the slab cache. This memory exists so that the parent process can claim some information out of it. Once this is completed, the slab cache is freed too.</p>
<blockquote>
<p>A process becomes zombie, when its parent tries to clear the process table of the dead child(alive parent and dead child).</p>
<p>A process becomes orphan when its parent is dead and is being re-parented(dead parent and alive child).</p>
</blockquote>
<hr />
]]></content:encoded></item><item><title><![CDATA[Data structures in Linux kernel]]></title><description><![CDATA[struct task_struct:
For every process that is created in the user space, kernel creates and maintains a data structure of type ‘struct task_struct’. This structure has all the information that the kernel needs to perform process management, scheduler...]]></description><link>https://linux-kernel.hashnode.dev/data-structures-in-linux-kernel</link><guid isPermaLink="true">https://linux-kernel.hashnode.dev/data-structures-in-linux-kernel</guid><dc:creator><![CDATA[Datta Prabhu M]]></dc:creator><pubDate>Mon, 27 Oct 2025 18:00:45 GMT</pubDate><content:encoded><![CDATA[<h3 id="heading-struct-taskstruct"><strong>struct task_struct:</strong></h3>
<p>For every process that is created in the user space, kernel creates and maintains a data structure of type ‘struct task_struct’. This structure has all the information that the kernel needs to perform process management, scheduler management, memory management etc on this process. This data structure is stored in the kernel stack and is active as long as the process is alive. This structure is defined in &lt;linux/sched.h&gt;</p>
<p>Below is the list of attributes this structure holds and the purpose of each attribute.</p>
<table><tbody><tr><td><p><strong>sl no</strong></p></td><td><p><strong>Attribute name</strong></p></td><td><p><strong>Attribute type</strong></p></td><td><p><strong>Config setting needed</strong></p></td><td><p><strong>Attribute Usage</strong></p></td></tr><tr><td><p>1</p></td><td><p>thread_info</p></td><td><p>struct thread_info</p></td><td><p>CONFIG_THREAD_INFO_IN_TASK</p></td><td><p>Used for storing low level CPU information related to threads belonging to the process. Mainly it provides information on which CPU the thread is running, CPU conext and CPU flags used for the threads</p></td></tr><tr><td><p>2</p></td><td><p><strong>state</strong></p></td><td><p>unsigned int</p></td><td><p></p></td><td><p>Store the process state, like TASK_RUNNABLE, TASK_INTERRUPTABLE etc</p></td></tr><tr><td><p>3</p></td><td><p>saved_state</p></td><td><p>unsigned int</p></td><td><p></p></td><td><p>This state refers to the status of trying to acquire a spinlock, common in multi-threaded applications. If lock acquisition fails, the thread is put to sleep and this state is preserved as "sleeping". It has nothing to do with the _state of the process.</p></td></tr><tr><td><p>4</p></td><td><p>stack</p></td><td><p>void <em></em></p></td><td><p></p></td><td><p>Refers to the tasks kernel-stack. Usually used to get the thread_info from a variable of type struct task_struct, as in the macro: #define task_thread_info(task) ((struct thread_info )(task)-&gt;stack)</p></td></tr><tr><td><p>5</p></td><td><p>usage</p></td><td><p>refcount_t</p></td><td><p></p></td><td><p>Used to count the number of references to the process(users)</p></td></tr><tr><td><p>6</p></td><td><p>flags</p></td><td><p>unsigned int</p></td><td><p></p></td><td><p>various flags used by the process for varous purposes.</p></td></tr><tr><td><p>7</p></td><td><p>ptrace</p></td><td><p>unsigned int</p></td><td><p></p></td><td><p>Holds the flags related to ptrace status of a process</p></td></tr><tr><td><p>8</p></td><td><p>alloc_tag</p></td><td><p>struct alloc_tag</p></td><td><p>CONFIG_MEM_ALLOC_PROFILING</p></td><td><p>used to track the memory allocations by the kernel</p></td></tr><tr><td><p>9</p></td><td><p>on_cpu</p></td><td><p>int</p></td><td><p></p></td><td><p>Serves as a lock mechanism for dealing with context switching b/w processes. When on_cpu is 0,it means this process is not running on any CPU and can be scheduled to run on any other CPUs. If set to any other value, this information helps in proper migration of the process across CPUs and avoid data inconsistencies.</p></td></tr><tr><td><p>10</p></td><td><p>wake_entry</p></td><td><p>struct call_single_node</p></td><td><p></p></td><td><p>This entry plays a role in how the scheduler wakes the processes to be scheduled, in the SMP environments.</p></td></tr><tr><td><p>11</p></td><td><p>wakee_flips</p></td><td><p>unsigned int</p></td><td><p></p></td><td><p>Helps the scheduler to track and make decisions about where to schedule based on previous wakeup patterns</p></td></tr><tr><td><p>12</p></td><td><p>wakee_flip_decay_ts</p></td><td><p>unsigned long</p></td><td><p></p></td></tr><tr><td><p>13</p></td><td><p>last_wakee</p></td><td><p>struct task_struct</p></td><td><p></p></td></tr><tr><td><p>14</p></td><td><p>recent_used_cpu</p></td><td><p>int</p></td><td><p></p></td><td><p>Recently used CPU by a process. Usually used for re-schedule on the same CPU if found idle.</p></td></tr><tr><td><p>15</p></td><td><p>wake_cpu</p></td><td><p>int</p></td><td><p></p></td><td><p>Represents the CPU where the process is intended to be woken up or woke up last</p></td></tr><tr><td><p>16</p></td><td><p>on_rq</p></td><td><p>int</p></td><td><p></p></td><td><p>Indicates the presence of a process on a run queue. Each CPU has its own run queue.<br />Can take two values:<br />1.TASK_ON_RQ_QUEUED : Process is on a CPU running queue.<br />2. TASK_ON_RQ_MIGRATING: Process is being moved from one running queue to another.<br /><br />This attribute helps with synchronisation of the processes on the running queues and helps with scheduling.</p></td></tr><tr><td><p>17</p></td><td><p>prio</p></td><td><p>int</p></td><td><p></p></td><td><p>This field is used by the scheduled to decide which process should be scheduled next. This value can be adjusted by the kernel dynamically or is based on 'nice' values.</p></td></tr><tr><td><p>18</p></td><td><p>static_prio</p></td><td><p>int</p></td><td><p></p></td><td><p>This value represents the nice value of the process which can be set by the users. This value cannot be dynamically adjusted by the kernel like 'prio'</p></td></tr><tr><td><p>19</p></td><td><p>normal_prio</p></td><td><p>int</p></td><td><p></p></td><td><p>This field is the default priority calculated based on the static_prio and real-time priority. This is important in fork() where the child process prio is set to the normal_prio of the parent.</p></td></tr><tr><td><p>20</p></td><td><p>rt_priority</p></td><td><p>unsigned int</p></td><td><p></p></td><td><p>This field is used for managing the real-time processes, usually used in embedded systems. This field is used by real-time scheduling algorithms like SCHED_FIFO, SCHED_RR. This value can be set by system calls.</p></td></tr><tr><td><p>21</p></td><td><p>se</p></td><td><p>struct sched_entity</p></td><td><p></p></td><td><p>This represents the scheduling entity used by the default Linux scheduler CFS(Completely Fair Scheduler)</p></td></tr><tr><td><p>22</p></td><td><p>rt</p></td><td><p>struct sched_rt_entity</p></td><td><p></p></td><td><p>This represents the scheduling entity used by the Real-Time scheduler classes like SCHED_FIFO and SCHED_RR</p></td></tr><tr><td><p>23</p></td><td><p>dl</p></td><td><p>struct sched_dl_entity</p></td><td><p></p></td><td><p>These represents the scheduling entity used by the Earliest Deadline First scheduler like SCHED_DEADLINE</p></td></tr><tr><td><p>24</p></td><td><p>dl_server</p></td><td><p>struct sched_dl_entity <em></em></p></td><td><p></p></td></tr><tr><td><p>25</p></td><td><p>scx</p></td><td><p>struct sched_ext_entity</p></td><td><p>CONFIG_SCHED_CLASS_EXT</p></td><td><p>This entry represents the scheduling class called sched_ext(called SCX)</p></td></tr><tr><td><p>26</p></td><td><p>sched_class</p></td><td><p>struct sched_class</p></td><td><p></p></td><td><p>This represents the scheduling class used by the process such as CFS, RT, DL etc</p></td></tr><tr><td><p>27</p></td><td><p>core_node</p></td><td><p>struct rb_node</p></td><td><p>CONFIG_SCHED_CORE</p></td><td><p>This field is used in the implementation of the control groups feature(cgroups). This field is controlled by CONFIG_SCHED_CORE setting</p></td></tr><tr><td><p>28</p></td><td><p>core_cookie</p></td><td><p>unsigned long</p></td><td><p></p></td><td><p>This field relates to core scheduler, a mechanism where all the related processes are made to schedule on the same physical CPU to improve performance. Each of these processes have the same ‘core_cookie’ value. Based on this value, the process's scheduling is optimized by the core scheduler. This field is controlled by CONFIG_SCHED_CORE setting.</p></td></tr><tr><td><p>29</p></td><td><p>core_occupation</p></td><td><p>unsigned int</p></td><td><p></p></td><td><p>This field is controlled by CONFIG_SCHED_CORE setting. Not much information is available why this is used for.</p></td></tr><tr><td><p>30</p></td><td><p>sched_task_group</p></td><td><p>struct task_group </p></td><td><p>CONFIG_CGROUP_SCHED</p></td><td><p>This field is used to categorize processes into a cgroup hierarchy.</p></td></tr><tr><td><p>31</p></td><td><p>uclamp_req</p></td><td><p>struct uclamp_se</p></td><td><p>CONFIG_UCLAMP_TASK</p></td><td><p>These fields allow the user to specify the min and max utilization allowed for RUNNABLE processes.</p></td></tr><tr><td><p>32</p></td><td><p>uclamp</p></td><td><p>struct uclamp_se</p></td><td><p>CONFIG_UCLAMP_TASK</p></td></tr><tr><td><p>33</p></td><td><p>stats</p></td><td><p>struct sched_statistics</p></td><td><p></p></td><td><p>This field is used to collect and track the performance metrics of the scheduler. Some of the metrics involved are execution times, number of context switches etc</p></td></tr><tr><td><p>34</p></td><td><p>preempt_notifiers</p></td><td><p>struct hlist_head</p></td><td><p>CONFIG_PREEMPT_NOTIFIERS</p></td><td><p>This field provides a mechanism to register callbacks that are executed whenever the process is pre-emptied or re-scheduled.</p></td></tr><tr><td><p>35</p></td><td><p>btrace_seq</p></td><td><p>unsigned int</p></td><td><p>CONFIG_BLK_DEV_IO_TRACE</p></td><td><p>This field helps track the block I/O requests for this process</p></td></tr><tr><td><p>36</p></td><td><p>policy</p></td><td><p>unsigned int</p></td><td><p></p></td><td><p>This field determines scheduling policy like SCHED_FIFO, SCHED_RR etc. Looks like a duplicated effort, we have other fields like ece, rt, dl, dl_serve which do the same thing</p></td></tr><tr><td><p>37</p></td><td><p>max_allowed_capacity</p></td><td><p>unsigned long</p></td><td><p></p></td><td><p>This field represents how much of CPU capacity a process is allowed to consume. Again looks like a duplicated effort.</p></td></tr><tr><td><p>38</p></td><td><p>nr_cpus_allowed</p></td><td><p>int</p></td><td><p></p></td><td><p>This field represents the number of CPUs a process is allowed to run on</p></td></tr><tr><td><p>39</p></td><td><p>cpus_ptr</p></td><td><p>const cpumask_t<em></em></p></td><td><p></p></td><td><p>This field points to a pointer of type cpumask_t, which represents number of CPUs a process is allowed to run on, duplicates the earlier nr_cpus_allowed field</p></td></tr><tr><td><p>40</p></td><td><p>user_cpus_ptr</p></td><td><p>cpumask_t </p></td><td><p></p></td><td><p>This field points to the cpumask_t pointer specifically requested by a user for a particular process</p></td></tr><tr><td><p>41</p></td><td><p>cpus_mask</p></td><td><p>cpumask_t</p></td><td><p></p></td><td><p>Again this field represents a variable of type cpumask_t which provides the CPU affinity of a process</p></td></tr><tr><td><p>42</p></td><td><p>migration_pending</p></td><td><p>void <em></em></p></td><td><p></p></td><td><p>This field is an indicator to represent that this process is waiting for a pending migration to a different CPU</p></td></tr><tr><td><p>43</p></td><td><p>migration_disabled</p></td><td><p>unsigned short</p></td><td><p></p></td><td><p>This field indicates if a migration is possible across CPUs</p></td></tr><tr><td><p>44</p></td><td><p>migration_flags</p></td><td><p>unsigned short</p></td><td><p></p></td><td><p>This field is used to control and track the migration effort within the system</p></td></tr><tr><td><p>45</p></td><td><p>rcu_read_lock_nesting</p></td><td><p>int</p></td><td><p>CONFIG_PREEMPT_RCU</p></td><td><p>RCU stands for Read-Copy Update, a mechanism used to synchronize data structures shared across threads within a process. This field is a counter to represent the read-side critical sections of a thread.</p></td></tr><tr><td><p>46</p></td><td><p>rcu_read_unlock_special</p></td><td><p>union rcu_special</p></td><td><p>CONFIG_PREEMPT_RCU</p></td><td><p>This field represents the state when the thread is in read-side critical section.</p></td></tr><tr><td><p>47</p></td><td><p>rcu_node_entry</p></td><td><p>struct list_head</p></td><td><p>CONFIG_PREEMPT_RCU</p></td><td><p>All the threads, which are in RCU read-side critical sections are added to a list. This field rcu_node_entry acts as the head of that list.</p></td></tr><tr><td><p>48</p></td><td><p>rcu_blocked_node</p></td><td><p>struct rcu_node</p></td><td><p>CONFIG_PREEMPT_RCU</p></td><td><p>This field is not NULL If the present thread is blocking the RCU read-side critical section, otherwise NULL</p></td></tr><tr><td><p>49</p></td><td><p>rcu_tasks_nvcsw</p></td><td><p>unsigned long</p></td><td><p>CONFIG_TASKS_RCU</p></td><td><p>This field tracks the voluntary context switches undergone by a thread. This parameter is useful in implementing the RCU mechanism</p></td></tr><tr><td><p>50</p></td><td><p>rcu_tasks_holdout</p></td><td><p>u8</p></td><td><p>CONFIG_TASKS_RCU</p></td><td><p>This field acts as a signal for the RCU subsystem, that a particular thread, needs to finish on the RCU read-side critical sections before the end of the grace period allotted.</p></td></tr><tr><td><p>51</p></td><td><p>rcu_tasks_idx</p></td><td><p>u8</p></td><td><p>CONFIG_TASKS_RCU</p></td><td><p>This field helps to understand if the thread, is in the RCU read-side critical section of exited it, for tracking purposes.</p></td></tr><tr><td><p>52</p></td><td><p>rcu_tasks_idle_cpu</p></td><td><p>int</p></td><td><p>CONFIG_TASKS_RCU</p></td><td><p>This field tracks on which CPU a particular idle task is executing on.</p></td></tr><tr><td><p>53</p></td><td><p>rcu_tasks_holdout_list</p></td><td><p>struct list_head</p></td><td><p>CONFIG_TASKS_RCU</p></td><td><p>This field is a list head which represents the list of threads that are currently being holding out on the grace period.</p></td></tr><tr><td><p>54</p></td><td><p>rcu_tasks_exit_cpu</p></td><td><p>int</p></td><td><p>CONFIG_TASKS_RCU</p></td><td><p>This field tracks the threads, that are exiting a RCU grace period.</p></td></tr><tr><td><p>55</p></td><td><p>rcu_tasks_exit_list</p></td><td><p>struct list_head</p></td><td><p>CONFIG_TASKS_RCU</p></td><td><p>This field is a list which is used to track the threads, which are exiting the RCU read-side critical sections.</p></td></tr><tr><td><p>56</p></td><td><p>trc_reader_nesting</p></td><td><p>int</p></td><td><p>CONFIG_TASKS_TRACE_RCU</p></td><td><p>This field is a counter to track the threads passing in and out of the RCU critical regions. Used for tracking purposes.</p></td></tr><tr><td><p>57</p></td><td><p>trc_ipi_to_cpu</p></td><td><p>int</p></td><td><p>CONFIG_TASKS_TRACE_RCU</p></td><td><p>IPI stands for Inter-Processor Interrupts. These are interrupts used by a CPU to interrupt another CPU. This field is used to store the CPU id that needs to be interrupted</p></td></tr><tr><td><p>58</p></td><td><p>trc_reader_special</p></td><td><p>union rcu_special</p></td><td><p>CONFIG_TASKS_TRACE_RCU</p></td><td><p>This field is used for handling and tracking purposes by threads in the RCU system which act as RCU readers</p></td></tr><tr><td><p>59</p></td><td><p>trc_holdout_list</p></td><td><p>struct list_head</p></td><td><p>CONFIG_TASKS_TRACE_RCU</p></td><td><p>This field is a list head which represents the list of threads that are currently being holding out on the grace period.</p></td></tr><tr><td><p>60</p></td><td><p>trc_blkd_node</p></td><td><p>struct list_head</p></td><td><p>CONFIG_TASKS_TRACE_RCU</p></td><td><p>This list represent the list which holds information on all the threads which are waiting for the RCU grace period to be completed so that they can perform an update operation</p></td></tr><tr><td><p>61</p></td><td><p>trc_blkd_cpu</p></td><td><p>int</p></td><td><p>CONFIG_TASKS_TRACE_RCU</p></td><td><p>This field holds the CPU information on which the RCU operations have been blocked</p></td></tr><tr><td><p>62</p></td><td><p>sched_info</p></td><td><p>struct shed_info</p></td><td><p></p></td><td><p>This field holds scheduler information like how many times this process has been run on a particular CPU, amount of time spent in a run queue etc</p></td></tr><tr><td><p>63</p></td><td><p>tasks</p></td><td><p>struct list_head</p></td><td><p></p></td><td><p>There is no much information about this field but could be holding information all the process in the system</p></td></tr><tr><td><p>64</p></td><td><p>pushable_tasks</p></td><td><p>struct plist_node</p></td><td><p></p></td><td><p>This field represents the list of tasks which can be pushed to other runqueues, which are not so busy</p></td></tr><tr><td><p>65</p></td><td><p>pushable_dl_tasks</p></td><td><p>struct rb_node</p></td><td><p></p></td><td><p>This field represents the tasks which are ready to be scheduled by the deadline scheduler.</p></td></tr><tr><td><p>66</p></td><td><p>mm</p></td><td><p>struct mm_struct </p></td><td><p></p></td><td><p>This field represents the entire virtual address space allocated for this process</p></td></tr><tr><td><p>67</p></td><td><p>active_mm</p></td><td><p>struct mm_struct <em></em></p></td><td><p></p></td><td><p>This field represents the currently active part of the memory address space. Usually used by kernel threads as 'mm' field is NULL for them.</p></td></tr><tr><td><p>68</p></td><td><p>faults_disabled_mapping</p></td><td><p>struct address_space</p></td><td><p></p></td><td><p>This field acts as a temporary marker that tells that the page faults for a particular memory region should be handled in a special way</p></td></tr><tr><td><p>69</p></td><td><p>exit_state</p></td><td><p>int</p></td><td><p></p></td><td><p>This field is used to store the exit state of a process. It can take two values:<br />1. EXIT_ZOMBIE: Indicates that the process is done with its execution but the resources are not freed yet. This happens when the child process exited but the parent process didn't call wait() yet.<br />2. EXIT_DEAD: Indicates that the process is done with its execution and its resources have been freed too. Happens immediately after the parent process calls the wait4() call on a zombie process.</p></td></tr><tr><td><p>70</p></td><td><p>exit_code</p></td><td><p>int</p></td><td><p></p></td><td><p>This field stores the exit status of a process. Usually its zero(0) when exited successfully and non-zero if not.</p></td></tr><tr><td><p>71</p></td><td><p>exit_signal</p></td><td><p>int</p></td><td><p></p></td><td><p>This field is usually the signal sent to the parent process when a child process is dead. Usually this is SIGCHLD</p></td></tr><tr><td><p>72</p></td><td><p>pdeath_signal</p></td><td><p>int</p></td><td><p></p></td><td><p>This field indicates the signal sent when a parent process dies</p></td></tr><tr><td><p>73</p></td><td><p>jobctl</p></td><td><p>unsigned long</p></td><td><p></p></td><td><p>This field is used to process the job control flags for a process or thread</p></td></tr><tr><td><p>74</p></td><td><p>personality</p></td><td><p>unsigned int</p></td><td><p></p></td><td><p>This field represents the execution domain of a process. The way some system calls behave differently for a process are based on this information</p></td></tr><tr><td><p>75</p></td><td><p>sched_reset_on_fork</p></td><td><p>unsigned</p></td><td><p></p></td><td><p>This is a flag used by the parent process to control the inheritance of privileged scheduling mechanisms by the child processed, acquired through the fork() process. Used mostly for security purposes.</p></td></tr><tr><td><p>76</p></td><td><p>sched_contributes_to_load</p></td><td><p>unsigned</p></td><td><p></p></td><td><p>When this flag is set, this processes system load is included in the load average calculation</p></td></tr><tr><td><p>77</p></td><td><p>sched_migrated</p></td><td><p>unsigned</p></td><td><p></p></td><td><p>This flag is set when a process is migrated from one CPU to the another. Helps the scheduler to track the process location and manage its scheduling on the new CPU</p></td></tr><tr><td><p>78</p></td><td><p>sched_task_hot</p></td><td><p>unsigned</p></td><td><p></p></td><td><p>When a process frequently uses data that resides in a particular CPU cache, its considered "cache hot" for that CPU. Moving such a process to a different CPU can lead to performance degration as the data needs to be re-loaded for that CPU. If this flag is set, it can work as a strong affinity for that CPU. A scheduler might hesitate to migrate such a process from that CPU for performance issues.</p></td></tr><tr><td><p>79</p></td><td><p>sched_remote_wakeup</p></td><td><p>unsigned</p></td><td><p></p></td><td><p>This field acts as a flag to indicate if the process has been remotely woken up by another CPU</p></td></tr><tr><td><p>80</p></td><td><p>sched_rt_mutex</p></td><td><p>unsigned</p></td><td><p>CONFIG_RT_MUTEXES</p></td><td><p>When a real-time process acquires an RT mutex, this flag is set to 1, indicating that this process is in the middle of the critical section. This is an indicator to the scheduler to handle it accordingly.</p></td></tr><tr><td><p>81</p></td><td><p>in_execve</p></td><td><p>unsigned</p></td><td><p></p></td><td><p>This field indicates if the process is in the middle of an execve() call</p></td></tr><tr><td><p>82</p></td><td><p>in_iowait</p></td><td><p>unsigned</p></td><td><p></p></td><td><p>This field indicates if the process is waiting on an I/O activity</p></td></tr><tr><td><p>83</p></td><td><p>restore_sigmask</p></td><td><p>unsigned</p></td><td><p>TIF_RESTORE_SIGMASK</p></td><td><p>This field indicates if the process sigmask needs to be reset after handling a signal handler</p></td></tr><tr><td><p>84</p></td><td><p>in_user_fault</p></td><td><p>unsigned</p></td><td><p>CONFIG_MEMCG_V1</p></td><td><p>This field indicates if the process is handling a user-space page fault</p></td></tr><tr><td><p>85</p></td><td><p>in_lru_fault</p></td><td><p>unsigned</p></td><td><p>CONFIG_LRU_GEN</p></td><td><p>This field indicates if the process is handling a page fault that involves LRU page replacement system</p></td></tr><tr><td><p>86</p></td><td><p>brk_randomized</p></td><td><p>unsigned</p></td><td><p>CONFIG_COMPAT_BRK</p></td><td><p>This field indicates if the heap area of the process is randomized(starts at a different address), for security purposes</p></td></tr><tr><td><p>87</p></td><td><p>no_cgroup_migration</p></td><td><p>unsigned</p></td><td><p>CONFIG_CGROUPS</p></td><td><p>When this field is set to 1, then it indicates that this process cannot be moved to a different cgroup.</p></td></tr><tr><td><p>88</p></td><td><p>frozen</p></td><td><p>unsigned</p></td><td><p>CONFIG_CGROUPS</p></td><td><p>This flag indicates if the process is immune to system wide freezing</p></td></tr><tr><td><p>89</p></td><td><p>use_memdelay</p></td><td><p>unsigned</p></td><td><p>CONFIG_BLK_CGROUP</p></td><td><p>Usually used in allowing a memory delay for disk I/O throttling operations</p></td></tr><tr><td><p>90</p></td><td><p>in_memstall</p></td><td><p>unsigned</p></td><td><p>CONFIG_PSI</p></td><td><p>This field is used to indicate if the process is stalled due to non-availability of the system resources, especially memory</p></td></tr><tr><td><p>91</p></td><td><p>in_page_owner</p></td><td><p>unsigned</p></td><td><p>CONFIG_PAGE_OWNER</p></td><td><p>This field is used to avoid recursion while page tracking</p></td></tr><tr><td><p>92</p></td><td><p>in_eventfd</p></td><td><p>unsigned</p></td><td><p>CONFIG_EVENTFD</p></td><td><p>This field indicates if the process is currently in the execution context of the eventfd_signal() function</p></td></tr><tr><td><p>93</p></td><td><p>pasid_activated</p></td><td><p>unsigned</p></td><td><p>CONFIG_ARCH_HAS_CPU_PASID</p></td><td><p>This field indicates if the Process Address Space Id (PAS ID) has been activated for this process</p></td></tr><tr><td><p>94</p></td><td><p>reported_split_lock</p></td><td><p>unsigned</p></td><td><p>CONFIG_X86_BUS_LOCK_DETECT</p></td><td><p>This field is used to indicate if a split lock has been detected for the process</p></td></tr><tr><td><p>95</p></td><td><p>in_thrashing</p></td><td><p>unsigned</p></td><td><p>CONFIG_TASK_DELAY_ACCT</p></td><td><p>Thrashing usually indicates the situation where the kernel spends more time swapping the data between physical memory and secondary disk than doing some useful work. This field is set to indicate that this process is experiencing thrashing like behavior.</p></td></tr><tr><td><p>96</p></td><td><p>in_nf_duplicate</p></td><td><p>unsigned</p></td><td><p></p></td><td><p>This field indicates that the process is currently involved in Netfilter packet duplication operations.</p></td></tr><tr><td><p>97</p></td><td><p>net_xmit</p></td><td><p>struct netdev_xmit</p></td><td><p>CONFIG_PREEMPT_RT</p></td><td><p>This field helps in managing aspects of network transmission related to the process.</p></td></tr><tr><td><p>98</p></td><td><p>atomic_flags</p></td><td><p>unsigned long</p></td><td><p></p></td><td><p>This field has list of flags related to a process or thread that need to be modified and read in an atomic manner</p></td></tr><tr><td><p>99</p></td><td><p>restart_block</p></td><td><p>struct restart_block</p></td><td><p></p></td><td><p>This field is used to define the restart behavior of the system calls.</p></td></tr><tr><td><p>100</p></td><td><p>pid</p></td><td><p>pid_t</p></td><td><p></p></td><td><p>Unique id of the process</p></td></tr><tr><td><p>101</p></td><td><p>tgid</p></td><td><p>pid_t</p></td><td><p></p></td><td><p>Pocess id of the Thread Group leader</p></td></tr><tr><td><p>102</p></td><td><p>stack_canary</p></td><td><p>unsigned long</p></td><td><p>CONFIG_STACKPROTECTOR</p></td><td><p>This field is used as a security measure to deal with the stack buffer overflow attacks</p></td></tr><tr><td><p>103</p></td><td><p>real_parent</p></td><td><p>struct task_struct </p></td><td><p></p></td><td><p>This field is a pointer to the parent process</p></td></tr><tr><td><p>104</p></td><td><p>parent</p></td><td><p>struct task_struct <em></em></p></td><td><p></p></td><td><p>This field is a pointer to the parent which is supposed to receive the SIGCHLD signal</p></td></tr><tr><td><p>105</p></td><td><p>children</p></td><td><p>struct list_head</p></td><td><p></p></td><td><p>This field is a list of children created through the fork mechanism</p></td></tr><tr><td><p>106</p></td><td><p>sibling</p></td><td><p>struct list_head</p></td><td><p></p></td><td><p>This field is a list of siblings which have been created through the fork mechanism of which this process is a part of</p></td></tr><tr><td><p>107</p></td><td><p>group_leader</p></td><td><p>struct task_struct </p></td><td><p></p></td><td><p>This field is a pointer to the primary thread within a thread group</p></td></tr><tr><td><p>108</p></td><td><p>ptraced</p></td><td><p>struct list_head</p></td><td><p></p></td><td><p>This field is a list of process on which this process has put a ptrace on</p></td></tr><tr><td><p>109</p></td><td><p>ptrace_entry</p></td><td><p>struct list_head</p></td><td><p></p></td><td><p>This field is a pointer to the entry of this process's parent ptraced entries</p></td></tr><tr><td><p>110</p></td><td><p>thread_pid</p></td><td><p>struct pid <em></em></p></td><td><p></p></td><td><p>This fieldis is a pointer to the process pid structure</p></td></tr><tr><td><p>111</p></td><td><p>pid_links</p></td><td><p>struct hlist_node</p></td><td><p></p></td><td><p>This field is an array of size PIDTYPE_MAX(whose value is 4) of type struct hlist_nodes</p></td></tr><tr><td><p>112</p></td><td><p>thread_node</p></td><td><p>struct list_head</p></td><td><p></p></td><td><p>This field connects all the threads belongign to the same thread group</p></td></tr><tr><td><p>113</p></td><td><p>vfork_done</p></td><td><p>struct completion </p></td><td><p></p></td><td><p>This field is used to synchronize between parent and child process when vfork is used</p></td></tr><tr><td><p>114</p></td><td><p>set_child_tid</p></td><td><p>int</p></td><td><p></p></td><td><p>This field is to set the tid of child process ot thread when using the clone() system call</p></td></tr><tr><td><p>115</p></td><td><p>clear_child_tid</p></td><td><p>int</p></td><td><p></p></td><td><p>This field is used to wakeup the processes when a thread is terminated</p></td></tr><tr><td><p>116</p></td><td><p>worker_private</p></td><td><p>void <em></em></p></td><td><p></p></td><td><p>Thsi field is a pointer to the struct kthread when the process creates kernel threads using the kthread interface.</p></td></tr><tr><td><p>117</p></td><td><p>utime</p></td><td><p>u64</p></td><td><p></p></td><td><p>This field is the amount of CPU time the process has spent executing in the user space</p></td></tr><tr><td><p>118</p></td><td><p>stime</p></td><td><p>u64</p></td><td><p></p></td><td><p>This field is the amount of CPU time the process has spent executing in the kernel space</p></td></tr><tr><td><p>119</p></td><td><p>utimescaled</p></td><td><p>u64</p></td><td><p>CONFIG_ARCH_HAS_SCALED_CPUTIME</p></td><td><p>This field implies that the raw time value might be adjusted based on factors like CPU frequency scaling or other system level considerations</p></td></tr><tr><td><p>120</p></td><td><p>stimescaled</p></td><td><p>u64</p></td><td><p>CONFIG_ARCH_HAS_SCALED_CPUTIME</p></td></tr><tr><td><p>121</p></td><td><p>gtime</p></td><td><p>u64</p></td><td><p></p></td><td><p>This field is the total CPU time spent by all the threads in a proces group</p></td></tr><tr><td><p>122</p></td><td><p>prev_cputime</p></td><td><p>struct prev_cputime</p></td><td><p></p></td><td><p>This field is a struct which contains utime and stime as members. Looks like a duplicated effort.</p></td></tr><tr><td><p>123</p></td><td><p>vtime</p></td><td><p>struct vtime</p></td><td><p>CONFIG_VIRT_CPU_ACCOUNTING_GEN</p></td><td><p>Thsi field tracks the virtual time a process spends in kernel, mostly not when consuming the CPU time, but waiting for some events to happen, like waiting on I/O events</p></td></tr><tr><td><p>124</p></td><td><p>tick_dep_mask</p></td><td><p>atomic_t</p></td><td><p>CONFIG_NO_HZ_FULL</p></td><td><p>This field helps the kernel determine whether a CPU needs to maintain a timer tick or if it can safely go into a tickless idle state, to improve power efficiency</p></td></tr><tr><td><p>125</p></td><td><p>nvcsw</p></td><td><p>unsigned long</p></td><td><p></p></td><td><p>This field is a counter of voluntary context switches. Happens when a process or thread voluntariliy relinquishes the CPU while waiting for I/O activity etc</p></td></tr><tr><td><p>126</p></td><td><p>nivcsw</p></td><td><p>unsigned long</p></td><td><p></p></td><td><p>This field is a counter of involuntary context switches, happens when a process is preemptied by the kernel</p></td></tr><tr><td><p>127</p></td><td><p>start_time</p></td><td><p>u64</p></td><td><p></p></td><td><p>This field represents the process creation time, based on a monotonic clock, which never goes backwards</p></td></tr><tr><td><p>128</p></td><td><p>start_boottime</p></td><td><p>u64</p></td><td><p></p></td><td><p>This field represents the process creation time, relative to the system boot time. Usually used by 'ps' and 'top' commands to display the process creation time.</p></td></tr><tr><td><p>129</p></td><td><p>min_flt</p></td><td><p>unsigned long</p></td><td><p></p></td><td><p>This field is a counter for the minor page faults experienced by the process</p></td></tr><tr><td><p>130</p></td><td><p>maj_flt</p></td><td><p>unsigned long</p></td><td><p></p></td><td><p>This field is a counter for the major page faults experienced by the process</p></td></tr><tr><td><p>131</p></td><td><p>posix_cputimers</p></td><td><p>struct posix_cputimers</p></td><td><p>CONFIG_POSIX_CPUTIMERS</p></td><td><p>This field holds all the POSIX CPU timers like CPUCLOCK_PROF, CPUCLOCK_VIRT, CPUCLOCK_SHED etc</p></td></tr><tr><td><p>132</p></td><td><p>posix_cputimers_work</p></td><td><p>struct posix_cputimers_work</p></td><td><p>CONFIG_POSIX_CPU_TIMERS_TASK_WORK</p></td><td><p>Thie field helps mange the work related to the CPU timers for the process or thread</p></td></tr><tr><td><p>133</p></td><td><p>ptracer_cred</p></td><td><p>struct cred </p></td><td><p></p></td><td><p>This field is a data structure which encapsulates all the securty related credentials of the process or thread</p></td></tr><tr><td><p>134</p></td><td><p>real_cred</p></td><td><p>struct cred <em></em></p></td><td><p></p></td></tr><tr><td><p>135</p></td><td><p>cred</p></td><td><p>struct cred </p></td><td><p></p></td></tr><tr><td><p>136</p></td><td><p>cashed_requested_key</p></td><td><p>struct key <em></em></p></td><td><p>CONFIG_KEYS</p></td><td><p>This field points to a structure which can provide the key management service for the kernel</p></td></tr><tr><td><p>137</p></td><td><p>nameidata</p></td><td><p>struct nameidata </p></td><td><p></p></td><td><p>This field is a structure which facilitates the conversion of a pathname to real VFS based file object entity. Calls like stat(), open(), link() use this data structure</p></td></tr><tr><td><p>138</p></td><td><p>sysvsem</p></td><td><p>struct sysv_sem</p></td><td><p>CONFIG_SYSVIPC</p></td><td><p>This field stores all the semaphore information attached to the process or thread</p></td></tr><tr><td><p>139</p></td><td><p>sysvshm</p></td><td><p>struct sysv_shm</p></td><td><p>CONFIG_SYSVIPC</p></td><td><p>This field stores all the shared memory associated with this process or thread</p></td></tr><tr><td><p>140</p></td><td><p>last_switch_count</p></td><td><p>unsigned long</p></td><td><p></p></td><td><p>This field is used by the process hung detector which is used to track and identify the processes which have become unresponsive(blocked for a long time)</p></td></tr><tr><td><p>141</p></td><td><p>last_switch_time</p></td><td><p>unsigned long</p></td><td><p></p></td></tr><tr><td><p>142</p></td><td><p>fs</p></td><td><p>struct fs_struct <em></em></p></td><td><p></p></td><td><p>This field encapsulates the file system context of the process</p></td></tr><tr><td><p>143</p></td><td><p>files</p></td><td><p>struct files_struct </p></td><td><p></p></td><td><p>This field encapsulates the open files information of the process.</p></td></tr><tr><td><p>144</p></td><td><p>io_uring</p></td><td><p>struct io_uring_task <em></em></p></td><td><p>CONFIG_IO_URING</p></td><td><p>This field points to a pointer to io_uring which can help with submssion and retrieval of the I/ O operations for this process</p></td></tr><tr><td><p>145</p></td><td><p>nsproxy</p></td><td><p>struct nsproxy </p></td><td><p></p></td><td><p>This field is a pointer to various namespaces as implemented in Linux</p></td></tr><tr><td><p>146</p></td><td><p>signal</p></td><td><p>struct signal_struct <em></em></p></td><td><p></p></td><td><p>This field is a pointer to the signal_struct which handles the signals and process groups in the kernel</p></td></tr><tr><td><p>147</p></td><td><p>sighand</p></td><td><p>struct sighand_struct </p></td><td><p></p></td><td><p>This field acts as signal handler for the process. All the threads in the same process group share the same signal handler information</p></td></tr><tr><td><p>148</p></td><td><p>blocked</p></td><td><p>sigset_t</p></td><td><p></p></td><td><p>This field stores all the blocked signals by the process</p></td></tr><tr><td><p>149</p></td><td><p>real_blocked</p></td><td><p>sigset_t</p></td><td><p></p></td><td><p>This field is for real-time signals blocked by the process</p></td></tr><tr><td><p>150</p></td><td><p>saved_sigmask</p></td><td><p>sigset_t</p></td><td><p></p></td><td><p>This field stores the signal mask before a thread enters the critical section and restores it after coming out. This is part of the signal handling mechanism that the kernal performs.</p></td></tr><tr><td><p>151</p></td><td><p>pending</p></td><td><p>struct sigpending</p></td><td><p></p></td><td><p>This field holds all the signals which are waiting to be delivered to the thread or process</p></td></tr><tr><td><p>152</p></td><td><p>sas_ss_sp</p></td><td><p>unsigned long</p></td><td><p></p></td><td><p>SAS stands for Signal Alternate Stack, which is a feature where the user is allowed to use an alternative stack for handling the signals. By default, the process uses the user-space stack for handling the signals. sas_ss_sp is a pointer to the stack, sas_ss_size is the size of SAS stack and sas_ss_flags is the list of flags used to control the SAS stack</p></td></tr><tr><td><p>153</p></td><td><p>sas_ss_size</p></td><td><p>size_t</p></td><td><p></p></td></tr><tr><td><p>154</p></td><td><p>sas_ss_flags</p></td><td><p>unsigned int</p></td><td><p></p></td></tr><tr><td><p>155</p></td><td><p>task_works</p></td><td><p>struct callback_head</p></td><td><p></p></td><td><p>This field refers to the list of work items that are pending to be executed bythe process. Usually a callback mechanism is implemented for such queues.</p></td></tr><tr><td><p>156</p></td><td><p>audit_context</p></td><td><p>struct audit_context <em></em></p></td><td><p>CONFIG_AUDIT, CONFIG_AUDITSYSCALL</p></td><td><p>This structure is used by the Linux Audit Subsystem to collect and store information related to system calls and other auditable events by the process or thread</p></td></tr><tr><td><p>157</p></td><td><p>loginuid</p></td><td><p>kuid_t</p></td><td><p>CONFIG_AUDIT</p></td><td><p>This field represents the login user id of the user who initiated the session that spawned the current process</p></td></tr><tr><td><p>158</p></td><td><p>sessionid</p></td><td><p>unsigned int</p></td><td><p>CONFIG_AUDIT</p></td><td><p>This field identifies the session to which the process belongs to.</p></td></tr><tr><td><p>159</p></td><td><p>seccomp</p></td><td><p>struct seccomp</p></td><td><p></p></td><td><p>Secure Computing Mode(seccomp) is a fearure supported by kernel to filter the system calls made by the process,thereby enhancing the security by limiting the attack surface</p></td></tr><tr><td><p>160</p></td><td><p>syscall_dispatch</p></td><td><p>struct syscall_user_dispatch</p></td><td><p></p></td><td><p>The syscall user dispatch feature allows the userspace programs to register a handler that can incercept system calls before they are exeucted by the kernel. This helps in monitoring and analyzing system calls for debugging and performance analysis.</p></td></tr><tr><td><p>161</p></td><td><p>parent_exec_id</p></td><td><p>u64</p></td><td><p></p></td><td><p>This is counter which is available in each child process and its initial value is self_exec_id value from its parent.</p></td></tr><tr><td><p>162</p></td><td><p>self_exec_id</p></td><td><p>u64</p></td><td><p></p></td><td><p>A counter in the current process that is incremented each time the process successfully executes a new program using the execve() system call</p></td></tr><tr><td><p>163</p></td><td><p>alloc_lock</p></td><td><p>spinlock_t</p></td><td><p></p></td><td><p>Spinlocks are crucial for protecting shared data structures in the kernel from race conditins, specially in multi processor environments. alloc_lock is a spinlock which helps protect various critical fields in the proces or thread like 'fs', 'files', ''mm' etc</p></td></tr><tr><td><p>164</p></td><td><p>pi_lock</p></td><td><p>raw_spinlock_t</p></td><td><p></p></td><td><p>The 'raw' form of spinlock refers to the basic or low-level form of spinlock available in the kernel. These locks are designed for critical sections where interrupt handlers are already disabled or disabling is not required.</p></td></tr><tr><td><p>165</p></td><td><p>wake_q</p></td><td><p>struct wake_q_node</p></td><td><p></p></td><td><p>This is a pointer to a list of process or threads waiting to be woken up. Helps in cases where multiple processes are waiting to be woken up.</p></td></tr><tr><td><p>166</p></td><td><p>pi_waiters</p></td><td><p>struct rb_root_cached</p></td><td><p>CONFIG_RT_MUTEXES</p></td><td><p>This structure is used to manage and schedule the tasks virtual runtime as part of the CFS(Completely Fair Scheduler) scheduler mechanism</p></td></tr><tr><td><p>167</p></td><td><p>pi_top_task</p></td><td><p>struct task_struct </p></td><td><p>CONFIG_RT_MUTEXES</p></td><td><p>This field is a pointer used by the Linux's Real-Time(RT) mutex framework to handle the priority inversion, commonly seen in the kernel. This field points to the process with the highest priority waitign for the resources.</p></td></tr><tr><td><p>168</p></td><td><p>pi_blocked_on</p></td><td><p>struct rt_mutex_waiter <em></em></p></td><td><p>CONFIG_RT_MUTEXES</p></td><td><p>This field is a pointer to the RT mutex that this process is locked on.</p></td></tr><tr><td><p>169</p></td><td><p>blocked_on</p></td><td><p>struct mutex </p></td><td><p></p></td><td><p>This field points to the rt_mutex_waiter structure representing the process's wait on that specific mutex. Moslty a location holder of this process in the mutext list of waiters.</p></td></tr><tr><td><p>170</p></td><td><p>blocker</p></td><td><p>unsigned long</p></td><td><p>CONFIG_DETECT_HUNG_TASK_BLOCKER</p></td><td><p>Thsi fieldis used by the krnel to identiy what this process is waiting on or blocked by.</p></td></tr><tr><td><p>171</p></td><td><p>non_block_count</p></td><td><p>int</p></td><td><p>CONFIG_DEBUG_ATOMIC_SLEEP</p></td><td><p>This is a counter used by the kernel to detect potential deadlocks while the process is sleeping in the atomic sections. If the value is &gt; 0, then a WARN_ON() warning is issued to the user-space process</p></td></tr><tr><td><p>172</p></td><td><p>irqtrace</p></td><td><p>struct irqtrace_events</p></td><td><p>CONFIG_TRACE_IRQFLAGS</p></td><td><p>This field is used to track the interrupt state of the process for the purpose of debugging and tracing</p></td></tr><tr><td><p>173</p></td><td><p>hardirq_threaded</p></td><td><p>unsigned_int</p></td><td><p>CONFIG_TRACE_IRQFLAGS</p></td><td><p>This field is used by the lock dependency validator(lockdep) to provide a finer grain control over the context of the interrupts.</p></td></tr><tr><td><p>174</p></td><td><p>hardirq_chain_key</p></td><td><p>u64</p></td><td><p>CONFIG_TRACE_IRQFLAGS</p></td><td><p>This field is a hash value of all the locks that are being held by the kernel to handle a hardware interrupt.</p></td></tr><tr><td><p>175</p></td><td><p>softirqs_enabled</p></td><td><p>int</p></td><td><p>CONFIG_TRACE_IRQFLAGS</p></td><td><p>These fields are related to the softirqs, a deferred interrupt handling mechanism which runs in the interrupt context and not process context</p></td></tr><tr><td><p>176</p></td><td><p>softirq_context</p></td><td><p>int</p></td><td><p>CONFIG_TRACE_IRQFLAGS</p></td></tr><tr><td><p>177</p></td><td><p>irq_config</p></td><td><p>int</p></td><td><p>CONFIG_TRACE_IRQFLAGS</p></td></tr><tr><td><p>178</p></td><td><p>softirq_disable_cnt</p></td><td><p>int</p></td><td><p>CONFIG_PREEMPT_RT</p></td><td><p>This field is used along with the per CPU counter to track if a specific task has disabled softirqs</p></td></tr><tr><td><p>179</p></td><td><p>curr_chain_key</p></td><td><p>u64</p></td><td><p>CONFIG_LOCKDEP</p></td><td><p>These fields are used by the kernel to implement the lock dependency validator feature to detect the deadlocks</p></td></tr><tr><td><p>180</p></td><td><p>lockdep_depth</p></td><td><p>int</p></td><td><p>CONFIG_LOCKDEP</p></td></tr><tr><td><p>181</p></td><td><p>lockdep_recursion</p></td><td><p>unsigned int</p></td><td><p>CONFIG_LOCKDEP</p></td></tr><tr><td><p>182</p></td><td><p>held_locks</p></td><td><p>struct held_lock</p></td><td><p>CONFIG_LOCKDEP</p></td></tr><tr><td><p>183</p></td><td><p>in_ubsan</p></td><td><p>unsigned int</p></td><td><p>CONFIG_UBSAN</p></td><td><p>This field is a counter used then UB scan reports are being generated. This field avoid infinite recursions in cases where a UB report generations calls itself.</p></td></tr><tr><td><p>184</p></td><td><p>journal_info</p></td><td><p>void <em></em></p></td><td><p></p></td><td><p>This field is to capture journalling related information related to a file system</p></td></tr><tr><td><p>185</p></td><td><p>bio_list</p></td><td><p>struct bio_list </p></td><td><p></p></td><td><p>This field is used as a queue for all the block I/O requests for the process</p></td></tr><tr><td><p>186</p></td><td><p>plug</p></td><td><p>struct blk_plug <em></em></p></td><td><p></p></td><td><p>This field is used to optimize the block I/O operations by plugging the I/O queue. This works by queueing all the I/O operations and submit them as a single request instead of multiple small requests.</p></td></tr><tr><td><p>187</p></td><td><p>reclaim_state</p></td><td><p>struct reclaim_state </p></td><td><p></p></td><td><p>This field is used to manage the memory reclaimation process for a process or thread when the system is under memory pressure</p></td></tr><tr><td><p>188</p></td><td><p>io_context</p></td><td><p>struct io_context <em></em></p></td><td><p></p></td><td><p>This field is responsible for managing the process's I/O scheduling and statistics, particulary in relation to block I/O</p></td></tr><tr><td><p>189</p></td><td><p>capture_control</p></td><td><p>struct capture_control </p></td><td><p>CONFIG_COMPACTION</p></td><td><p>This field helps with the memory compaction mechanism wherein when this process is captured, the associated memory pages are compacted to avoid page faults by this process.</p></td></tr><tr><td><p>190</p></td><td><p>ptrace_message</p></td><td><p>unsigned_long</p></td><td><p></p></td><td><p>This field is used to relay information to the traced process by the kernel.</p></td></tr><tr><td><p>191</p></td><td><p>last_siginfo</p></td><td><p>kernel_siginfo_t <em></em></p></td><td><p></p></td><td><p>This field is used to store the last received signal to the process</p></td></tr><tr><td><p>192</p></td><td><p>ioac</p></td><td><p>struct task_io_accounting</p></td><td><p></p></td><td><p>This field is used to store I/O accounting information for a process</p></td></tr><tr><td><p>193</p></td><td><p>psi_flags</p></td><td><p>unsigned int</p></td><td><p>CONFIG_PSI</p></td><td><p>This field is a bitmask used by the Pressure Stall Information(PSI) to track the process's resource-related stall events.</p></td></tr><tr><td><p>194</p></td><td><p>acct_rss_mem1</p></td><td><p>u64</p></td><td><p>CONFIG_TASK_XACCT</p></td><td><p>This field is used for memory accounting. RSS is the Resident Stack Size and holds the information related to the number of pages used by the process</p></td></tr><tr><td><p>195</p></td><td><p>acct_vm_mem1</p></td><td><p>u64</p></td><td><p>CONFIG_TASK_XACCT</p></td><td><p>This field stores the cumulative memory usage of the proces over its lifetime.</p></td></tr><tr><td><p>196</p></td><td><p>acct_timexpd</p></td><td><p>u64</p></td><td><p>CONFIG_TASK_XACCT</p></td><td><p>This field is used to store the CPU time for accounting purposes. It's value is updated by the kernel during the process's lifetime</p></td></tr><tr><td><p>197</p></td><td><p>mems_allowed</p></td><td><p>nodemask_t</p></td><td><p>CONFIG_CPUSETS</p></td><td><p>This field provides a mechanism to control and restrict the memory allocation to the NUMA nodes, primarily within the context of the cpusets feature, to improve performance and resource management in NUMA systems.</p></td></tr><tr><td><p>198</p></td><td><p>mems_allowed_seq</p></td><td><p>seqcount_spinlock_t</p></td><td><p>CONFIG_CPUSETS</p></td><td><p>This field is a counter to track the process memory policies, specially related to the NUMA nodes in use.</p></td></tr><tr><td><p>199</p></td><td><p>cpuset_mem_spread_rotor</p></td><td><p>int</p></td><td><p>CONFIG_CPUSETS</p></td><td><p>This field is used for controlling the memory placement in the cpuset's feature</p></td></tr><tr><td><p>200</p></td><td><p>cgroups</p></td><td><p>struct css_set </p></td><td><p>CONFIG_CGROUPS</p></td><td><p>This field is a pointer to a set of cgroup sub-system states for the process</p></td></tr><tr><td><p>201</p></td><td><p>cg_list</p></td><td><p>strcut list_head</p></td><td><p>CONFIG_CGROUPS</p></td><td><p>This field is used to link the process to the css_set list of processes</p></td></tr><tr><td><p>202</p></td><td><p>closid</p></td><td><p>u32</p></td><td><p>CONFIG_X86_CPU_RESCTRL</p></td><td><p>This field is a hardware level identifier used in Intel's Resource Director Technology(RDT). This is usually used to enable CPU resource control support.</p></td></tr><tr><td><p>203</p></td><td><p>rmid</p></td><td><p>u32</p></td><td><p>CONFIG_X86_CPU_RESCTRL</p></td><td><p>This field is used as a unique identifier for a process within the context of the hardware-assisted resource management and monitoring provided by the Intel's RDT technology.</p></td></tr><tr><td><p>204</p></td><td><p>robust_list</p></td><td><p>struct robust_list_head <em></em></p></td><td><p>CONFIG_FUTEX</p></td><td><p>When a process uses futexes for synchronization, it can register a list of futexes that it owns with the kernel. This field acts as a pointer to such a list.</p></td></tr><tr><td><p>205</p></td><td><p>compat_robust_list</p></td><td><p>strcut compat_robust_list_head</p></td><td><p>CONFIG_FUTEX, CONFIG_COMPAT</p></td><td><p>This field is an integral part of the robust futex mechanism that guarantees system stability and prevents deadlocks by correctly managing the state of the 32-bit application locks, even on 64-bit systems.</p></td></tr><tr><td><p>206</p></td><td><p>pi_state_list</p></td><td><p>struct list_head</p></td><td><p>CONFIG_FUTEX</p></td><td><p>These fields are used to manage process dependencies on the Priority-Inversion futexes. These make sure that high-priority processes are not blocked by low-priority processes indefinitely.</p></td></tr><tr><td><p>207</p></td><td><p>pi_state_cache</p></td><td><p>struct futex_pi_state </p></td><td><p>CONFIG_FUTEX</p></td></tr><tr><td><p>208</p></td><td><p>futex_exit_mutex</p></td><td><p>struct mutex</p></td><td><p>CONFIG_FUTEX</p></td></tr><tr><td><p>209</p></td><td><p>futex_state</p></td><td><p>unsigned int</p></td><td><p>CONFIG_FUTEX</p></td></tr><tr><td><p>210</p></td><td><p>perf_recursion</p></td><td><p>u8</p></td><td><p>CONFIG_PERF_EVENTS</p></td><td><p>These fields are used for enabling support for performance events provided by hardware and software.</p></td></tr><tr><td><p>211</p></td><td><p>perf_event_ctxp</p></td><td><p>struct perf_event_context <em></em></p></td><td><p>CONFIG_PERF_EVENTS</p></td></tr><tr><td><p>212</p></td><td><p>perf_event_mutex</p></td><td><p>struct mutex</p></td><td><p>CONFIG_PERF_EVENTS</p></td></tr><tr><td><p>213</p></td><td><p>perf_event_list</p></td><td><p>struct list_head</p></td><td><p>CONFIG_PERF_EVENTS</p></td></tr><tr><td><p>214</p></td><td><p>perf_ctx_data</p></td><td><p>struct perf_ctx_data </p></td><td><p>CONFIG_PERF_EVENTS</p></td></tr><tr><td><p>215</p></td><td><p>preempt_disable_ip</p></td><td><p>unsigned long</p></td><td><p>CONFIG_DEBUG_PREEMPT</p></td><td><p>This field holds the instruction pointer (IP) of the function that last disabled the preemption for this process.</p></td></tr><tr><td><p>216</p></td><td><p>mempolicy</p></td><td><p>struct mempolicy <em></em></p></td><td><p>CONFIG_NUMA</p></td><td><p>This field defines the memory allocation policy for a process or a specific region. It specifies how memory pages should be alocated, particularly from which NUMA nodes etc</p></td></tr><tr><td><p>217</p></td><td><p>il_prev</p></td><td><p>short</p></td><td><p>CONFIG_NUMA</p></td><td><p>This field identifiles the memory node allocated to the processes to implement the weighted memory interleaving allocation for the NUMA systems.</p></td></tr><tr><td><p>218</p></td><td><p>il_weight</p></td><td><p>u8</p></td><td><p>CONFIG_NUMA</p></td><td><p>This field allows the memory allocation policy to be weighted interleaving instead of the uniformed one for NUMA systems.</p></td></tr><tr><td><p>219</p></td><td><p>pref_node_fork</p></td><td><p>short</p></td><td><p>CONFIG_NUMA</p></td><td><p>This field stores the processes preferred NUMA node, when its created through fork() system call.</p></td></tr><tr><td><p>220</p></td><td><p>numa_scan_seq</p></td><td><p>int</p></td><td><p>CONFIG_NUMA_BALANCING</p></td><td><p>NUMA balancing feature helps to place the memory locations of the process in the NUMA node associated with the process. This feature scans the process memory pages in the other NUMA nodes to check if they can be migrated for better performance. This field 'numa_scan_seq' is a counter which helps with this feature. mostly used to avoid race conditions while performing the memory migrations.</p></td></tr><tr><td><p>221</p></td><td><p>numa_scan_period</p></td><td><p>unsigned int</p></td><td><p>CONFIG_NUMA_BALANCING</p></td><td><p>This field decides the period or duration of the memory scanning to identify for any possible memory migrations.</p></td></tr><tr><td><p>222</p></td><td><p>numa_scan_period_max</p></td><td><p>unsigned int</p></td><td><p>CONFIG_NUMA_BALANCING</p></td><td><p>This fileld sets the maximum scanning duration for the process. This upper bound is required to balance the performance that arises out of the NUMA enabled systems.</p></td></tr><tr><td><p>223</p></td><td><p>numa_preferred_nid</p></td><td><p>int</p></td><td><p>CONFIG_NUMA_BALANCING</p></td><td><p>This field indicates the preferred NUMA node for a process's memory allocation. Look's like a duplicate of pref_node_fork field.</p></td></tr><tr><td><p>224</p></td><td><p>numa_migrate_retry</p></td><td><p>unsigned long</p></td><td><p>CONFIG_NUMA_BALANCING</p></td><td><p>This field is a timestamp to prevent the kernel from frequently migrating the memory pages for a fast moving process.</p></td></tr><tr><td><p>225</p></td><td><p>node_stamp</p></td><td><p>u64</p></td><td><p>CONFIG_NUMA_BALANCING</p></td><td><p>This field is used to track the process's migration history in a NUMA enabled system.</p></td></tr><tr><td><p>226</p></td><td><p>last_task_numa_placement</p></td><td><p>u64</p></td><td><p>CONFIG_NUMA_BALANCING</p></td><td><p>This field is used by the scheduler to record the time of the process's last NUMA related memory placement decision.</p></td></tr><tr><td><p>227</p></td><td><p>last_sum_exec_runtime</p></td><td><p>u64</p></td><td><p>CONFIG_NUMA_BALANCING</p></td><td><p>This field is used to track the process's runtime for scheduling decisions, usually used by the CFS scheduler. Not sure how thi sis related to NUMA</p></td></tr><tr><td><p>228</p></td><td><p>numa_work</p></td><td><p>struct callback_head</p></td><td><p>CONFIG_NUMA_BALANCING</p></td><td><p>This field enables the automatic NUMA balancing by the kernel.</p></td></tr><tr><td><p>229</p></td><td><p>numa_group</p></td><td><p>struct numa_group </p></td><td><p>CONFIG_NUMA_BALANCING</p></td><td><p>This field is used to track NUMA related information for a process or a group of processes.</p></td></tr><tr><td><p>230</p></td><td><p>numa_faults</p></td><td><p>unsigned long <em></em></p></td><td><p>CONFIG_NUMA_BALANCING</p></td><td><p>This field stores the number of page faults that a process experiences on each NUMA node.</p></td></tr><tr><td><p>231</p></td><td><p>total_numa_faults</p></td><td><p>unsigned long </p></td><td><p>CONFIG_NUMA_BALANCING</p></td><td><p>This field is the cumulative number of page faults experienced by a process all through its lifetime.</p></td></tr><tr><td><p>232</p></td><td><p>numa_faults_locality</p></td><td><p>unsigned long</p></td><td><p>CONFIG_NUMA_BALANCING</p></td><td><p>This field is used to track the count of page faults in local and remote NUMA nodes.</p></td></tr><tr><td><p>233</p></td><td><p>numa_pages_migrated</p></td><td><p>unsigned long</p></td><td><p>CONFIG_NUMA_BALANCING</p></td><td><p>Thsi field keeps track of the number of memory pages migrated by the kernel on a NUMA system for this process.</p></td></tr><tr><td><p>234</p></td><td><p>rseq</p></td><td><p>struct rseq <em></em></p></td><td><p>CONFIG_RSEQ</p></td><td><p>These fields are used to implement the rseq() system call.</p></td></tr><tr><td><p>235</p></td><td><p>rseq_len</p></td><td><p>u32</p></td><td><p>CONFIG_RSEQ</p></td></tr><tr><td><p>236</p></td><td><p>rseq_sig</p></td><td><p>u32</p></td><td><p>CONFIG_RSEQ</p></td></tr><tr><td><p>237</p></td><td><p>rseq_event_mask</p></td><td><p>unsigned long</p></td><td><p>CONFIG_RSEQ</p></td></tr><tr><td><p>238</p></td><td><p>rseq_fields</p></td><td><p>char</p></td><td><p>CONFIG_RSEQ, CONFIG_DEBUG_RSEQ</p></td></tr><tr><td><p>239</p></td><td><p>mm_cid</p></td><td><p>int</p></td><td><p>CONFIG_SCHED_MM_CID</p></td><td><p>There is not much infomation available on whatthese fields and why they are used. They were introduced in 4.x in conjuction with the above RSEQ feature.</p></td></tr><tr><td><p>240</p></td><td><p>last_mm_cid</p></td><td><p>int</p></td><td><p>CONFIG_SCHED_MM_CID</p></td></tr><tr><td><p>241</p></td><td><p>migrate_from_cpu</p></td><td><p>int</p></td><td><p>CONFIG_SCHED_MM_CID</p></td></tr><tr><td><p>242</p></td><td><p>mm_cid_active</p></td><td><p>int</p></td><td><p>CONFIG_SCHED_MM_CID</p></td></tr><tr><td><p>243</p></td><td><p>cid_work</p></td><td><p>struct callback_head</p></td><td><p>CONFIG_SCHED_MM_CID</p></td></tr><tr><td><p>244</p></td><td><p>tlb_ubc</p></td><td><p>struct tlbflush_unmap_batch</p></td><td><p></p></td><td><p>This field is used to store the pages which are being unmapped from TLB. Instead of flusing them one at a time, they are done as a batch and they are stored here until the batch reaches a certain size.</p></td></tr><tr><td><p>245</p></td><td><p>splice_pipe</p></td><td><p>struct pipe_inode_info </p></td><td><p></p></td><td><p>This field is a process cached private pipe which is used in zero-copy transfers within splice() system call. This technique copies the data between two file descriptors without copying data to and from the user space.</p></td></tr><tr><td><p>246</p></td><td><p>task_frag</p></td><td><p>struct page_frag</p></td><td><p></p></td><td><p>This field is used for optmizing memory allocations, for networking subsystems.</p></td></tr><tr><td><p>247</p></td><td><p>delays</p></td><td><p>struct task_delay_info <em></em></p></td><td><p>CONFIG_TASK_DELAY_ACCT</p></td><td><p>This field is used to track the block I/O delays expereinced by the process.</p></td></tr><tr><td><p>248</p></td><td><p>make_it_fail</p></td><td><p>int</p></td><td><p>CONFIG_FAULT_INJECTION</p></td><td><p>These fields are related to the fault injection feature. WE use this feature for testing purposes.</p></td></tr><tr><td><p>249</p></td><td><p>fail_nth</p></td><td><p>unsigned int</p></td><td><p>CONFIG_FAULT_INJECTION</p></td></tr><tr><td><p>250</p></td><td><p>nr_dirtied</p></td><td><p>int</p></td><td><p></p></td><td><p>This field is used in the context of memory management. A memory page is considered dirty, when it is written over by the process but the changes have not been written to the persistent storage.nr_dirtied is a counter used to identify the number of dirty pages which are dirtied by this process.</p></td></tr><tr><td><p>251</p></td><td><p>nr_dirtied_pause</p></td><td><p>int</p></td><td><p></p></td><td><p>This field is used in the context when this process is aggreesively dirtying the pages and crossed over the per process threshold set by the kernel.</p></td></tr><tr><td><p>252</p></td><td><p>dirty_paused_when</p></td><td><p>unsigned long</p></td><td><p></p></td><td><p>This field holds the timestamp for the beginning of the write-and-pause period of the process's pages.</p></td></tr><tr><td><p>253</p></td><td><p>latency_record_count</p></td><td><p>int</p></td><td><p>CONFIG_LATENCY_TOP</p></td><td><p>This field is used in the context of latency calculations by the kernel. This feature allows the kernel to keep a track of the longest delays caused by various operations. latncy_record_count field is used to store the scheduling latency events caused by this process.</p></td></tr><tr><td><p>254</p></td><td><p>latency_record</p></td><td><p>struct latency_record</p></td><td><p>CONFIG_LATENCY_TOP</p></td><td><p>This field stores the latency event caused or expereinced by this process. This is an array</p></td></tr><tr><td><p>255</p></td><td><p>timer_slack_ns</p></td><td><p>u64</p></td><td><p></p></td><td><p>These fields are used to round-up the poll() and select() timer values(these are in nanoseconds)</p></td></tr><tr><td><p>256</p></td><td><p>default_timer_slack_ns</p></td><td><p>u64</p></td><td><p></p></td></tr><tr><td><p>257</p></td><td><p>kasan_depth</p></td><td><p>unsigned int</p></td><td><p>CONFIG_KASAN_GENERIC or CONFIG_KASAN_SW_TAGS</p></td><td><p>Kernel Address Sanitizer(KASAN) is a dynamic memory error detector. kasan_depth field is a counter used to track the resursion depth during memory allocation and deallocation.</p></td></tr><tr><td><p>258</p></td><td><p>kcsan_ctx</p></td><td><p>struct kcsan_ctx</p></td><td><p>CONFIG_KCSAN</p></td><td><p>This field stores the information related to the Kernel Concurrency Sanitizer (KCSAN). KCSAN is used to track the concurrency bugs in the kernel.</p></td></tr><tr><td><p>259</p></td><td><p>kcsan_save_irqtrace</p></td><td><p>struct irqtrace_events</p></td><td><p>CONFIG_KCSAN, CONFIG_TRACE_IRQFLAGS</p></td><td><p>This field stores the IRQ trace state when the KCSAN is active</p></td></tr><tr><td><p>260</p></td><td><p>kcsan_stack_depth</p></td><td><p>int</p></td><td><p>CONFIG_KCSAN, CONFIG_KCSAN_WEAK_MEMORY</p></td><td><p>This field stores the stack depth of the kernel for this process. Used in conjuction with KCSAN feature.</p></td></tr><tr><td><p>261</p></td><td><p>kmsan_ctx</p></td><td><p>struct kmsan_ctx</p></td><td><p>CONFIG_KMSAN</p></td><td><p>KMSAN is Kernel Memory Sanitizer, used for tracking the uninitialized memory in the kernel. kmsan_ctx field stores the per process state of the KMSAN detector.</p></td></tr><tr><td><p>262</p></td><td><p>kunit_test</p></td><td><p>struct kunit </p></td><td><p>CONFIG_KUNIT</p></td><td><p>This field is a pointer used by the kUnit test frameworkto associate a running kernel thread/ process with the test context that spawned it.</p></td></tr><tr><td><p>263</p></td><td><p>curr_ret_stack</p></td><td><p>int</p></td><td><p>CONFIG_FUNCTION_GRAPH_TRACER</p></td><td><p>The tracer is a debugging and profiling tool in the kernel that records the entry and exit of the functions. This field is a pointer to a process specific 'shadow stack' that holds the return addresses of the instrumented function calls.</p></td></tr><tr><td><p>264</p></td><td><p>curr_ret_depth</p></td><td><p>int</p></td><td><p>CONFIG_FUNCTION_GRAPH_TRACER</p></td><td><p>These fields are used to track the call stack of the kernel functions</p></td></tr><tr><td><p>265</p></td><td><p>ret_stack</p></td><td><p>unsigned long <em></em></p></td><td><p>CONFIG_FUNCTION_GRAPH_TRACER</p></td></tr><tr><td><p>266</p></td><td><p>ftrace_timestamp</p></td><td><p>unsigned long long</p></td><td><p>CONFIG_FUNCTION_GRAPH_TRACER</p></td><td><p>There is not much information available for these fields, but they are used in the ftracer debugging tool.</p></td></tr><tr><td><p>267</p></td><td><p>ftrace_sleeptime</p></td><td><p>unsigned long long</p></td><td><p>CONFIG_FUNCTION_GRAPH_TRACER</p></td></tr><tr><td><p>268</p></td><td><p>trace_overrun</p></td><td><p>atomic_t</p></td><td><p>CONFIG_FUNCTION_GRAPH_TRACER</p></td></tr><tr><td><p>269</p></td><td><p>tracing_graph_pause</p></td><td><p>atomic_t</p></td><td><p>CONFIG_FUNCTION_GRAPH_TRACER</p></td></tr><tr><td><p>270</p></td><td><p>trace_recursion</p></td><td><p>unsigned long</p></td><td><p>CONFIG_TRACING</p></td><td><p>Not much information is available about this field.</p></td></tr><tr><td><p>271</p></td><td><p>kcov_mode</p></td><td><p>unsigned int</p></td><td><p>CONFIG_KCOV</p></td><td><p>These fields help with getting the kernel code coverage for fizzing purposes.</p></td></tr><tr><td><p>272</p></td><td><p>kcov_size</p></td><td><p>unsigned int</p></td><td><p>CONFIG_KCOV</p></td></tr><tr><td><p>273</p></td><td><p>kcov_area</p></td><td><p>void </p></td><td><p>CONFIG_KCOV</p></td></tr><tr><td><p>274</p></td><td><p>kcov</p></td><td><p>struct kcov <em></em></p></td><td><p>CONFIG_KCOV</p></td></tr><tr><td><p>275</p></td><td><p>kcov_handle</p></td><td><p>u64</p></td><td><p>CONFIG_KCOV</p></td></tr><tr><td><p>276</p></td><td><p>kcov_sequence</p></td><td><p>int</p></td><td><p>CONFIG_KCOV</p></td></tr><tr><td><p>277</p></td><td><p>kcov_softirq</p></td><td><p>unsigned int</p></td><td><p>CONFIG_KCOV</p></td></tr><tr><td><p>278</p></td><td><p>memcg_in_oom</p></td><td><p>struct mem_cgroup </p></td><td><p>CONFIG_MEMCG_V1</p></td><td><p>This field is used to indicate if the process is involved in a memory cgroup out-of-memory event.</p></td></tr><tr><td><p>279</p></td><td><p>memcg_nr_pages_over_high</p></td><td><p>unsigned int</p></td><td><p>CONFIG_MEMCG</p></td><td><p>This field is used to track the number of memory pages this process has allocated that exceeds the its memory cgroup's 'high' limit.</p></td></tr><tr><td><p>280</p></td><td><p>active_memcg</p></td><td><p>struct mem_cgroup <em></em></p></td><td><p>CONFIG_MEMCG</p></td><td><p>CONFIG_MEMCG acts as a memory controller for the cgroups. mem_cgroup is a structure for the memory controller for each cgroup. active_memcg is a fpointer to the memory control group that is active for this process. It is primarily used to track and enforce memory usage limits imposed by the cgroup memory controller.</p></td></tr><tr><td><p>281</p></td><td><p>objcg</p></td><td><p>struct obj_cgroup </p></td><td><p>CONFIG_MEMCG</p></td><td><p>This field represents a list of memory objects associated with the memory cgoup</p></td></tr><tr><td><p>282</p></td><td><p>throttle_disk</p></td><td><p>struct gendisk <em></em></p></td><td><p>CONFIG_BLK_CGROUP</p></td><td><p>This field is used to disk I/O throttling purposes where disk bandwidth and operations per second are limited for a specific process of group of processes.</p></td></tr><tr><td><p>283</p></td><td><p>utask</p></td><td><p>struct uprobe_task </p></td><td><p>CONFIG_UPROBES</p></td><td><p>Uprobes are the user space probes which are used for probing the applications. Its the counter part to kernels Kprobes. utask is a variable which holds the metadata for a specific process when it is being instrumented by a user level probe.</p></td></tr><tr><td><p>284</p></td><td><p>sequential_io</p></td><td><p>unsigned int</p></td><td><p>CONFIG_BCACHE or CONFIG_BCACHE_MODULE</p></td><td><p>CONFIG_BCACHE allows a block device to be used as a cache for other devices. sequential_io is a field used by the kernel to track and average the process's sequential I/O patterns.</p></td></tr><tr><td><p>285</p></td><td><p>sequencial_io_avg</p></td><td><p>unsigned int</p></td><td><p>CONFIG_BCACHE or CONFIG_BCACHE_MODULE</p></td></tr><tr><td><p>286</p></td><td><p>kmap_ctrl</p></td><td><p>struct kmap_ctrl</p></td><td><p></p></td><td><p>This field is used to manage the mapping of the high memory pages within a single process.</p></td></tr><tr><td><p>287</p></td><td><p>task_state_change</p></td><td><p>unsigned long</p></td><td><p>CONFIG_DEBUG_ATOMIC_SLEEP</p></td><td><p>These fields are used to change the state of the process.</p></td></tr><tr><td><p>288</p></td><td><p>saved_state_change</p></td><td><p>unsigned long</p></td><td><p>CONFIG_DEBUG_ATOMIC_SLEEP, CONFIG_PREEMPT_RT</p></td></tr><tr><td><p>289</p></td><td><p>rcu</p></td><td><p>struct rcu_head</p></td><td><p></p></td><td><p>This field is used by RCU for syncronization.</p></td></tr><tr><td><p>290</p></td><td><p>rcu_users</p></td><td><p>refcount_t</p></td><td><p></p></td><td><p>This field is used to manage the RCU based references.</p></td></tr><tr><td><p>291</p></td><td><p>pagefault_disabled</p></td><td><p>int</p></td><td><p></p></td><td><p>This field is used to check if the page faults have been disabled for this process.</p></td></tr><tr><td><p>292</p></td><td><p>oom_reaper_list</p></td><td><p>struct task_struct <em></em></p></td><td><p>CONFIG_MMU</p></td><td><p>This field adds the process to the oom_reaper kernel thread for cleanup of its memory managmenet structures</p></td></tr><tr><td><p>293</p></td><td><p>oom_reaper_timer</p></td><td><p>struct timer_list</p></td><td><p>CONFIG_MMU</p></td><td><p>This field is used to schedule the OOM reaper scheduler.</p></td></tr><tr><td><p>294</p></td><td><p>stack_vm_area</p></td><td><p>struct vm_struct </p></td><td><p>CONFIG_VMAP_STACK</p></td><td><p>This field is used when configuring virtual ly enabled kernel stacks. This mechanism allows the kernel stack buffer overflows to be caught without causing data corruptions.</p></td></tr><tr><td><p>295</p></td><td><p>stack_refcount</p></td><td><p>refcount_t</p></td><td><p>CONFIG_THREAD_INFO_IN_TASK</p></td><td><p>This field holds the number of references to the process kernel stack.</p></td></tr><tr><td><p>296</p></td><td><p>patch_state</p></td><td><p>int</p></td><td><p>CONFIG_LIVEPATCH</p></td><td><p>This field is used for live patching the kernel to track the security vulnerabilities.</p></td></tr><tr><td><p>297</p></td><td><p>security</p></td><td><p>void <em></em></p></td><td><p>CONFIG_SECURITY</p></td><td><p>This field allows to chose a security model for the kernel.</p></td></tr><tr><td><p>298</p></td><td><p>bpf_storage</p></td><td><p>strcu bpf_local_storage</p></td><td><p>CONFIG_BPF_SYSCALL</p></td><td><p>This field alllows to attach BPF defined storage to this process. This mechanism allows BPF to store and access the private data of the process context.</p></td></tr><tr><td><p>299</p></td><td><p>bpf_ctx</p></td><td><p>struct bpf_run_ctx </p></td><td><p>CONFIG_BPF_SYSCALL</p></td><td><p>This field supports the adavanced eBPF <a target="_blank" class="in-cell-link" href="http://features.it/">features.It</a> allows the BPF programs to associate with the runtime context of the process.</p></td></tr><tr><td><p>300</p></td><td><p>bpf_net_context</p></td><td><p>struct bpf_net_context <em></em></p></td><td><p></p></td><td><p>This field stores the network based context for BPF programs for this process.</p></td></tr><tr><td><p>301</p></td><td><p>lowest_stack</p></td><td><p>unsigned long</p></td><td><p>CONFIG_KSTACK_ERASE</p></td><td><p>This field is used to detect the kernel stack buffer overflow in old kernel versions.</p></td></tr><tr><td><p>302</p></td><td><p>prev_lowest_stack</p></td><td><p>unsigned long</p></td><td><p>CONFIG_KSTACK_ERASE_METRICS</p></td><td><p>This field is used to track the kernel stack usage.</p></td></tr><tr><td><p>303</p></td><td><p>mce_vaddr</p></td><td><p>void </p></td><td><p>CONFIG_X86_MCE</p></td><td><p>These fields are used for configuring the machine checks. This setting allows the processes to notify the kernel if it detects any issues related to heating, data corruption etc.</p></td></tr><tr><td><p>304</p></td><td><p>mce_kflags</p></td><td><p><strong>u64</strong></p></td><td><p>CONFIG_X86_MCE</p></td></tr><tr><td><p>305</p></td><td><p>mce_addr</p></td><td><p>u64</p></td><td><p>CONFIG_X86_MCE</p></td></tr><tr><td><p>306</p></td><td><p>mce_ripv</p></td><td><p>u64</p></td><td><p>CONFIG_X86_MCE</p></td></tr><tr><td><p>307</p></td><td><p>mce_kill_me</p></td><td><p>struct callback_head</p></td><td><p>CONFIG_X86_MCE</p></td></tr><tr><td><p>308</p></td><td><p>mce_count</p></td><td><p>int</p></td><td><p>CONFIG_X86_MCE</p></td></tr><tr><td><p>309</p></td><td><p>kretprobe_instances</p></td><td><p>struct llist_head</p></td><td><p>CONFIG_KRETPROBES</p></td><td><p>This field is used when kernel tracing is enabled. With Kernel tracing, we can dynamically break into any kernel routine for debugging and performace related information.</p></td></tr><tr><td><p>310</p></td><td><p>rethooks</p></td><td><p>struct llist_head</p></td><td><p>CONFIG_RETHOOK</p></td><td><p>This field enables return hook feature, usually used by other hooking featues like fprobe and kprobes</p></td></tr><tr><td><p>311</p></td><td><p>l1d_flush_kill</p></td><td><p>struct callback_head</p></td><td><p>CONFIG_ARCH_HAS_PARANOID_L1D_FLUSH</p></td><td><p>This field is used as a kill swITch for processes which are not running on SMT disabled cores.</p></td></tr><tr><td><p>312</p></td><td><p>rv</p></td><td><p>union rv_task_monitor</p></td><td><p>CONFIG_RV</p></td><td><p>This field is used to enable and monitor the kernels runtime verification substem</p></td></tr><tr><td><p>313</p></td><td><p>user_event_mm</p></td><td><p>struct user_event_mm *</p></td><td><p>CONFIG_USER_EVENTS</p></td><td><p>This field associates this process with the Linux Kernels User Event tracing subsystem</p></td></tr><tr><td><p>314</p></td><td><p>unwind_info</p></td><td><p>struct unwind_task_info</p></td><td><p>CONFIG_UNWIND_USER</p></td><td><p>Thie field refers to the call stack unwinding feature for the user space programs, meant to examine the call stack in the running state.</p></td></tr><tr><td><p>315</p></td><td><p>thread</p></td><td><p>struct task_struct</p></td><td><p></p></td><td><p>This field stores the CPU specific state of this process.</p></td></tr><tr><td><p></p></td><td><p></p></td><td><p></p></td><td><p></p></td><td><p></p></td></tr></tbody></table>

<hr />
<h3 id="heading-struct-vmareastruct">struct vm_area_struct</h3>
<p>virtual memory areas(VMAs) are defined by a data structure ‘struct vm_area_struct’ defined in ./linux/mm_types.h.</p>
<p>VMAs are used to define the memory areas associated with a process. Read more about it in the ‘Process Management’ <a target="_blank" href="https://hashnode.com/post/cmi6r13yw000102l2b46wd0lg">blog</a></p>
<table><tbody><tr><td><p><strong>sl no</strong></p></td><td><p><strong>Attribute name</strong></p></td><td><p><strong>Attribute type</strong></p></td><td><p><strong>Attribute Usage</strong></p></td></tr><tr><td><p>1</p></td><td><p>vm_start</p></td><td><p>unsigned long</p></td><td><p>Beginning of a virtual memory area</p></td></tr><tr><td><p>2</p></td><td><p>vm_end</p></td><td><p>unsigned long</p></td><td><p>End of a virtual memory area</p></td></tr><tr><td><p>3</p></td><td><p>vm_mm</p></td><td><p>struct mm_struct <em></em></p></td><td><p>This pointer points back to the process address space, this VMA belongs to</p></td></tr><tr><td><p>4</p></td><td><p>vm_page_prot</p></td><td><p>pgprot_t</p></td><td><p>Permissions associated with the memory area(READ, WRITE, EXECUTE)</p></td></tr><tr><td><p>5</p></td><td><p>vm_flags</p></td><td><p>vm_flags_t</p></td><td><p>flags used to manipulate the memory areas(like permissions, sharing etc)</p></td></tr><tr><td><p>6</p></td><td><p>vm_lock_seq</p></td><td><p>unsigned int</p></td><td><p>lock for this memory area</p></td></tr><tr><td><p>7</p></td><td><p>anon_vma_chain</p></td><td><p>struct list_head</p></td><td><p>Used by anonymous memory areas usually created by calls to malloc() ( referred to as heap region too)</p></td></tr><tr><td><p>8</p></td><td><p>anon_vma</p></td><td><p>struct anon_vma</p></td></tr><tr><td><p>9</p></td><td><p>vm_ops</p></td><td><p>struct vm_operations_struct</p></td><td><p>refers to the operations that can be executed on the vmas(like open, remove, access etc).</p></td></tr><tr><td><p>10</p></td><td><p>vm_pgoff</p></td><td><p>unsigned long</p></td><td><p>Refers to the page offset, usally associated with the vm_file information below.</p></td></tr><tr><td><p>11</p></td><td><p>vm_file</p></td><td><p>struct file <em></em></p></td><td><p>When vma is associated with a file, this pointer points to that file, otherwise NULL. Say, the process open a file, that file content is stored in some memory and that memory is referred by this vma</p></td></tr><tr><td><p>12</p></td><td><p>vm_private_data</p></td><td><p>void </p></td><td><p>Used when shared memory is involved between processes</p></td></tr><tr><td><p>13</p></td><td><p>swap_readahead_info</p></td><td><p>atomic_long_t</p></td><td><p>used when SWAP is enabled</p></td></tr><tr><td><p>14</p></td><td><p>vm_region</p></td><td><p>struct vm_region<em></em></p></td><td><p>Used when MMU is enabled by the kernel</p></td></tr><tr><td><p>15</p></td><td><p>vm_policy</p></td><td><p>struct mempolicy</p></td><td><p>Defines the NUMA policy for the VMA</p></td></tr><tr><td><p>16</p></td><td><p>numab_state</p></td><td><p>struct vma_numab_state <em></em></p></td><td><p>Relates to NUMA related policy</p></td></tr><tr><td><p>17</p></td><td><p>vmlock_dep_map</p></td><td><p>struct lockdep_map</p></td><td><p>enabled when CONFIG_DEBUG_LOCK_ALLOC is used</p></td></tr><tr><td><p>18</p></td><td><p>anon_name</p></td><td><p>struct anon_vma_name</p></td><td><p>Name associated with the VMA or a NULL</p></td></tr><tr><td><p>19</p></td><td><p>vm_userfaultfd_ctx</p></td><td><p>struct vm_userfaultfd_ctx</p></td><td><p>Related to the system call userfaultfd(), used when tracking the user faults associated with this VMA</p></td></tr><tr><td><p>20</p></td><td><p>pfnmap_track_ctx</p></td><td><p>struct pfnmap_track_ctx *</p></td><td><p>Used when Physical Frame Tracking (PFN) is enabled</p></td></tr><tr><td><p></p></td><td><p></p></td><td><p></p></td><td><p></p></td></tr></tbody></table>]]></content:encoded></item><item><title><![CDATA[Linux Kernel Initialization]]></title><description><![CDATA[This blog is to understand how the Linux kernel is installed and initialized in the physical memory.
Linux Boot Process:


When we start the system, initial control goes to the BIOS firmware, sitting on a chip on the motherboard.

This software start...]]></description><link>https://linux-kernel.hashnode.dev/core-kernel-initialization</link><guid isPermaLink="true">https://linux-kernel.hashnode.dev/core-kernel-initialization</guid><dc:creator><![CDATA[Datta Prabhu M]]></dc:creator><pubDate>Thu, 16 Oct 2025 02:02:27 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1760590902014/0f73994b-6ed3-4b88-ac94-89eed98431dc.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This blog is to understand how the Linux kernel is installed and initialized in the physical memory.</p>
<p><strong>Linux Boot Process:</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1760731791478/dd576b14-a0b9-477c-86a3-e0ce660b2324.png" alt /></p>
<ul>
<li><p>When we start the system, initial control goes to the BIOS firmware, sitting on a chip on the motherboard.</p>
</li>
<li><p>This software starts with checking if the hardware is working fine. This process is called Power-On-Self-Test(POST).</p>
</li>
<li><p>Once POST completes, BIOS checks the boot order. BIOS tries to boot from the first available boot disk(USB, hard drive etc).</p>
</li>
<li><p>Lets say, the system is trying to boot from a hard drive.</p>
</li>
<li><p>BIOS tries to locate the Master Boot Record(MBR) from the hard drive. MBR is a 512 bytes(always) present in the Disk 0, Sector 1 and Head 0 location. This location is hard coded.</p>
</li>
<li><p>BIOS moves MBR to the physical memory. MBR has the location of the boot loader. For example, GRUB, LILO etc. Let’s say we are using GRUB.</p>
</li>
<li><p>MBR loads the GRUB files into the physical memory. This is when we see the menu options with all the available operating systems and versions. Users are expected to choose one in this list.</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1760729928116/7715e5de-d7ee-43fe-9fe5-42a87377fb71.png" alt class="image--center mx-auto" /></p>
<p>  We can access the GRUB files at ‘/boot/grub/grub.cfg’ location. We can modify the contents by changing the file ‘/etc/default/grub’.</p>
</li>
<li><p>Boot loader has access to two files:</p>
<ol>
<li><p>first is the linux kernel executable, which is usually named, <strong>vmlinuz-*.</strong> This is the file which controls the entire system and hardware once loaded and initialized later.</p>
</li>
<li><p>Second is a file called initial RAM disk, usually named ‘<strong>initrd-*</strong>’. The purpose of this file will be explained further.</p>
</li>
</ol>
</li>
<li><p>Boot loader loads the linux kernel executable file first into the physical memory. But where does it load it?</p>
<ul>
<li><p>This depends on the kernel configurations, like CONFIG_PHYSICAL_START, CONFIG_PHYSICAL_ALIGN, CONFIG_RANDOMIZE_BASE.</p>
<p>  On Linux Kernel-6.11, these values are as below:</p>
</li>
<li><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1760845807913/f4c80655-edf9-4adc-9a18-9b5dd8fcb7c2.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>These values show that the kernel is installed on the physical memory at 0x1000000 location( 100 MB) from the beginning of the physical memory. Since a static location is not safe, the latest implementations randomize this location. This is done by configuring CONFIG_RANDOM_BASE to ‘y’ during building the kernel.</p>
<p>  Also, the size of the memory allocation for Kernel depends on the build configurations used, but is usually 1 GB as shown below.</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1760729226409/c58ce455-ad9b-4cce-9515-228124130158.png" alt class="image--center mx-auto" /></p>
<p>  More about this will be discussed in another blog.</p>
</li>
</ul>
</li>
<li><p>Initially the kernel is in compressed format to ease the time to load to the memory. Once it's loaded, it de-compresses itself. Then the first activity it does is to mount the ‘initrd’ files on a file system called ‘initramfs’. This is an intermediary step before the kernel mounts the actual root file system.</p>
</li>
<li><p>From the ‘initramfs’ file system, kernel executes some assembly code, which is usually present in location ./arch/x86/kernel/head_{32 | 64}.S (depending on 32 vs 64 bit systems).</p>
</li>
<li><p>This assembly code is architecture dependent. The goal of running this assembly code is to execute a C type method called ‘start_kernel’.</p>
</li>
<li><p>Start_kernel completes the initialization of the kernel to its fullest form, upon which it mounts the root file system, starts the ‘init’ process and provides the user a login prompt.</p>
</li>
</ul>
<hr />
<p><strong>Kernel Memory Sections</strong></p>
<p>We noted earlier that the kernel occupies around 1 GB of memory in the physical memory during the above boot process.</p>
<p>This allocation consists of multiple sections as shown below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1760754412993/4096e395-a130-4b32-bc4f-e58fb3c269a9.png" alt /></p>
<ul>
<li><p><strong>22528K kernel code</strong>: This is the executable machine code of the kernel itself, stored in the <code>.text</code> segment. This section is typically read-only.</p>
</li>
<li><p><strong>4524K rwdata</strong>: Short for read-write data, this memory contains global and static variables that have been initialized with a non-zero value. It is stored in the <code>.data</code> segment and can be modified at runtime.</p>
</li>
<li><p><strong>15008K rodata</strong>: Short for read-only data, this memory holds constant data that should not change during execution, such as string literals. It is stored in the <code>.rodata</code> segment.</p>
</li>
<li><p><strong>4884K init</strong>: This is temporary kernel initialization memory. After the system is booted, this memory is released back to the general memory pool to be reused.</p>
</li>
<li><p><strong>4736K bss</strong>: Short for Block Started by Symbol, this section contains uninitialized global and static variables. The kernel initializes this memory to zero at boot.</p>
</li>
<li><p><strong>995728K reserved</strong>: This is a large block of memory reserved by the firmware for hardware functions that the kernel does not manage. It is typically not available for general-purpose use.</p>
</li>
<li><p><strong>0K cma-reserved</strong>: This field refers to "Contiguous Memory Allocator" reserved memory, which is used for device drivers that require large, physically contiguous memory blocks. In this case, none is reserved.</p>
</li>
</ul>
<p>These values are typical for a RAM of size 16 G. We can get these values for a system from ‘dmesg’ logs, as below(last line):</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1760762859734/070aaf5c-fccd-46dc-b441-f6667cc290e9.png" alt class="image--center mx-auto" /></p>
<blockquote>
<p>The rest of the blog is to understand what happens in ‘start_kernel’ code.</p>
</blockquote>
<hr />
<p><strong>Core</strong> K<strong>ernel Initialization</strong></p>
<ul>
<li>[set_task_stack_end_magic()] creates a kernel stack and adds a canary value <strong>0x57AC6E9D</strong> at the end of the stack to check for buffer overflows, As shown in the below picture.</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1760729763161/1fa1972d-adcf-43f4-92f5-18e40d520cea.png" alt class="image--right mx-auto mr-0" /></p>
<ul>
<li><p>The size of this stack is architecture dependent. This stack is created in the kernel memory section ‘bss’ in the physical memory(RAM). The size is usually PAGE_SIZE or 2 * PAGE_SIZE. A page size is usually 4096 or 8192 bytes.</p>
<ul>
<li><p>How do you get this value on your system?</p>
<p>  To get the page size, you can use the command, ‘getconf PAGESIZE’ on the terminal, as below:</p>
</li>
</ul>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1760819223429/73eba088-dfcc-45c2-b573-7237bce4e149.png" alt class="image--right mx-auto mr-0" /></p>
<p>To get the kernel stack size, you can use the command ‘ulimit -s’ as below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1760819233863/3f081770-f358-414e-8028-9e7864bde6cd.png" alt class="image--center mx-auto" /></p>
<ul>
<li>Whether the kernel stack grows upwards or downwards is based on the setting ‘CONFIG_STACK_GROWSUP’ and is platform dependent. For example, for x86 or ARM or PPC, this is not set and the stack grows downwards.</li>
</ul>
<ul>
<li><p>[smp_setup_processor_id()] Creates a CPU logical map for fetching logical processor id for a given physical CPU Id. This is required to manage and identify CPUs consistently across the system. For systems with multi-processor systems, where CONFIG_SMP is set, the values range from 1…n</p>
</li>
<li><p>[local_irq_disable()] Disable hardware interrupts on the CPU where the init process is running. These interrupts will be inactive until the init process is completed.</p>
</li>
<li><p>[boot_cpu_init()] Decide which CPU Id to boot kernel from. In single CPU system, this would be 0.</p>
</li>
<li><p>[page_address_init()] Create a 128 sized array of type ‘struct page_address_slot’ which is used to get the virtual address for a page in the highmem region. More about this will be discussed in a future blog.</p>
</li>
<li><div data-node-type="callout">
  <div data-node-type="callout-emoji">💡</div>
  <div data-node-type="callout-text">All the memory allocations from the below step are fulfilled through ‘memblock’. This is a boot time memory management system where memory is allocated in ‘regions’ directly in the physical memory. No virtual addressing happens here.</div>
  </div>
</li>
<li><p>[setup_arch()] All the architecture specific setup here:</p>
<ul>
<li><p>Load the kernel PGD (Page Global Descriptor) table to CPU’s CR3 register( only for 32 bit system)</p>
</li>
<li><p>Flush the TLB cache to remove any garbage entries(32 bit).</p>
</li>
<li><p>Set the MAX_PHYSMEM_BITS value which is used for addressing the virtual address space.</p>
</li>
<li><p>Reserve memblock region for the <strong>.text</strong> region of the kernel. Kernel memory sections have been described earlier.</p>
</li>
<li><p>Reserve memblock region for the <strong>initrd</strong> image.</p>
</li>
<li><p>Reserve memblock region for <strong>data</strong> part of the kernel.</p>
</li>
<li><p>Reserve memblock region for the <strong>init</strong> process. This memory is claimed back once the init process is started and moved to the user space.</p>
</li>
<li><p>Randomize the kernel base memory if CONFIG_RANDOMIZE_BASE is enabled.</p>
</li>
<li><p>Initialize the Interrupt Descriptor Table(IDT) which maps the interrupt or exception number to a memory address that handles it. This allows the CPU to avoid any unexpected events before the system is fully configured.</p>
</li>
</ul>
</li>
<li><p>[setup_nr_cpu_ids()] Calculate the number of CPUs in the system and assign this value to the variable ‘nr_cpu_ids’. This value is used in all cases where CPU operations are involved.</p>
</li>
<li><p>[setup_per_cpu_areas()] Initialize memory for ‘per-CPU’ variables. This feature allows a copy of a variable to be made available(usually in L3 cache) for each CPU and thereby allow the CPUs to read the local copy instead of using locks to fetch its value from the physical memory.</p>
</li>
<li><p>[setup_log_buf()] Setup a log buffer of size 128 KB. All the messages that ‘printk’ logs, are stored in this buffer. These messages can be accessed using the ‘dmesg’ shell command .</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1760835278147/e56ece8b-2297-4233-a8e1-90719d046e71.png" alt class="image--right mx-auto mr-0" /></p>
<ul>
<li><p>[sort_main_extable()] Sort the kernel exception handlers table. This list is required to handle any exceptions seen by the kernel and make sure the system doesn’t crash.</p>
</li>
<li><p>[sched_init()] Initialize the scheduler, for task scheduling ahead. All the scheduler algorithms (like DL, RR, FAIR etc) are initialized here.</p>
</li>
<li><p>[trace_init()] Initialize tracing infrastructure, part of the ‘ftrace’ framework. Trace events are generated after this step.</p>
</li>
<li><p>[kfence_init()] Initialize Kernel Electric Fence(KFence) memory error detector. This tool is designed to detect common heap memory errors like out-of-bounds access, use-after-free and invalid-free errors.</p>
</li>
<li><p>[lockdep_init()] Initialize the lock dependency validator, which is a tool to detect the potential deadlocks and incorrect locking patterns within the kernel.</p>
</li>
<li><p>[anon_vma_init()] Create slab cache called ‘anon_vma’ for kernel objects of type ‘struct anon_vma’, which is used to manage the anonymous virtual memory. This memory refers to the virtual memory which is not backed by a file or disk, like a process’s stack or heap.</p>
</li>
<li><p>[thread_stack_cache_init()] Create slab cache named ‘thread_stack’ for kernel threads.</p>
</li>
<li><p>[fork_init()] Allocate slab cache named ‘task_struct’ for kernel objects of type ‘struct task_struct’. This structure holds the information about a single process.</p>
</li>
<li><p>[proc_caches_init()] Create slab caches for the below kernel objects:</p>
<ul>
<li><p>slab cache named ‘sighand_cache’ for kernel objects ‘struct sighand_struct’.</p>
</li>
<li><p>slab cache named ‘signal_cache’ for kernel objects ‘struct signal_struct’.</p>
</li>
<li><p>slab cache named ‘files_cache’ for kernel objects ‘struct files_struct’</p>
</li>
<li><p>slab cache named ‘fs_cache’ for kernel objects ‘struct fs_struct’.</p>
</li>
<li><p>slab cache named ‘vm_area_struct’ for kernel objects ‘struct vm_area_struct’.</p>
</li>
</ul>
</li>
<li><p>[security_init()] Initialize the Linux Security Module (LSM) framework by loading all the LSM modules which were enabled in the boot config.</p>
</li>
<li><p>[net_ns_init()] Create slab cache called ‘net_namespace’ for kernel objects of type ‘struct net’ . Network namespaces allow for network isolation and each namespace can have its own network stack(ip addresses, firewalls, routing etc). This allows for launching multiple applications and services (isolated from each other) on a single Linux system. This is similar to container and virtual machine technologies which we use today.</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1760910779053/170f37de-8ce0-46c2-a32f-f0a3696652da.png" alt /></p>
<ul>
<li><p>[vfs_caches_init()] Initialize Virtual File System(VFS) by creating slab caches for kernel objects like directory entries, inodes, file objects, mount points, buffers for storing and accessing the files.</p>
</li>
<li><p>[pagecache_init()] Initialize page cache mechanism. As part of this setup, an array of size 256 is created to hold the information of the processes or threads which are waiting for a particular page to be made available. These are called wait queues. That means each page in the page cache, gets a wait queue of this size to hold information of the processes or threads waiting to access this page. This step also creates kernel threads and other data structures used to handle the ‘dirty’ pages, these are pages which have been modified by the process or thread, but not written back to the secondary storage.</p>
</li>
<li><p>[signals_init()] Create slab cache for kernel objects of type ‘struct sigqueue’.</p>
</li>
<li><p>[seq_file_init()] Initialize seq_file which is used to create virtual files later in the other file systems like ‘proc’. Virtual files are dynamically created when requested for. All the content in the /proc folder is created by this seq_file mechanism.</p>
</li>
<li><p>[proc_root_init()] Mount ‘proc’ file system. Mount ‘sys’, ‘fs’, ‘driver’, ‘’tty’, ‘sys’ file systems under ‘proc’ file system.</p>
</li>
<li><p>[nsfs_init()] Initialize and mount ‘nsfs’ file system. This file system helps with Linux namespaces, which are used to isolate the processes for optimizing the system resources. This file system cannot be mounted and usually is available through the proc file system. This file system helps to find which namespace is being used for a particular process.</p>
</li>
<li><p>[pidfs_init()] Initialize the ‘pidfs’ pseudo file system by creating the required data structures and mounting it. This file system is usually used within the kernel to manage the process Ids and related information.</p>
</li>
<li><p>[cpuset_init()] Initialize cpusets as part of the cgroup controllers. This step allows group of processes to limit access to cpusets.</p>
</li>
<li><p>[mem_cgroup_init()] Create a slab cache called ‘mem_cgroup’ to create kernel objects of type ‘struct mem_cgroup’.</p>
</li>
<li><p>[cgroup_init()] Initialize control groups (cgroup). Mount the file system ‘/sys/fs’ as ‘cgroup’ and create cgroup files like ‘cgroup.procs’ etc, as shown below:</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1760848114691/3b9d2ca6-74c1-48bd-9543-9e7d74ee4315.png" alt class="image--right mx-auto mr-0" /></p>
<ul>
<li><p>[taskstats_init_early()] Assign slab cache memory for the structure ‘taskstats’ which would be used for delay accounting subsystem.</p>
</li>
<li><p>[delayacct_init()] Initializes delay accounting subsystem, which tracks the and reports delays experienced by the tasks(processes and threads) waiting for kernel resources. This information is made available to user-space through the taskstats interface. This step involves assigning cache memory to store this information and then initiate this accounting for the initial ‘init’ process.</p>
</li>
<li><p>[acpi_subsystem_init()] Initialize ACPI system. ACPI stands for Advanced Configuration and Power Interface which is an in-built power management mechanism which shuts down parts of the system which are not in use to save power. Usually helpful for laptops.</p>
</li>
<li><p>[kcsan_init()] Initializes KCSAN tool which can detect data races within the kernel code. We can enable this tool by using the setting CONFIG_KCSAN=y and then compile the kernel. Initialization happens by adding a random value to per_cpu_data called ‘kcsan_rand_state’ variable.</p>
</li>
<li><p>[rest_init()] As a last step, spawns ‘init’ process as a user space process and assigns PID of 1 and spawns kernel thread ‘kthreadd’ and assigns it a PID of 2. A new ‘idle’ process is created (also called swapper process) with PID 0. This swapper process is scheduled by the scheduler when no other process is available to be scheduled on the CPU.</p>
<ul>
<li>How do you identify kernel threads ? These are process which are reported in [] brackets when you run ‘ps’ command, as shown below:</li>
</ul>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1760836418092/b3904664-0790-4dfc-83f6-d5530911fff5.png" alt class="image--right mx-auto mr-0" /></p>
<ul>
<li>As you can see here, PID 1 is assigned to init process, PID 2 is assigned to first kernel thread ‘kthreadd’ and all the kernel threads are created by this thread and have a parent PID of 2 and are displayed in square brackets ([]).</li>
</ul>
]]></content:encoded></item></channel></rss>