Creating Kthread
====================


.. panels::
    :container: container pb-4
    :column: col-lg-12 p-2
    :card: shadow

    Topics in this section,

        * :ref:`Version Info <p1_Kthread_0>`

        * :ref:`Learnings in this section <p1_Kthread_1>`

        * :ref:`Explanation of kthread APIs <p1_Kthread_2>`

            * :ref:`kthread_create_on_node <p1_Kthread_3>`

            * :ref:`kthread_create <p1_Kthread_4>`

            * :ref:`kthread_should_stop <p1_Kthread_5>`

            * :ref:`kthread_run <p1_Kthread_6>`

            * :ref:`kthread_stop <p1_Kthread_7>`

        * :ref:`Explanation of miscellaneous APIs <p1_Kthread_8>`

            * :ref:`Module parameter APIs <p1_Kthread_9>`

            * :ref:`IS_ERR <p1_Kthread_10>`

            * :ref:`pr_info <p1_Kthread_11>`

            * :ref:`wake_up_process <p1_Kthread_12>`

            * :ref:`msleep <p1_Kthread_13>`

            * :ref:`Driver entry point APIs <p1_Kthread_14>`

        * :ref:`Example 1: Creating thread using kthread_run <p1_Kthread_15>`

            * :ref:`List of headers <p1_Kthread_16>`

            * :ref:`Module Macros <p1_Kthread_17>`

            * :ref:`Initialize thread variables <p1_Kthread_18>`

            * :ref:`Module init function <p1_Kthread_19>`

            * :ref:`Thread start function <p1_Kthread_52>`

            * :ref:`Module exit function <p1_Kthread_20>`

            * :ref:`Thread stop function <p1_Kthread_53>`

            * :ref:`Thread function API <p1_Kthread_21>`

            * :ref:`Driver entry points <p1_Kthread_22>`

            * :ref:`See the full program below <p1_Kthread_23>`

            * :ref:`Makefile <p1_Kthread_24>`

            * :ref:`Compile and Load the module <p1_Kthread_25>`

        * :ref:`Example 2: Creating thread using kthread_create <p1_Kthread_26>`
 
            * :ref:`List of headers <p1_Kthread_27>`
 
            * :ref:`Module Macros <p1_Kthread_28>`
 
            * :ref:`Initialize thread variables <p1_Kthread_29>`
 
            * :ref:`Module init function <p1_Kthread_30>`

            * :ref:`Thread start function <p1_Kthread_50>`
 
            * :ref:`Module exit function <p1_Kthread_31>`

            * :ref:`Thread stop function <p1_Kthread_51>`
 
            * :ref:`Thread function API <p1_Kthread_32>`
 
            * :ref:`Driver entry points <p1_Kthread_33>`
 
            * :ref:`See the full program below <p1_Kthread_34>`
 
            * :ref:`Makefile <p1_Kthread_35>`
 
            * :ref:`Compile and Load the module <p1_Kthread_36>`

        * :ref:`Example 3: Creating thread using kthread_create_on_node <p1_Kthread_37>`

            * :ref:`List of headers <p1_Kthread_38>`
  
            * :ref:`Module Macros <p1_Kthread_39>`
  
            * :ref:`Initialize thread variables <p1_Kthread_40>`
  
            * :ref:`Module init function <p1_Kthread_41>`

            * :ref:`Thread start function <p1_Kthread_54>`
  
            * :ref:`Module exit function <p1_Kthread_42>`

            * :ref:`Thread stop function <p1_Kthread_55>`
  
            * :ref:`Thread function API <p1_Kthread_43>`
  
            * :ref:`Driver entry points <p1_Kthread_44>`
  
            * :ref:`See the full program below <p1_Kthread_45>`
  
            * :ref:`Makefile <p1_Kthread_46>`
  
            * :ref:`Compile and Load the module <p1_Kthread_47>`

        * :ref:`Summary of Kthread APIs <p1_Kthread_48>`

        * :ref:`Summary of Miscellaneous APIs <p1_Kthread_49>`

.. _p1_Kthread_0:
 
.. tab-set::
 
    .. tab-item:: Version Info

        =============================== =======================================
        #                               Version
        =============================== =======================================
        Ubuntu                          Ubuntu 22.10
        Kernel                          6.7.9
        =============================== =======================================


.. _p1_Kthread_1:
 
.. tab-set::
 
    .. tab-item:: Learnings in this section

        * In this program, you are going to learn

        .. panels::
                :container: container pb-4
                :column: col-lg-12 p-2
                :card: shadow

                * How to create the kernel thread ?

        .. panels::
                :container: container pb-4
                :column: col-lg-12 p-2
                :card: shadow

                * What are the different ways to create kernel thread?

        .. panels::
                :container: container pb-4
                :column: col-lg-12 p-2
                :card: shadow

                * How to stop the kernel thread ?

        .. panels::
                :container: container pb-4
                :column: col-lg-12 p-2
                :card: shadow

                * How to use Kthread APIs ?

                        * `kthread_create_on_node <https://elixir.bootlin.com/linux/v6.7.9/source/include/linux/kthread.h#L11>`_

                        * `kthread_create <https://elixir.bootlin.com/linux/v6.7.9/source/include/linux/kthread.h#L27>`_

                        * `kthread_should_stop <https://elixir.bootlin.com/linux/v6.7.9/source/include/linux/kthread.h#L90>`_

                        * `kthread_run <https://elixir.bootlin.com/linux/v6.7.9/source/include/linux/kthread.h#L51>`_

                        * `kthread_stop <https://elixir.bootlin.com/linux/v6.7.9/source/include/linux/kthread.h#L88>`_

        .. panels::
                :container: container pb-4
                :column: col-lg-12 p-2
                :card: shadow

                * How to use below APIs ?

                        * `MODULE_LICENSE <https://elixir.bootlin.com/linux/v6.7.9/source/include/linux/module.h#L230>`_

                        * `MODULE_DESCRIPTION <https://elixir.bootlin.com/linux/v6.7.9/source/include/linux/module.h#L239>`_

                        * `MODULE_AUTHOR <https://elixir.bootlin.com/linux/v6.7.9/source/include/linux/module.h#L236>`_

                        * `IS_ERR <https://elixir.bootlin.com/linux/v6.2/source/tools/include/linux/err.h#L45>`_

                        * `pr_info <https://elixir.bootlin.com/linux/v6.7.9/source/include/linux/printk.h#L527>`_

                        * `wake_up_process <https://elixir.bootlin.com/linux/v6.7.9/source/include/linux/sched.h#L1999>`_

                        * `msleep <https://elixir.bootlin.com/linux/v6.7.9/source/include/linux/delay.h#L61>`_

                        * `module_init <https://elixir.bootlin.com/linux/v6.7.9/source/include/linux/module.h#L88>`_

                        * `module_exit <https://elixir.bootlin.com/linux/v6.7.9/source/include/linux/module.h#L100>`_

