Linux multi-threaded programming of pthread (reprint)

Reprinted Source: https://blog.csdn.net/skyroben/article/details/72793409

1. Background

Linux does not thread in the true sense, its implementation is to simulate the process, it belongs to the user-level threads, located libpthread shared library (so the thread ID is valid only in the library), follows the POSIX standard.

There is a genuine Windows, TCB data structure to describe the thread.

Linux on the two most famous LinuxThreads threading library and NPTL.

 

Two Linux threading model of comparison:

Comparison of Linux threading model

 

Linux multi-threaded virtual address space mapping is similar to creating multiple sub-processes with vfork.

2. The difference between processes and threads

    Process: a dynamic program running instance, assume an example allocation of system resources. (The main purpose of the Linux implementation process is resource-exclusive)

    Thread: a branch runs in internal processes (process's address space) run, is the basic unit of scheduling (schedule by scheduling LWP). (The main purpose of Linux implementation of thread is a shared resource)

    Thread all the resources provided by the process.

    Single process: only one process thread (LWP = PID).

    LWP: lightweight processes.

 

    Because multiple threads of the same process share the same address space, so the Text Segment, Data Segment are shared, if you define a function, in each thread can call, if you define a global variable, you can access to each thread in addition, each thread has shared the following process resources and the environment: 

1. file descriptor table
Treatment (SIG_IGN, SIG_DFL or custom signal processing function) 2. each signal  
3. The current working directory
4. The user id and group id
 However, some resources each thread of each one:
 1. thread ID
2. The context information comprising values ​​of various registers, program counter and stack pointer
3. stack space
4. errno variable
The mask character signal
6. scheduling priority

The advantages of multi-threaded programs (relative to the process of comparison):

1. The plurality of threads, using the same address space among each other, sharing most of the data, it takes a thread start space is much smaller than the operating space it takes a process, and the time required for switching between the threads from each other the time required to switch between far less than the process, create destroy fast.
2. The mechanism is to facilitate communication between threads. Because the shared data space between threads in the same process, so the data a thread can be directly used for the other threads, it is not only fast, but also convenient.

3. Process Control

In the Linux system, thread related functions are defined in the header file pthread.h.

Create a thread function --pthread_create function

#include <pthread.h>
int pthread_create(pthread_t * thread, const pthread_arrt_t* attr,void*(*start_routine)(void *), void* arg)
(1) thread argument is the new thread identifier, as an integer.
(2) attr parameter setting properties of the new thread. To pass NULL expressed as the default thread attributes.
(3) start_routine and arg parameter specifies the functions and parameters are new thread will run. When start_routine return, withdrew from this thread
(4) Return value: returns 0 on success, failure to return the error number.
 
    Type thread id is thread_t, only to ensure that the current process is unique, thread_t this type have different implementations on different systems, call pthread_self () id can get the current thread
    When the type pid_t process id, the id of each process is unique in the entire system, calling getpid () id can get the current process, it is a positive integer value.

Terminate the thread --pthread_cancel function and function pthread_exit

Terminate a thread without terminating the whole process, there are three ways:
1. return from the thread function. This method is not suited for the main thread, the main function return equivalent to calling exit.
2. A thread can call pthread_cancel terminate another thread in the same process.
3. The thread can call pthread_exit terminate itself.
 
#include <pthread.h>
 
int pthread_cancel(pthread_t thread);
(1) thread parameter is the target thread identifier.
(2) This function returns 0 on success, failure error code is returned.
 
#include <pthread.h>
 
void pthread_exit(void * retval);
(1) retval is void * type, other threads can call pthread_join get this pointer. It is noted that the memory cell or return pthread_exit returned pointer points must be global or allocated by malloc can not be allocated on the stack of the thread function, because when other threads get the function returns a pointer to the thread has been pulled out.
(2) pthread_exit which function to pass through the exit information retval thread parameters to recyclers. After executing it will not return to the caller, and never fail.

Thread waits --pthread_join

#include <pthread.h>
 
void pthread_join(pthread_t thread,void ** retval);
(1) the function is called thread hangs wait until terminated as thread id thread.
(2) thread terminates the thread in a different manner, by terminating the state pthread_join obtained are different,
 
Summarized as follows:
1. If the thread through the thread return to return, in unit value_ptr pointed thread is stored in the return value of the function thread.
2. If the thread thread thread exception is invoked pthread_cancel other end off unit value_ptr pointed in the store is constant PTHREAD_CANCELED.
3. If the thread is a thread calls himself pthread_exit terminated, value_ptr pointed unit is stored in the parameters passed to pthread_exit. If you are not interested in the state of thread to terminate the thread, you can pass NULL to value_ptr parameters.

(3) returns 0 on success, failure to return an error code. Error code may occur:

4. Separation thread

 1. at any one point in time, the thread is bound (the Joinable) or separated (detached).
 2. a combination of thread can be retracted its resources and kill other threads. Before being recovered by other threads, its memory resources
(eg stack) is not released. (Created by default under the thread of cases are combinable) 
 3. A separate thread can not be recycled or kill another thread, which automatically releases the memory resources by the system when it terminates.
 4. If a binding thread end of the run but not join, cause some resources are not recyclable, so creating a thread should call pthread_join to wait for the end of the thread to run and get the thread exit code, recover its resources. 
      
调用pthread_join后,如果该线程没有运行结束,调用者会被阻塞。如何解决这种情况呢?      
    例如,在Web服务器中当主线程为每个新来的连接请求创建一个子线程进行处理的时候,主线程并不希望因为调用pthread_join而阻塞(因为还要继续处理之后到来的连接请求),这时可以在子线程中加入代码 pthread_detach(pthread_self())或者父线程调用pthread_detach(thread_id)(非阻塞,可立即返回)这将该子线程的状态设置为分离的(detached),如此一来,该线程运行结束后会自动释放所有资源。
 
验证代码:
#include <stdio.h>
#include <error.h>
#include <stdlib.h>
#include <pthread.h>

void* thread_run(void* _val)
{
    pthread_detach(pthread_self()); //注释这句代码join success
    printf("%s\n", (char*)_val);
    return NULL;
}

int main(){
    pthread_t tid;
    int tret = pthread_create(&tid, NULL, thread_run, "thread_run~~~~~");
    //线程创建成功之后,程序的执行流变成两个,一个执行函数thread_run,一个继续向下执行。
    if (tret == 0){
        sleep(1);
        int ret = pthread_join(tid, NULL);
        if (ret == 0){
            printf("pthread_join success\n");
            return ret;
        }else{
            printf("pthread_join failed info: %s\n", strerror(ret));
            return ret;
        }
    }else{
        printf("create pthread failed info: %s", strerror(tret));
        return tret;
    }
}                        
运行结果:
分析:
可以看到被分离的线程不可以被等待;一个线程初始为可结合的,要么在父线程等待或分离,要么在子线程分离,只能采取上述几种措施的一种。

Guess you like

Origin www.cnblogs.com/leokale-zz/p/11135089.html