Creation and destruction of Linux kernel threads

Source: Internet
Author: User

Linux will create the kernel thread to the work of a dedicated kernel thread kthreadd to complete, the thread will check the global list kthread_create_list, if it is null, will be schedule () to abandon the CPU to sleep state, Otherwise, remove one item from the list to create the corresponding thread. This article demonstrates the creation of kernel threads from the beginning of the creation of Khtreadd kernel threads.
1 Kthreadd
linux2.6.30, the creation of kernel threads is done through the Kethradd kernel daemon thread, although the mechanism changes, but eventually calls Do_fork to complete the thread creation. The Kthreadd daemon is a kernel thread that has been created when the Linux kernel is booted. At the end of the Start_kernel call, the Rest_init interface is called, and Kthreadd is created in this interface, as shown in the following code:
asmlinkage void __init start_kernel (void)
{
。。。。。。。。。。。。。。。。。。。。。。
Rest_init ();
}
static noinline void __init_refok rest_init (void)
__releases (Kernel_lock)
{
int pid;
/* Creates a kernel thread at startup, which is used primarily to create kernel threads */
PID = Kernel_thread (Kthreadd, NULL, CLONE_FS | Clone_files);
Kthreadd_task = Find_task_by_pid_ns (PID, &init_pid_ns);
}
The Kthreadd daemon thread itself is also a kernel thread, which is essentially the same as other kernel threads, except that the kernel thread does the work of creating kernel threads. The invocation relationship of the function is as follows:
Start_kernel= "rest_init=" kernel_thread= "do_fork
When there is no kernel thread creation request, the Kthreadd daemon is asleep, and once the kernel thread creates the request, the Kthreadd daemon thread is awakened and the kernel thread is created.
The Kthreadd daemon thread creates a specific kernel thread primarily by passing in kernel thread creation parameters, so it is necessary to understand the kernel thread's creation parameters before telling the kernel thread's creation. The data structure associated with kernel thread creation is primarily a struct kthread_create_info, which represents the information needed to create a kernel thread. The structure definition is as follows:
Structkthread_create_info
{
/* Information passed to Kthread () Fromkthreadd. */
Int (*THREADFN) (void *data);/* callback function for kernel thread */
void *data;/* parameters of the callback function */
struct completion started;/*kthreadd waiting for newly created thread to start */

/* Result passed back to Kthread_create () from Kthreadd. */
struct Task_struct *result;/* returned after a successful creation task_struct*/
struct completion done;/* user waits for thread creation to complete */

The struct List_head list;/* is primarily used to place the Create parameter structure in a global linked list */
};
When a user needs to create a kernel thread, it populates the data structure, hangs the struct in the global Kthread_create_list list, and then wakes up the Kthreadd daemon to create the kernel thread, while the user thread blocks waiting for kernel thread creation to complete. Detailed user interface will be described below, here is not to repeat.
Based on the description of the front-facing kernel thread to create the struct, the Kthreadd daemon thread needs to do a simple job of traversing kthread_create_list, if there is a kernel thread that needs to be created in the list, call Create_ Kthread completes the creation of the kernel thread. Conversely, no kernel threads need to be created, then the Kthreadd daemon will sleep, waiting for the next kernel thread to create a request to wake up.
Static Voidcreate_kthread (struct Kthread_create_info *create)
{
int pid;
/* We want our own signal handler (Wetake no signals by default). */
PID =kernel_thread (Kthread, create, CLONE_FS | Clone_files | SIGCHLD);
if (PID < 0)
Create->result = Err_ptr (PID);
Else
Wait_for_completion (&create->started);/* Wait for the newly created thread to start */
Complete (&create->done);/* Notifies the user that the thread requested to create has completed */
}
Create_kthread primarily started calling Kernel_thread to create kernel threads, where the creation of kernel threads is consistent with the creation of Kthreadd kernel daemon threads, which is the same as the same. If the Kthreadd creation thread fails, the user is notified directly that the request creation action has been completed and that the creation is successful and needs to be judged by the user. Instead, the kernel thread is created successfully, and the Kthreadd daemon waits for the newly created thread to start before notifying the user that the action to create the kernel thread has been completed. After a kernel thread has been created, remove the next kernel thread from the Kthread_create_list list that needs to be created, specifying that all the requested kernel threads are created successfully and Ktheadd the thread sleeps.
2 Kthread_create and Kthread_run
Since linux2.6.30 uses the Kthreadd daemon thread to create kernel threads, users should not call Kernel_thread directly to create kernel threads when the kernel is programmed. (Here is just speculation, details to be researched) the Linux kernel provides users with two interfaces for creating kernel threads, one for kthread_create and the other for Kthread_run. The Kthread_run interface is actually the Kthread_create package. The difference is that after the kernel thread is created, Kthread_run calls the wake_up_process directly to wake up the kernel thread so that it can be dispatched immediately, while the kernel thread created through Kthread_create is sleep by default and will not be dispatched. Instead, it needs to be shown to wake the kernel thread to be dispatched. The code looks like this:
Structtask_struct * kthread_create (int (*THREADFN) (void *data),
void *data,
const Char namefmt[],
...)
{
struct Kthread_create_info create;
/* Populate the CREATE structure body */
CREATE.THREADFN = THREADFN;
Create.data = data;
Init_completion (&create.started);
Init_completion (&create.done);
/* Attach the Create struct to the global kthread_create_list list */
Spin_lock (&kthread_create_lock);
List_add_tail (&create.list,&kthread_create_list);
Spin_unlock (&kthread_create_lock);
/* Wake up the Kthradd daemon to create the kernel thread */
Wake_up_process (Kthreadd_task);
/* Wait for thread creation to end */
Wait_for_completion (&create.done);
The/*kthreadd thread does not guarantee that 100% is created successfully, it needs to be verified here.
if (!is_err (Create.result)) {
struct Sched_param param = {. sched_priority = 0};
Va_list args;
* Root may be changed our (Kthreadd's) priority or CPU mask.
* The kernel thread should not inherit theseproperties.
*/
/* Set the priority and CPU affinity of the thread */
Sched_setscheduler_nocheck (Create.result,sched_normal,? m);
Set_user_nice (Create.result,kthread_nice_level);
Set_cpus_allowed_ptr (Create.result,cpu_all_mask);
}
return create.result;
}
As we can tell from the previous article, to create a kernel thread, the first thing to do is to populate the KTHREAD_CREATE_INFO structure, pass the handler function of the thread and the related parameters to the Kthreadd daemon thread, in order to complete the work that the user needs the new thread to create. After the structure is populated, you also need to hang the struct into the global kthread_create_list list, then wake the Kthreadd thread to start creating the kernel thread, the user thread sleeps waiting for the new thread to create the action to complete, and after the new thread completes, set the thread's related properties, at this point, The thread will be able to complete the relevant work.
3 Kernel Thread handler function
Thread handlers for kernel threads are not user-defined interfaces, but are a unified interface implemented by the kernel. This unified interface is Kthread, and user-defined threading functions are callbacks through the unified interface. The Kthread interface has done a lot of work, first, the callback user-defined interface that we just said, so that the kernel thread can do what the user wants the thread to do. Second, is to notify the Kthreadd daemon thread, the newly created thread has started to start, the Khtreadd thread can create the next kernel thread, and the third is to implement the newly created thread to sleep before it is explicitly called, and, finally, to terminate the new kernel thread conveniently. Releases the associated resources. The code looks like this:
static int kthread (void *_create)
{
struct Kthread_create_info *create =_create;
Int (*THREADFN) (void *data);
void *data;
int ret =-EINTR;

/* Copy Data:it ' s on kthread ' s stack*/
THREADFN = create->threadfn;
data = create->data;

/* OK, tell user we ' re spawned, waitfor stop or wakeup */
__set_current_state (task_uninterruptible);
Create->result = current;
Complete (&create->started);
Schedule ();
/* thread is not terminated, the callback interface of the calling user completes the related work */
if (!kthread_should_stop ())
RET = THREADFN (data);

/* It might has exited on its own, w/okthread_stop. Check. */
/* If the user wishes to terminate the thread, the user is notified that the end is ready to be completed */
if (Kthread_should_stop ()) {
Kthread_stop_info.err = ret;
Complete (&kthread_stop_info.done);
}
return 0;
}
4 Terminating Kernel threads
The termination of the kernel thread is done through the Kthread_stop interface. Once the user invokes the Kthread_stop interface, it first wakes the kernel thread, sets the thread that needs to be terminated, and then sleeps, waiting for the wake of the thread handler function. As seen by the handler function of the previous kernel thread, the user-defined callback interface is not executed, and the user thread is woken up to complete the work of terminating the kernel thread. Kthread_stop used to Trace_point to complete the kernel thread cleanup work, Trace_point's work is unclear, just think it can do the cleanup we need.
5 binding the kernel thread to the specified CPU
The CPU that corresponds to the SMP architecture can be executed by binding the created kernel thread to a specified CPU via the Kthread_bind interface. By binding, you can reduce the migration of kernel threads between CPUs and increase the productivity of kernel threads. Binding CPU, the main principle is through the affinity of the CPU to achieve. This is also the Linux scheduler is inherently supported, here is only the use of the scheduler affinity function to implement the kernel thread binding function.
6 Summary
Kernel threads are often used in the Linux kernel, and understanding the creation of Linux kernel threads and the destruction process can help us understand how some of the features in the kernel that are done with kernel threads work. For example, Work_queue,work_queue is the creation of kernel threads to complete the relevant functions, if we know how the kernel thread works, in the use of work_queue, you can do the heart, you can know when work_queue at work, When to hibernate and so on. In short, learning the Linxu kernel from a trickle can help us just understand the mechanics and principles of some of the kernel's functions.

Creation and destruction of Linux kernel threads

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.