.. _p1_Kthread_2:

.. tab-set::

    .. tab-item:: Explanation of Kthread APIs

        .. _p1_Kthread_3:

        .. tab-set::

            .. tab-item:: kthread_create_on_node

                * Here is the function prototype of the API: `kthread_create_on_node <https://elixir.bootlin.com/linux/v6.7.9/source/include/linux/kthread.h#L11>`_

                .. code-block:: c

                    #include <linux/kthread.h>

                    struct task_struct *kthread_create_on_node(int (*threadfn)(void *data),
					                                            void *data,
					                                            int node,
					                                            const char namefmt[], ...);

   
                * where

                    * `kthread_create_on_node <https://elixir.bootlin.com/linux/v6.7.9/source/include/linux/kthread.h#L11>`_: creates a kthread on the current node.

                    * return type: struct task_struct* (i.e) returns the address of the kthread.

                    * threadfn: the function to execute on kthread

                    * data: data pointer for the threadfn which can be used to pass any possible arguments required for the threadfn.

                    * namefmt: printf-style format string for the thread name which will be displayed on ps output when the thread is in execution.


                * Here is an example of how to use the API,

                .. code-block:: c

                   kthread_create_on_node(mythread,NULL,0,"sample kthread");


        .. _p1_Kthread_4:

        .. tab-set::

            .. tab-item:: kthread_create

                * Here is the function prototype of the API: `kthread_create <https://elixir.bootlin.com/linux/v6.7.9/source/include/linux/kthread.h#L27>`_

                .. code-block:: c

                    #include <linux/kthread.h>

                    #define kthread_create(threadfn, data, namefmt, arg...) \
	                    kthread_create_on_node(threadfn, data, NUMA_NO_NODE, namefmt, ##arg)


                * where

                    * `kthread_create <https://elixir.bootlin.com/linux/v6.7.9/source/include/linux/kthread.h#L27>`_: creates a kthread and can be waked up to start its execution using wake_up_process

                    * return type: struct task_struct* (i.e) returns the address of the kthread

                    * threadfn: the function to execute on kthread

                    * data: data pointer for the threadfn which can be used to pass any possible arguments required for the threadfn.

                    * namefmt: printf-style format for the thread name which will be displayed on ps output when the thread is in execution.


                * Here is an example of how to use the API,

                .. code-block:: c

                    kthread_create(mythread,NULL,"sample kthread");


        .. _p1_Kthread_5:

        .. tab-set::

            .. tab-item:: kthread_should_stop

                * Here is the function prototype of the API: `kthread_should_stop <https://elixir.bootlin.com/linux/v6.7.9/source/include/linux/kthread.h#L90>`_

                .. code-block:: c

                    #include <linux/kthread.h>

                    bool kthread_should_stop(void);

                * where

                    * `kthread_should_stop <https://elixir.bootlin.com/linux/v6.7.9/source/include/linux/kthread.h#L90>`_: this is used to determine whether the thread should return now. Whenever the `kthread_stop() <https://elixir.bootlin.com/linux/v6.7.9/source/include/linux/kthread.h#L88>`_ is called it will be woken and returns true.

                    * return type: returns true when the thread is stopped, false when the thread is still in execution


                * Here is an example of how to use the API,

                .. code-block:: c

                    while (!kthread_should_stop())
                    {
                        //add the instructions to be performed during thread execution.
                    }


        .. _p1_Kthread_6:

        .. tab-set::

            .. tab-item:: kthread_run

                * Here is the function prototype of the API: `kthread_run <https://elixir.bootlin.com/linux/v6.7.9/source/include/linux/kthread.h#L51>`_

                .. code-block:: c

                    #include <linux/kthread.h>

                    #define kthread_run(threadfn, data, namefmt, ...)

                * where

                    * `kthread_run <https://elixir.bootlin.com/linux/v6.7.9/source/include/linux/kthread.h#L51>`_ : is used to create and wake a kthread

                    * return type: struct task_struct* (i.e) address of the kthread

                    * threadfn: function to executed by kthread

                    * data: data pointer for threadfn which can be used to send any possible arguments required for threadfn.

                    * namefmt: printf-style format for the thread name which will be displayed on ps output when the thread is in execution.

                * Here is an example of how to use the API,

                .. code-block:: c

                    kthread_run(mythread,NULL,"sample kthread");


        .. _p1_Kthread_7:

        .. tab-set::

            .. tab-item:: kthread_stop

                * Here is the function prototype of the API: `kthread_stop <https://elixir.bootlin.com/linux/v6.7.9/source/include/linux/kthread.h#L88>`_

                .. code-block:: c

                    #include <linux/kthread.h>

                    int kthread_stop(struct task_struct *k);

                * where

                    * `kthread_stop <https://elixir.bootlin.com/linux/v6.7.9/source/include/linux/kthread.h#L88>`_: stops a kthread.

                    * return type: returns the return value of threadfn() which is passed as an argument during kthread creation. 

                    * k: kthread created by one of the API used to created kthread.

                * Here is the example of how to use the API,

                .. code-block:: c

                    kthread_stop(mythread);

.. _p1_Kthread_8:

.. tab-set::

    .. tab-item:: Explanation of miscellaneous APIs

        .. _p1_Kthread_9:

        .. tab-set::

            .. tab-item:: Module parameter APIs

                * Here is the prototype of module paramter APIs

                .. code-block:: c

                    #include <linux/module.h>

                    #define MODULE_LICENSE(_license) MODULE_FILE MODULE_INFO(license, _license)
                    #define MODULE_AUTHOR(_author) MODULE_INFO(author, _author)
                    #define MODULE_DESCRIPTION(_description) MODULE_INFO(description, _description)


                * where

                    * `MODULE_LICENSE <https://elixir.bootlin.com/linux/v6.7.9/source/include/linux/module.h#L230>`_: tells the kernel what license is used by our module.

                    * `MODULE_AUTHOR <https://elixir.bootlin.com/linux/v6.7.9/source/include/linux/module.h#L236>`_: denotes the author of this kernel module.

                    * `MODULE_DESCRIPTION <https://elixir.bootlin.com/linux/v6.7.9/source/include/linux/module.h#L239>`_: gives a basic idea about what the kernel module does.

                    * These information can be found when modinfo command is used which lists out all these above mentioned information.


                * Here is the example of how to use the Module parameter APIs,

                .. code-block:: c

                    MODULE_LICENSE("GPL");
                    MODULE_AUTHOR("Linux Usr");
                    MODULE_DESCRIPTION("Sample kernel module");

        .. _p1_Kthread_10:

        .. tab-set::

            .. tab-item:: IS_ERR

                * Here is the prototype of the API: `IS_ERR <https://elixir.bootlin.com/linux/v6.2/source/tools/include/linux/err.h#L45>`_

                .. code-block:: c

                    #include <linux/err.h>

                    static inline bool __must_check IS_ERR(__force const void *ptr);

                * where

                    * `IS_ERR <https://elixir.bootlin.com/linux/v6.2/source/tools/include/linux/err.h#L45>`_: Detects an error pointer

                    * return type: return true if it's an error pointer else return false.

                    * ptr: pointer which needs to detected.

                * Here is an example of how to use the API,

                .. code-block:: c

                    if(IS_ERR(sample_ptr)) {
                        //instructions to be executed when error ptr is detected
                    } else {
                        //instructions to be executed when error ptr is not detected
                    }

        .. _p1_Kthread_11:

        .. tab-set::

            .. tab-item:: pr_info

                * Here is the prototype of the API: `pr_info <https://elixir.bootlin.com/linux/v6.7.9/source/include/linux/printk.h#L527>`_

                .. code-block:: c

                    #include <linux/printk.h>

                    #define pr_info(fmt, ...) \
                        printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)

                * where
                    
                    * `pr_info <https://elixir.bootlin.com/linux/v6.7.9/source/include/linux/printk.h#L527>`_: Prints an info-level messages

                    * fmt: format string

                * Here is an example of how to use the API,

                .. code-block:: c

                    pr_info("//sample print statement");

        .. _p1_Kthread_12:

        .. tab-set::

            .. tab-item:: wake_up_process

                * Here is the example of the API: `wake_up_process <https://elixir.bootlin.com/linux/v6.7.9/source/include/linux/sched.h#L1999>`_

                .. code-block:: c

                    #include <linux/sched.h>

                    extern int wake_up_process(struct task_struct *tsk);
    
                * where

                    * `wake_up_process <https://elixir.bootlin.com/linux/v6.7.9/source/include/linux/sched.h#L1999>`_: wake up a specific process

                    * return type: returns 1 if the process is woken up, 0 if the process is in running state.

                    * tsk: process to be woken up.

                * Here is the example of how to use the API,

                .. code-block:: c

                    wake_up_process(mythread);

        .. _p1_Kthread_13:

        .. tab-set::

            .. tab-item:: msleep

                * Here is the example of the API: `msleep <https://elixir.bootlin.com/linux/v6.7.9/source/include/linux/delay.h#L61>`_

                .. code-block:: c

                    #include <linux/delay.h>

                    void msleep(unsigned int msecs);

                * where

                    * `msleep <https://elixir.bootlin.com/linux/v6.7.9/source/include/linux/delay.h#L61>`_: will put it in sleep for a certain amount of msecs time.

                    * msecs: time in milliseconds to sleep for

                * Here is the example of how to use the API,

                .. code-block:: c

                    msleep(1000);

        .. _p1_Kthread_14:

        .. tab-set::

            .. tab-item:: Driver entry point API's

                * Here is the prototype of the Driver entry point API's

                .. code-block:: c

                    #include <linux/module.h>

                    #define module_init(x)	__initcall(x);
                    #define module_exit(x)	__exitcall(x);

                * where

                    * `module_init <https://elixir.bootlin.com/linux/v6.7.9/source/include/linux/module.h#L88>`_: driver initialization entry point which will be called at module insertion time.

                    * `module_exit <https://elixir.bootlin.com/linux/v6.7.9/source/include/linux/module.h#L100>`_: driver exit entry point which will be called during the removal of module.

                    * x:    
                            * function to be run at module insertion for `module_init <https://elixir.bootlin.com/linux/v6.7.9/source/include/linux/module.h#L88>`_ function.
                            * function to be run when driver is removed for `module_exit <https://elixir.bootlin.com/linux/v6.7.9/source/include/linux/module.h#L100>`_ function.

                * Here is an example of how to use the driver entry point API's

                .. code-block:: c

                    module_init(myinitmodule);
                    module_exit(myexitmodule);


