Analysis on the creation of Linux threads

Source: Internet
Author: User
Tags posix signal handler

This article first uses the interface pthread_create to create a thread and tracks the interface with the strace command Pthread_ The steps to create a thread and the system calls involved, and then discusses the Linux thread-to- process relationship, and finally outlines the implementation of the POSIX threads,Linux the changes made by the kernel.

Creating a thread using pthread_create

You can use pthread_create to create threads under Linux, which is declared as follows:

#include <pthread.h>int pthread_create (phtread_t *thread, const pthread_attr_t *attr,                                    void * (*start_routine ) (void *), void *arg);

As you can see, when we create a thread, we can specify the properties of the thread pthread_attr_t, such as the separation state property of the thread, the size of the line stacks, and so on (of course pthread_attr_init interface to manipulate this property structure), or you can pass parameters to the thread entry function when creating a thread Arg . Note When you create a new thread with a change interface, the newly created thread may run before the Pthread_create function returns. Here is a simple example:

#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <pthread.h>void* thread ( void* Arg) {    printf ("This is a pthread.\n");    Sleep (5);    return ((void *) 0); int main (int argc,char **argv) {    pthread_t id;     int ret;    printf ("pthread_start\n");    ret = Pthread_create (&id,null,thread,null);    printf ("pthread_end\n");    if (ret! = 0)    {           printf ("Create pthread error!\n");        Exit (1);    }       printf ("This is the main process.\n");    Pthread_join (id,null);    return 0;}

The compiler obtains the executable file:

$GCC-G-lpthread-wall-o hack_pthread_create hack_pthread_create.c

We can use the command strace to track the thread's creation process:

$strace  ./hack_pthread_create

The output of the relevant part of the interface pthread_create is as follows :

Mmap (NULL, 8392704, prot_read| Prot_write, map_private| map_anonymous| Map_stack,-1, 0) = 0x7f70b6c2f000brk (0)                                  = 0x1fe3000brk (0x2004000)                          = 0x2004000mprotect (0x7f70b6c2f000, 4096, Prot_none) = 0clone (child_stack=0x7f70b742eff0, flags=clone_vm| clone_fs| clone_files| clone_sighand| clone_thread| clone_sysvsem| clone_settls| clone_parent_settid| Clone_child_cleartid, parent_tidptr=0x7f70b742f9d0, tls=0x7f70b742f700, child_tidptr=0x7f70b742f9d0) = 64861

With the above output you can know that the steps for creating a thread Pthread_create interface are as follows:

1) Call mmap to allocate memory on the heap, size 8392704 bytes, or 8196KB, which is 8m+4k , the space is bigger than the stack . 4K , it 4k size is the We must uphold buffer size of the stack .

2) Call Mprotect () to set a memory page of the protected area ( size 4K), the page start address is 0x7f70b6c2f000 , This page is used to monitor stack overflow, and if there is a read and write operation on this piece, a SIGSEGV signal will be triggered .

3) Call Clone () to create the thread. In Linux , this interface is used to create processes, in essence,Linux threads are implemented using processes, with specific reference to the following. The first parameter of the call is the address of the bottom of the stack. The memory usage of the stack space starts with the high memory. Where the parameters flags The main markup meanings are described below:

Clone_vm mmap or munmap also affects other processes. It is worth mentioning that the fork clone to create a subprocess and it will not be set CLONE_VM mark.

Clone_fs indicates that the parent and child processes share file system information, including the file system root directory, the current working directory, and the umask. Chroot are called in parent or child processes ,andchdir and umask also affect other processes.

Clone_files indicates that the parent and child processes share the same file descriptor table. Opening a new file in a parent or child process, or closing a file, or Modifying the associated file flagwith Fcntl, can also affect other processes.

Clone_sighand indicates that the parent and child processes share the same signal handler table, that is, the parent process or child process modifies how the signal is handled by sigaction, and it also affects other processes. However, the parent and child processes have separate masks, so that a process can block or not block a signal through sigprocmask, and it will not affect other processes.

Clone_thread is used to indicate that a child process is in the same thread group as the parent process. Simply put, the child process that is created is the creation of a thread for user space.

Clone_sysvsem is used to indicate that the child process shares the same semaphore list as the parent process.

The "sub-process" is essentially the thread we create, and from these identities we can see that the resources are shared among the threads in the process.

Linux thread and process relationships