.. _p1_Kthread_15:

.. tab-set::

    .. tab-item:: Example 1: Creating Kthread using kthread_run

        * In this example let's see how to create kthread using kthread_run and execute it.

        .. _p1_Kthread_16:

        .. tab-set::

            .. tab-item:: List of headers

                * Include the follow header files(.h) to refer the API being used for the execution.

                .. code-block:: c

                     #include <linux/init.h>
                     #include <linux/kernel.h>
                     #include <linux/kthread.h>
                     #include <linux/module.h>
                     #include <linux/delay.h>

        .. _p1_Kthread_17:

        .. tab-set::

            .. tab-item:: Module macros

                * Add the following module macros to display information about the license, author and description about the module.

                .. code-block:: c

                     MODULE_LICENSE("GPL");
                     MODULE_AUTHOR("Linux Usr");
                     MODULE_DESCRIPTION("Example of kthread_run");

        .. _p1_Kthread_18:

        .. tab-set::

            .. tab-item:: Initialize thread variables

                * Declare the thread variables which we are going to create and use in this example

                .. code-block:: c

                    static struct task_struct *def_thread;

        .. _p1_Kthread_19:

        .. tab-set::

            .. tab-item:: Module init function

                * Add the module init function which will be executed once we load the kernel module using insmod command.

                .. code-block:: c

                    static int __init kthread_run_init(void)
                    {
                        pr_info("Inside thread_init function\n");
                        thread_start();
                        return 0;
                    }

        .. _p1_Kthread_52:

        .. tab-set::

            .. tab-item:: Thread start function

                * Add the thread start function which is called from module init function, creates the thread and starts it's execution.

                .. code-block:: c

                    void thread_start(void)
                    {
                        def_thread = kthread_run(def_thread_task,NULL,"kthread_run examples");
                        if (IS_ERR(def_thread))
                            pr_info ("Error creatig death\n");
                        else
                            pr_info ("thread created successfully\n");
                    }


        .. _p1_Kthread_20:

        .. tab-set::

            .. tab-item:: Module exit function

                * Add the module exit function which will be executed once we unload the kernel module using rmmod command.

                .. code-block:: c

                    static void __exit kthread_run_exit(void)
                    {
                        pr_info("Inside kthread exit function\n");
                        thread_stop();
                    }

        .. _p1_Kthread_53:

        .. tab-set::

            .. tab-item:: Thread stop function

                * Add the thread stop function which is called from module exit function, destroys the thread created and stops it's execution.

                .. code-block:: c

                    void thread_stop(void)
                    {
                        kthread_stop(def_thread);
                        pr_info("Destroyed thread\n");
                    }

        .. _p1_Kthread_21:

        .. tab-set::

            .. tab-item:: Thread function API

                * Add the thread function API which will be called as soon as the kthread is created and is in running state.

                .. code-block:: c

                    int def_thread_task(void *data)
                    {
                        while(!kthread_should_stop()) {
                            pr_info("Executing def_thread_task\n");
                            msleep(1000);
                        }
                        return 0;
                    }

        .. _p1_Kthread_22:

        .. tab-set::

            .. tab-item:: Driver entry points

                * Add the driver entry points which will be executed once the module is inserted or removed from the kernel.

                .. code-block:: c
    
                    module_init(kthread_run_init);
                    module_exit(kthread_run_exit);

        .. _p1_Kthread_23:

        .. tab-set::

            .. tab-item:: See the full program below

                .. tab-set::
                    
                    .. tab-item:: kthread.c

                       .. literalinclude:: p1_createKthread/kthread_run/kthread.c
                            :language: c
                            :linenos:

        .. _p1_Kthread_24:

        .. tab-set::

            .. tab-item:: Makefile

                .. literalinclude:: p1_createKthread/kthread_run/Makefile
                    :language: c
                    :linenos:

        .. _p1_Kthread_25:

        .. tab-set::

            .. tab-item:: Compile and load the module

                * Run make to compile the kernel source and generate the .ko image.

                .. code-block:: shell

                    make -C /lib/modules/6.7.9/build M=$HOME/kthread_examples/
                    make[1]: Entering directory '/usr/src/linux-headers-6.7.9'
                    warning: the compiler differs from the one used to build the kernel
                    The kernel was built by: x86_64-linux-gnu-gcc (Ubuntu 12.2.0-3ubuntu1) 12.2.0
                    You are using:           gcc (Ubuntu 12.2.0-3ubuntu1) 12.2.0
                    CC [M]  $HOME/kthread_examples/kthread.o
                    MODPOST $HOME/kthread_examples/Module.symvers
                    CC [M]  $HOME/kthread_examples/kthread.mod.o
                    LD [M]  $HOME/kthread_examples/kthread.ko
                    BTF [M] $HOME/kthread_examples/kthread.ko
                    Skipping BTF generation for $HOME/kthread_examples/kthread.ko due to unavailability of vmlinux
                    make[1]: Leaving directory '/usr/src/linux-headers-6.7.9'


                * Check if the .ko is generated or not using ls command.

                .. code-block:: shell

                    test@test-V520-15IKL:~$ ls -l
                    total 360
                    -rw-rw-r-- 1 test test    713 Mar 18 16:06 kthread.c
                    -rw-rw-r-- 1 test test 169784 Mar 18 16:08 kthread.ko
                    -rw-rw-r-- 1 test test     58 Mar 18 16:08 kthread.mod
                    -rw-rw-r-- 1 test test   1047 Mar 18 16:08 kthread.mod.c
                    -rw-rw-r-- 1 test test  96512 Mar 18 16:08 kthread.mod.o
                    -rw-rw-r-- 1 test test  74696 Mar 18 16:08 kthread.o
                    -rw-rw-r-- 1 test test    161 Mar 18 16:00 Makefile
                    -rw-rw-r-- 1 test test     58 Mar 18 16:08 modules.order
                    -rw-rw-r-- 1 test test      0 Mar 18 16:08 Module.symvers

                * Run modinfo command to get the information about the kernel module.
 
                .. code-block:: shell
 
                    test@test-V520-15IKL:~/.../tc_1$ modinfo kthread.ko
                    filename:       $HOME/kthread_examples/kthread.ko
                    description:    Example of kthread_run
                    author:         Linux Usr
                    license:        GPL
                    srcversion:     8D2147F67AB01CF0E482DAC
                    depends:
                    retpoline:      Y
                    name:           kthread
                    vermagic:       6.7.9 SMP preempt mod_unload modversions

                * insert the module using insmod command.

                .. code-block:: shell

                    test@test-V520-15IKL:~$ sudo insmod ./kthread.ko

                * check if the module is loaded or not using lsmod command.

                .. code-block:: shell

                    test@test-V520-15IKL:~$ sudo lsmod | grep kthread
                    kthread                16384  0

                * check if the thread is created or not using ps command.

                .. code-block:: shell

                    test@test-V520-15IKL:~$ ps -N | grep kthread_run
                    33753 ?        00:00:00 kthread_run examples

                * check for the kernel messages from init function and thread function once the module is loaded and thread is created.

                .. code-block:: shell
             
                    test@test-V520-15IKL:~$ sudo dmesg
                    [ 9245.487512] Inside thread_init function
                    [ 9245.487534] thread created successfully
                    [ 9245.487535] Executing def_thread_task
                    [ 9246.508165] Executing def_thread_task
                    [ 9247.528053] Executing def_thread_task

                * remove the module from kernel using rmmod command.

                .. code-block:: shell

                    test@test-V520-15IKL:~$ sudo rmmod kthread

                * check if the module is still loaded after removing the kernel module using lsmod if it is not displayed in lsmod output it is verified that the module is removed successfully.

                .. code-block:: shell

                    test@test-V520-15IKL:~$ sudo lsmod | grep kthread
                    test@test-V520-15IKL:~$

                * check if the thread is destroyed using ps command if it is not displayed in ps output we can confirm that the thread is destroyed successfully.
 
                .. code-block:: shell
 
                    test@test-V520-15IKL:~$ ps -N | grep kthread_run
                    test@test-V520-15IKL:~$

                * Check for kernel messages from exit function using dmesg command.

                .. code-block:: shell

                    test@test-V520-15IKL:~$ sudo dmesg
                    [ 9247.746660] Inside thread exit function
                    [ 9248.552306] Destroyed thread


.. _p1_Kthread_26:
 
.. tab-set::
 
    .. tab-item:: Example 2: Creating Kthread using kthread_create
 
        * In this example let's see how to create kthread using kthread_create and execute it.
 
        .. _p1_Kthread_27:
 
        .. tab-set::
 
            .. tab-item:: List of headers
 
                * Include the follow header files(.h) to refer the API being used for the execution.
 
                .. code-block:: c

                    #include <linux/init.h>
                    #include <linux/kernel.h>
                    #include <linux/module.h>
                    #include <linux/kthread.h>
                    #include <linux/delay.h>
                    #include <linux/threads.h>

        .. _p1_Kthread_28:
 
        .. tab-set::
 
            .. tab-item:: Module macros
 
                * Add the following module macros to display information about the license, author and description about the module.
 
                .. code-block:: c
 
                    MODULE_LICENSE("GPL");
                    MODULE_AUTHOR("Linux Usr");
                    MODULE_DESCRIPTION("example of kthread_create");
 
        .. _p1_Kthread_29:
 
        .. tab-set::
 
            .. tab-item:: Initialize thread variables
 
                * Declare the thread variables which we are going to create and use in this example
 
                .. code-block:: c

                    static struct task_struct *def_thread;

        .. _p1_Kthread_30:
 
        .. tab-set::
 
            .. tab-item:: Module init function
 
                * Add the module init function which will be executed once we load the kernel module using insmod command.
 
                .. code-block:: c
                
                    static int __init kthread_create_init(void)
                    {
                        pr_info("Inside kthread init function\n");
                        thread_start();
                        return 0;
                    }

        .. _p1_Kthread_50:

        .. tab-set::

            .. tab-item:: Thread start function

                * Add the thread start function called from the module init function which is used to create the thread and execute it.

                .. code-block:: c

                    void thread_start(void)
                    {
                        def_thread = kthread_create(my_thread_fn,NULL,"kthread_create examples");
                        if(IS_ERR(def_thread))
                            pr_info("Error in creating thread\n");
                        else {
                            pr_info("Thread created successfully\n");
                            wake_up_process(def_thread);
                            pr_info("wake up process done successfully\n");
                        }
                    }

        .. _p1_Kthread_31:
 
        .. tab-set::
 
            .. tab-item:: Module exit function
 
                * Add the module exit function which will be executed once we unload the kernel module using rmmod command.
 
                .. code-block:: c

                    static void __exit kthread_create_exit(void)
                    {
                        pr_info("Inside kthread exit function\n");
                        thread_stop();
                    }

        .. _p1_Kthread_51:

        .. tab-set::

            .. tab-item:: Thread stop function

                * Add the thread stop function called from the module exit function which is used to destroy the thread and stop its execution.

                .. code-block:: c

                    void thread_stop(void)
                    {
                        kthread_stop(def_thread);
                        pr_info("Destroyed thread\n");
                    }

        .. _p1_Kthread_32:
 
        .. tab-set::
 
            .. tab-item:: Thread function API
 
                * Add the thread function API which will be called as soon as the kthread is created and is in running state.
 
                .. code-block:: c

                    int my_thread_fn(void *data)
                    {
                        while(!kthread_should_stop()) {
                            pr_info("inside my_thread_fn\n");
                            msleep(100);
                        }   
                        return 0;
                    }
 
        .. _p1_Kthread_33:
 
        .. tab-set::
 
            .. tab-item:: Driver entry points
 
                * Add the driver entry points which will be executed once the module is inserted or removed from the kernel.
 
                .. code-block:: c

                    module_init(kthread_create_init);
                    module_exit(kthread_create_exit);

        .. _p1_Kthread_34:
 
        .. tab-set::
 
            .. tab-item:: See the full program below
 
                .. tab-set::
                     
                    .. tab-item:: kthread.c
 
                        .. literalinclude:: p1_createKthread/kthread_create/kthread.c
                            :language: c
                            :linenos:
 
        .. _p1_Kthread_35:
 
        .. tab-set::
 
            .. tab-item:: Makefile
 
                .. literalinclude:: p1_createKthread/kthread_create/Makefile
                    :language: c
                    :linenos:

        .. _p1_Kthread_36:
 
        .. tab-set::
 
            .. tab-item:: Compile and load the module
 
                * Run make to compile the kernel source and generate the .ko image.
 
                .. code-block:: shell
 
                    make -C /lib/modules/6.7.9/build M=$HOME/kthread_examples/
                    make[1]: Entering directory '/usr/src/linux-headers-6.7.9'
                    warning: the compiler differs from the one used to build the kernel
                    The kernel was built by: x86_64-linux-gnu-gcc (Ubuntu 12.2.0-3ubuntu1) 12.2.0
                    You are using:           gcc (Ubuntu 12.2.0-3ubuntu1) 12.2.0
                    CC [M]  $HOME/kthread_examples/kthread.o
                    MODPOST $HOME/kthread_examples/Module.symvers
                    CC [M]  $HOME/kthread_examples/kthread.mod.o
                    LD [M]  $HOME/kthread_examples/kthread.ko
                    BTF [M] $HOME/kthread_examples/kthread.ko
                    Skipping BTF generation for $HOME/kthread_examples/kthread.ko due to unavailability of vmlinux
                    make[1]: Leaving directory '/usr/src/linux-headers-6.7.9'
 
 
                * Check if the .ko is generated or not using ls command.
 
                .. code-block:: shell

                    test@test-V520-15IKL:~$ ls -l
                    total 360
                    -rw-rw-r-- 1 test test    713 Mar 18 16:06 kthread.c
                    -rw-rw-r-- 1 test test 169784 Mar 18 16:08 kthread.ko
                    -rw-rw-r-- 1 test test     58 Mar 18 16:08 kthread.mod
                    -rw-rw-r-- 1 test test   1047 Mar 18 16:08 kthread.mod.c
                    -rw-rw-r-- 1 test test  96512 Mar 18 16:08 kthread.mod.o
                    -rw-rw-r-- 1 test test  74696 Mar 18 16:08 kthread.o
                    -rw-rw-r-- 1 test test    161 Mar 18 16:00 Makefile
                    -rw-rw-r-- 1 test test     58 Mar 18 16:08 modules.order
                    -rw-rw-r-- 1 test test      0 Mar 18 16:08 Module.symvers

                * Run modinfo command to get the information about the kernel module.
  
                .. code-block:: shell
  
                    test@test-V520-15IKL:~/.../tc_1$ modinfo kthread.ko
                    filename:       $HOME/kthread_examples/kthread.ko
                    description:    Example of kthread_create
                    author:         Linux Usr
                    license:        GPL
                    srcversion:     8D2147F67AB01CF0E482DAC
                    depends:
                    retpoline:      Y
                    name:           kthread
                    vermagic:       6.7.9 SMP preempt mod_unload modversions

                * insert the module using insmod command.
 
                .. code-block:: shell
 
                    test@test-V520-15IKL:~$ sudo insmod ./kthread.ko

                * check if the module is loaded or not using lsmod command.
 
                .. code-block:: shell
 
                    test@test-V520-15IKL:~$ sudo lsmod | grep kthread
                    kthread                16384  0
 
                * check if the thread is created or not using ps command.
 
                .. code-block:: shell
 
                    test@test-V520-15IKL:~$ ps -N | grep kthread_create
                    37279 ?        00:00:00 kthread_create examples
 
                * check for the kernel messages from init function and thread function once the module is loaded and thread is created.
 
                .. code-block:: shell
              
                    test@test-V520-15IKL:~$ sudo dmesg
                    [ 7208.702412] Inside kthread init function
                    [ 7208.702440] Thread created successfully
                    [ 7208.702441] wake up process done successfully
                    [ 7208.702443] inside my_thread_fn
                    [ 7208.809751] inside my_thread_fn
                    [ 7208.917731] inside my_thread_fn

                * remove the module from kernel using rmmod command.
 
                .. code-block:: shell
 
                    test@test-V520-15IKL:~$ sudo rmmod kthread

                * check if the module is still loaded after removing the kernel module using lsmod if it is not displayed in lsmod output it is verified that the module is removed successfully.
 
                .. code-block:: shell
 
                    test@test-V520-15IKL:~$ sudo lsmod | grep kthread
                    test@test-V520-15IKL:~$
 
                * check if the thread is destroyed using ps command if it is not displayed in ps output we can confirm that the thread is destroyed successfully.
  
                .. code-block:: shell
  
                    test@test-V520-15IKL:~$ ps -N | grep kthread_create
                    test@test-V520-15IKL:~$
 
                * Check for kernel messages from exit function using dmesg command.

                .. code-block:: shell
 
                    test@test-V520-15IKL:~$ sudo dmesg
                    [ 7211.926351] Inside kthread exit function
                    [ 7211.961807] Destroyed thread
 