InLinuxin the system, the process is defined as the execution instance of the program, It doesn't do anything, just a variety of resources needed to maintain the application, while the thread is the real execution entity. In order for the process to do some work, a process must contain at least one thread. The process maintains the resources that the program contains(Static Resources), such as: virtual address space, open file descriptor collection, file system status, signal handlers, and so on, the resources that the thread maintains for the run-related(Dynamic Resources), such as: Run stack, scheduling-related control information, the signal set to be processed. InLinuxThere is no thread concept in the kernel, and each execution entity is atask_structstructure, usually called a process. A process is an execution unit, maintaining the dynamic resources associated with the implementation. It also refers to the static resources required by the program. Through system callsCloneWhen you create a child process, you can selectively let the child process share the resources referenced by the parent process. Such child processes are often referred to as lightweight processes.Linuxis based on a lightweight process, by the user-statepthreadthe library implementation.

When using pthread , it seems to the user that each task_struct corresponds to a thread , A set of threads and a set of resources that they collectively refer to is a process, but a set of threads does not just refer to the same set of resources, they must also be treated as a whole, the so-called thread group.

In summary, a process can have multiple threads, which are automatically dispatched by the kernel, and each thread has its own thread context, including thread ID, stack, stack pointer, program counters, general purpose registers, and condition codes. Other resources in the process are shared by all threads, including virtual address space (code, data, heap, shared library), file system Information, file descriptor list, and signal handlers.

Implementation of Linux threads

    functions called from interface pthread_create know that in Linux The thread is implemented through the process, LINUX&NBSP; kernel provides a clone () system call, clone parameters have clone_vm, clone_files, clone_sighand,clone_thread Span style= "font-family: Song Body" and so on. When creating a thread, the new process is created by clone () parameters ( LWP (lightweight process)) shared memory space with parent process, file Descriptor and signal handlers to achieve the same purpose of creating threads.

    in linux 2. Before 4, phtread line libraries corresponding implementation is a name linuxthreads lib But the library does not meet the posix Those requirements, it is implemented in user space, in signal processing, process scheduling ( "

    to linux2. After 4, phtread line libraries corresponding implementation is NPTL (native posix thread library) NPTL implementation satisfies posix requirements. NPTL is a 1x1 . The implementation of NPTL relies on the modification of the Linux. The kernel has the following related modifications:

    1) in kernel futex (Fast userspace mutex) support for handling between threads sleep wake futex kernel

    2) in linux 2.4 Span style= "font-family: Arial" > , the kernel has the concept of thread groups, all threads in the thread group share a pid pid is the so-called Thread group identity ( thread group identifier  (tgid) to the task_structtgid pid otherwise tgid pid ).

If you call getpidin a newly created thread, the value returned is the tgid, the PIDof the main thread (that is, theusual process PID), to obtain the thread itself in the kernel ID, that is , the PID in tast_struct, you can call Gettid obtained.

InClonein system calls, PassClone_threadparameter (that is, when you create a thread) you can put the new process'sTgid is set to the tgid of the parent process (Otherwise, the new processTgid will be set to its own PID). Similar toID intask_structThere are also two of them:Task->signal->pgidOf the beginning process of the Save Process group.Pidtask->signal->sessionSave the session to the beginning of the processPID, through the twoIDto associate process groups and sessions. With theTgid,kernel, or relatedShellprogram will know that atast_structrepresents a process or a thread, and you know when to show them., when should I not show?(such as inPSthe time, ThreadsIt usually doesn't show, but with the option- Lit will show)。

Executing a similar execve function in any thread in the process, except for the main thread, the other threads terminate, and the new program executes in the main thread.

Note the above discussion ID with the thread's pthread_t completely irrelevant, and in most of the system calls that use PID as a parameter or action on the process, this PID will be treated as tgid to the entire thread group (process).

3)To cope with"signals sent to the process"and the"signal sent to thread", Task_structit maintains two sets ofsignal_pending,one set is shared by the thread group., a set is thread-unique. ThroughKillsent signals are placed in the thread group sharedsignal_pendingin, can be handled by any one of the threads; byPthread_killthe signal sent(Pthread_killis apthreadinterface of the library, in the corresponding system callTkill)be placed on the thread exclusivesignal_pendingin, can only be handled by this thread。 When a thread stops/continue to, or when a deadly signal is received,, The kernel applies processing actions to the entire group of threads.

Referenceshttp://my.oschina.net/sincoder/blog/132303
http://blog.csdn.net/yetyongjin/article/details/7673837
Http://hi.baidu.com/_kouu/item/282b80a933ccc3a829ce9dd9
Http://hi.baidu.com/_kouu/item/358716f4c5f0cd0ec6dc45d0
Http://man7.org/linux/man-pages/man2/clone.2.html
Http://stackoverflow.com/questions/9154671/distinction-between-processes-and-threads-in-linux

Analysis on the creation of Linux 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.