.. _p1_Kthread_37:
  
.. tab-set::
  
    .. tab-item:: Example 3: Creating Kthread using kthread_create_on_node
  
        * In this example let's see how to create kthread using kthread_create_on_node and execute it.
  
        .. _p1_Kthread_38:
  
        .. tab-set::
  
            .. tab-item:: List of headers
  
                * Include the follow header files(.h) to refer the API being used for the execution.
  
                .. code-block:: c
                
                    #include <linux/init.h>
                    #include <linux/kernel.h>
                    #include <linux/module.h>
                    #include <linux/kthread.h>
                    #include <linux/delay.h>
                    #include <linux/threads.h>

        .. _p1_Kthread_39:
  
        .. tab-set::
  
            .. tab-item:: Module macros
  
                * Add the following module macros to display information about the license, author and description about the module.
  
                .. code-block:: c
  
                    MODULE_LICENSE("GPL");
                    MODULE_AUTHOR("Linux Usr");
                    MODULE_DESCRIPTION("example of kthread_create_on_node");
  
        .. _p1_Kthread_40:
  
        .. tab-set::
  
            .. tab-item:: Initialize thread variables
  
                * Declare the thread variables which we are going to create and use in this example
  
                .. code-block:: c
 
                    static struct task_struct *def_thread;

        .. _p1_Kthread_41:
  
        .. tab-set::
  
            .. tab-item:: Module init function
  
                * Add the module init function which will be executed once we load the kernel module using insmod command.
  
                .. code-block:: c
                 
                    static int __init kthread_create_on_node_init(void)
                    {                         
                        pr_info("Inside kthread init function\n");
                        thread_start();
                        return 0;
                    }
 
        .. _p1_Kthread_54:

        .. tab-set::

            .. tab-item:: thread start function

                * Add the thread start function called from module init function, which creates the thread, wakes it up and starts its execution.

                .. code-block::

                    void thread_start(void)
                    {
                        def_thread = kthread_create_on_node(my_thread_fn,NULL,0,"kthread_create_on_node example");
                        if(IS_ERR(def_thread))
                            pr_info("Error in creating thread\n");
                        else {
                            pr_info("Thread created successfully\n");
                            wake_up_process(def_thread);
                            pr_info("wake up process done successfully\n");
                        }
                    }

        .. _p1_Kthread_42:
  
        .. tab-set::
  
            .. tab-item:: Module exit function
  
                * Add the module exit function which will be executed once we unload the kernel module using rmmod command.
  
                .. code-block:: c

                    static void __exit kthread_create_on_node_exit(void)
                    {
                        pr_info("Inside kthread exit function\n");
                        thread_stop();
                    }

        .. _p1_Kthread_55:

        .. tab-set::

            .. tab-item:: thread stop function

                * Add the thread stop function which is called from module exit function, which destroys the thread and stops the execution.

                .. code-block:: c

                    void thread_stop(void)
                    {
                        kthread_stop(def_thread);
                        pr_info("Destroyed thread\n");
                    }

        .. _p1_Kthread_43:
  
        .. tab-set::
  
            .. tab-item:: Thread function API
  
                * Add the thread function API which will be called as soon as the kthread is created and is in running state.
  
                .. code-block:: c
 
                    int my_thread_fn(void *data)
                    {
                        while(!kthread_should_stop()) {
                            pr_info("inside my_thread_fn\n");
                            msleep(100);
                        }
                        return 0;
                    }
  
        .. _p1_Kthread_44:
  
        .. tab-set::
  
            .. tab-item:: Driver entry points
  
                * Add the driver entry points which will be executed once the module is inserted or removed from the kernel.
  
                .. code-block:: c
 
                    module_init(kthread_create_on_node_init);
                    module_exit(kthread_create_on_node_exit);
                   
        .. _p1_Kthread_45:
  
        .. tab-set::
  
            .. tab-item:: See the full program below
  
                .. tab-set::
                      
                    .. tab-item:: kthread.c
  
                        .. literalinclude:: p1_createKthread/kthread_create_on_node/kthread.c
                            :language: c
                            :linenos:
  
        .. _p1_Kthread_46:
  
        .. tab-set::
  
            .. tab-item:: Makefile
  
                .. literalinclude:: p1_createKthread/kthread_create_on_node/Makefile
                    :language: c
                    :linenos:

        .. _p1_Kthread_47:
  
        .. tab-set::
  
            .. tab-item:: Compile and load the module
  
                * Run make to compile the kernel source and generate the .ko image.
  
                .. code-block:: shell
  
                    make -C /lib/modules/6.7.9/build M=$HOME/kthread_examples/
                    make[1]: Entering directory '/usr/src/linux-headers-6.7.9'
                    warning: the compiler differs from the one used to build the kernel
                    The kernel was built by: x86_64-linux-gnu-gcc (Ubuntu 12.2.0-3ubuntu1) 12.2.0
                    You are using:           gcc (Ubuntu 12.2.0-3ubuntu1) 12.2.0
                    CC [M]  $HOME/kthread_examples/kthread.o
                    MODPOST $HOME/kthread_examples/Module.symvers
                    CC [M]  $HOME/kthread_examples/kthread.mod.o
                    LD [M]  $HOME/kthread_examples/kthread.ko
                    BTF [M] $HOME/kthread_examples/kthread.ko
                    Skipping BTF generation for $HOME/kthread_examples/kthread.ko due to unavailability of vmlinux
                    make[1]: Leaving directory '/usr/src/linux-headers-6.7.9'
  
  
                * Check if the .ko is generated or not using ls command.
  
                .. code-block:: shell
 
                    test@test-V520-15IKL:~$ ls -l
                    total 360
                    -rw-rw-r-- 1 test test    713 Mar 18 16:06 kthread.c
                    -rw-rw-r-- 1 test test 169784 Mar 18 16:08 kthread.ko
                    -rw-rw-r-- 1 test test     58 Mar 18 16:08 kthread.mod
                    -rw-rw-r-- 1 test test   1047 Mar 18 16:08 kthread.mod.c
                    -rw-rw-r-- 1 test test  96512 Mar 18 16:08 kthread.mod.o
                    -rw-rw-r-- 1 test test  74696 Mar 18 16:08 kthread.o
                    -rw-rw-r-- 1 test test    161 Mar 18 16:00 Makefile
                    -rw-rw-r-- 1 test test     58 Mar 18 16:08 modules.order
                    -rw-rw-r-- 1 test test      0 Mar 18 16:08 Module.symvers
               
                * Run modinfo command to get the information about the kernel module.

                .. code-block:: shell

                    test@test-V520-15IKL:~/.../tc_1$ modinfo kthread.ko
                    filename:       $HOME/kthread_examples/kthread.ko
                    description:    Example of kthread_create_on_node
                    author:         Linux Usr
                    license:        GPL
                    srcversion:     8D2147F67AB01CF0E482DAC
                    depends:
                    retpoline:      Y
                    name:           kthread
                    vermagic:       6.7.9 SMP preempt mod_unload modversions

                * insert the module using insmod command.
  
                .. code-block:: shell
  
                    test@test-V520-15IKL:~$ sudo insmod ./kthread.ko
  
                * check if the module is loaded or not using lsmod command.
  
                .. code-block:: shell
  
                    test@test-V520-15IKL:~$ sudo lsmod | grep kthread
                    kthread                16384  0

                * check if the thread is created or not using ps command.

                .. code-block:: shell

                    test@test-V520-15IKL:~$ ps -N | grep kthread_create_on_node
                    37679 ?        00:00:00 kthread_create_on_node example

                * check for the kernel messages from init function and thread function once the module is loaded and thread is created.

                .. code-block:: shell

                    test@test-V520-15IKL:~$ sudo dmesg
                    [16449.337971] Inside kthread init function
                    [16449.337999] Thread created successfully
                    [16449.338000] wake up process done successfully
                    [16449.338002] inside my_thread_fn
                    [16449.442381] inside my_thread_fn
                    [16449.550441] inside my_thread_fn

                * remove the module from kernel using rmmod command.
  
                .. code-block:: shell
  
                    test@test-V520-15IKL:~$ sudo rmmod kthread

                * check if the module is still loaded after removing the kernel module using lsmod if it is not displayed in lsmod output it is verified that the module is removed successfully.
  
                .. code-block:: shell
  
                    test@test-V520-15IKL:~$ sudo lsmod | grep kthread
                    test@test-V520-15IKL:~$
  
                * check if the thread is destroyed using ps command if it is not displayed in ps output we can confirm that the thread is destroyed successfully.
   
                .. code-block:: shell
   
                    test@test-V520-15IKL:~$ ps -N | grep kthread_create_on_node
                    test@test-V520-15IKL:~$
  
                * Check for kernel messages from exit function using dmesg command.

                .. code-block:: shell
  
                    test@test-V520-15IKL:~$ sudo dmesg
                    [16451.230316] Inside kthread exit function
                    [16451.282283] Destroyed thread

.. _p1_Kthread_48:

.. tab-set::

    .. tab-item:: Summary of Kthread APIs

        =============================== =======================================
        kthread API                     Learning
        =============================== =======================================
        kthread_create_on_node          Create a thread on the current node
        kthread_create                  Create a thread
        kthread_run                     Create and wake a thread
        kthread_should_stop             To determine when thread should exit
        kthread_stop                    Stop a thread created by kthread_create
        =============================== =======================================

.. _p1_Kthread_49:

.. tab-set::

    .. tab-item:: Summary of miscellaneous APIs

        =============================== ===========================================================================================
        API                             Learning
        =============================== ===========================================================================================
        MODULE_LICENSE                  Used to denote the license used in the kernel module
        MODULE_AUTHOR                   Used to mention the author of the kernel module
        MODULE_DESCRIPTION              Used to describe what the module does
        IS_ERR                          Detects an error pointer
        wake_up_process                 wake up a specific process
        msleep                          will put in sleep for a certain amount of msecs time.
        module_init                     Driver initialization entry point
        module_exit                     Driver exit entry point
        pr_info                         Print an info-level message
        =============================== ===========================================================================================