UNIX threading Concepts, control primitives, properties

Source: Internet
Author: User
Tags terminates

Threads: Thread-based concepts:

Threads are also called lightweight processes in Linux. And it and the process have PCB (Process control block), but the difference is that the virtual address space of the process is exclusive, that is, each process has its own virtual address space, but the thread of the PCB is shared, in the same virtual address space, each thread has its own PCB. Although each thread has its own PCB, from the kernel point of view, the process and the thread are the same, because the same virtual address space inside each thread of the PCB points to the memory resources of the three-level page table is the same. Under Linux, threads can be viewed as the smallest unit of execution (the process uses multithreading to accomplish tasks), and the process is the smallest allocation of resource units (the system is created as a process, without creating a thread to perform the argument). in fact, whether it's creating a fork in a process or creating a thread's pthread_create, the underlying implementation is invoking the same kernel function clone. If you copy the address space of the other party, it will produce a "process", and if the address space of the other party is shared, a "thread" is generated. A process can be seen as a process with only one thread.
Because the Linux kernel does not differentiate between processes and threads, it is differentiated only at the user level, so all functions related to thread manipulation are library functions, not system calls.

Thread-sharing resources:

1. Shared file descriptor List (PCB is the same physical address pointed to, and file descriptor is present in the PCB, of course the same)
2. How the shared signal is processed (same way)
3. Share the current working directory (same as)
4. Shared process ID and group ID (thread is still in process, so the process ID and group ID are the same)
5. Share a portion of memory address space (. text/.data/.bss/heap/shared Library) (facilitates data sharing and synchronization)

Thread non-shared resource:

1. Thread ID (in the same process, in order to identify different threads)
2. The value of the register (because the thread is running concurrently, each thread has its own different running situation, when switching between threads, it is necessary to save the value of the Register collection of the original thread to facilitate re-switching back to restore)
3. Stack space (the independence of the stack space ensures that the thread runs independently and is unaffected by other threads)
4.errno variable (also guarantees the independent operation of the thread, not affected by other threads)
5. Signal shielding word (same as)
6. Scheduling priority (threads need to be dispatched like a process, so there are parameters that need to be dispatched, that is, priority)

Threading Pros and Cons:

Advantages:
1. Improved concurrency of the program
2. The overhead is smaller than the process (do not create your own unique virtual space each time as a process)
3. Data communication and sharing convenience (because threads share a portion of memory address space)
Disadvantages:
1. Library functions are less stable than system calls
2.GDB does not support debugging (GDB is generated much earlier than thread join)
3. Poor support for signals (same signal birth and thread not at the same time)

Control primitives: View Thread ID:

Function Prototypes: pthread_t pthread_self(void)
Return value: Returns the thread ID without a failure (because, even if the thread is not created, the process can be considered a process with only one main thread), the pthread_t type is an unsigned integer under the Linux system and may be a struct in other systems. And the thread ID is a recognition flag inside the process, so the thread ID of the different processes allows the same.

To create a thread:

Function Prototypes: int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);
Return value: Successful return 0. Failed return error number
Parameters: Thread: Outgoing parameter, save the system for our allocated thread id;attr: Usually null, indicating the use of thread default properties. ; Start_routine: The function pointer, which points to the main function of the thread, which ends after the function is run, and that the thread is terminated when the thread main function executes.
Note: When the Pthread_create function is called, the current thread continues to execute downward, and the newly created thread executes the Start_routine function we passed in, and the newly created thread ends after the function executes.

When we compile with GCC about threading, we need to add additional -pthread parameters.
Example:

#include <stdio.h>#include <pthread.h>#include <unistd.h>#include <stdlib.h>#include <string.h>void *print_id(void *arg)       //线程所执行的函数{    printf("%dth pthread id:%lu\n", (int )arg, pthread_self());}int main(){    int ret;    pthread_t tid;    int i = 0;    for(; i < 5; i++)   //循环创建5个线程    {        ret = pthread_create(&tid, NULL, print_id, (void *)i);          if(ret != 0)        {            printf("%s\n", strerror(ret));  //由于线程创建失败返回的错误码不保存在errno中,所以用strerror函数将其转成错误信息进行输出        }    }    printf("%dth pthread id:%lu\n", i, pthread_self());    sleep(5);       //这里是为了防止各线程还没执行完,进程就先退出了    return 0;}

Remember to share global variables between threads

#include <stdio.h>#include <pthread.h>#include <unistd.h>#include <string.h>int var = 100;void *glb_share(void *arg)      //改变全局变量var的值{    var = 200;}int main(){    pthread_t tid;    int ret;    if((ret = pthread_create(&tid, NULL, glb_share, NULL)) != 0)    {        printf("%s\n", strerror(ret));    }    sleep(1);    printf("var : %d \n", var);     //输出var的值,输出结果为200。已经改变。    sleep(1);    return 0;}

Thread exit:
Function Prototypes: void pthread_exit(void *retval)
Parameter: retval: Indicates the thread exit state, usually passed null
Note: The function is to exit() exit the current process, and the pthread_exit() function exits the current thread. That is, if a function is called in the thread, exit() then the process exits and the program ends.
Here we use the code of the previous loop to create the thread to perform a test to enhance the understanding of the relationship between threads and processes:

#include <stdio.h>#include <pthread.h>#include <unistd.h>#include <stdlib.h>#include <string.h>void *print_id(void *arg){    sleep(2);       //相比于之前,这里多加了睡眠2s    printf("%dth pthread id:%lu\n", (int )arg, pthread_self());}int main(){    int ret;    pthread_t tid;    int i = 0;      for(; i < 5; i++)    {        ret = pthread_create(&tid, NULL, print_id, (void *)i);        if(ret != 0)        {            printf("%s\n", strerror(ret));        }        if(i == 2)      //创建了3个线程之后,主线程就退出            pthread_exit(NULL);     }    printf("%dth pthread id:%lu\n", i, pthread_self());    sleep(5);    return 0;}

The result of the run is to output the ID of the first 3 threads created, and in the 2 seconds of the thread sleep, the main thread has exited, but the remaining threads can continue to execute, which illustrates the independence between threads, and the code behind the main function will not run. So it confirms what you said before that you can think of a process as a process that has a main thread. If you pthread_exit(NULL) replace the function exit(1) , you can see that the program ends immediately, indicating that the exit function exits the process and pthread_exit exits a single thread.

Blocking wait thread exits:
Function Prototypes: int pthread_join(pthread_t thread, void **retval)
Return value: Successful return 0, failure return error number
Parameters: Thread: The id;retval of the threads to be exited: The end state of the storage thread, and if it is called by another thread pthread_cancel the exception terminates, the value retval holds is a constant pthread_canceled.

Thread Separation:
Function Prototypes: int pthread_detach(pthread_t thread)
Return value: Successful return 0, failure return error number
Parameter: Thread: The ID of the threads to detach
Thread Detach state: Thread is actively disconnected from the main path. After the thread ends, its exit state is not fetched by other threads, and is automatically freed by itself. In general, after a thread terminates, its terminating state remains until the other thread calls Pthread_join, but after it is set to detach, the thread immediately reclaims all of the resources it occupies, without leaving the terminating state. Therefore, you cannot call Pthread_join on a thread that has a detached state set.
Example:

#include <stdio.h>#include <pthread.h>#include <unistd.h>#include <stdlib.h>#include <string.h>void *detach_pthread(void *arg){    int exit_code = 233;    pthread_exit((void *)exit_code);}int main(){    pthread_t tid;    int ret;    void *retval;    pthread_create(&tid, NULL, detach_pthread, NULL);    pthread_detach(tid);        //设置分离态    ret = pthread_join(tid, &retval);  //阻塞回收线程,并接收返回状态    if(ret != 0)    //pthread_join调用失败之后输出原因    {        printf("pthread_join error:%s\n", strerror(ret));    }    else        //否则输出退出状态    {        printf("exit code : %d\n", retval);    }    return 0;}

The result of this code run is: Pthread_join error:invalid argument (invalid argument)
This shows that the thread that set the split state is out of the range of the Pthread_join collection.
Alternatively, thread separation can be achieved by setting the properties of the thread.

Kill Thread:
Function Prototypes: int pthread_cancel(pthread_t thread)
Return value: Successfully returned 0, failed to return error code
Parameter: Thread: The number of threads to kill
Note: This function does not kill kill the specified function as it is called, but it is to reach a cancellation point (check whether the thread is canceled), usually some system calls have a cancellation point, such as read write close, etc. but we can call the Pthread_testcancel () function to act as a cancellation point, and the return value of the canceled thread is pthread_canceled (-1).

Example:

#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <pthread.h>void *test_cancel(void *arg){    int val = 3;    while(1)    {        pthread_testcancel();    }    pthread_exit((void *)val);}int main(){    pthread_t tid;    void *ret = NULL;    pthread_create(&tid, NULL, test_cancel, NULL);    pthread_cancel(tid);        //杀死创建的进程    pthread_join(tid, &ret);    //阻塞等待线程退出,并获取退出状态    printf("thread exit code = %d\n", (int)ret);    return 0;}

The result of this code output is thread exit code =-1, indicating that the thread was successfully killed, otherwise it would return 3.

Check that two thread IDs are the same:
Function Prototypes: int pthread_equal(pthread_t t1, pthread_t t2);
Return value: If the thread ID is the same, returns a value other than 0, otherwise 0 is returned. There is no failure condition.

Thread Properties:

The default properties can resolve most cases, but if you have higher performance requirements, you can reduce the use of memory by modifying the thread properties to reduce the size of the line stacks.
To set the structure of a thread property:

typedef struct{    int detachstate; //线程分离状态    int schedpolicy;  //线程调度策略    struct sched_param schedparam;  //线程的调度参数    int inheritsched;   //线程的继承性    int scope;  //线程的作用域    size_t guardsize;   //线程栈末尾的警戒缓冲区大小    int stackaddr_set;  //线程的栈设置    void* stackaddr;    //线程栈的位置    size_t stacksize;   //线程栈的大小}pthread_attr_t;

Members of the main structural bodies:
1. Thread Separation Status
2. Thread stack size (default average allocation)
3. Thread stack guard buffer size (at the end of the stack)

Property values cannot be set directly and need to be manipulated with corresponding functions.

Some related functions:

Thread Property Initialization:
Function Prototypes:int pthread_attr_init(pthread_attr_t *attr)
Return value: Successful return 0, failure return error number
Parameter: attr: Setting the structure of a property
Note: You need to initialize the property first, then set the related property, and then create the thread.
Destroy Thread Properties:
Function Prototypes:int pthread_attr_destroy(pthread_attr_t *attr)
Return value: Successful return 0, failure return error number
Parameters: Thread properties to destroy
Get thread Detach state:
Function Prototypes:int pthread_attr_getdetachstate(pthread_attr_t *attr, int *detachstate)
Return value: Successfully returned 0, failed to return error code
Parameters: attr: Set the structure of the property; Detachstate: Incoming parameter, get state, pthread_create_detached (detached state) pthread_create_joinable (non-detached state).
To set the thread detach state:
Function Prototypes:int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
Return value: Successful return 0. Failure return error code
Parameters: attr: Sets the structure of the property, Detachstate: Outgoing parameter, set state, pthread_create_detached (detached state) pthread_create_joinable (non-detached state).
Gets the stack size of the thread:
Function Prototypes:int pthread_attr_getstacksize(pthread_attr_t *attr, size_t *stacksize);
Return value: Successfully returned 0, failed to return error code
Parameter: attr: Sets the structure of the property; StackSize: The default stack size
Set the stack size of the thread:
Function Prototypes:int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize);
Return value: Successfully returned 0, failed to return error code
Parameter: attr: Sets the structure of the property; StackSize: The size of the stack that is passed in the parameter, set

Gets the first address and size of the thread's stack:
Function Prototypes: int pthread_attr_getstack(pthread_attr_t *attr, void **stackaddr, size_t *stacksize);
Return value: Successfully returned 0, failed to return error code
Parameters: attr: Sets the structure of the property; STACKADDR: Outgoing parameter, first address of Stack, stacksize: outgoing parameter, stack size
Set the first address and size of the thread's stack:
Function Prototypes: int pthread_attr_setstack(pthread_attr_t *attr, void *stackaddr, size_t stacksize);
Return value: Successfully returned 0, failed to return error code
Parameters: attr: Sets the structure of the property; STACKADDR: Incoming parameter, the new stack's first address; StackSize: The size of the stack passed in the parameter, set
When the remaining stack space is not enough, we can use the malloc function or mmap allocated space as the new stack space.

Example:

#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <pthread.h> #define SIZE 0x100000void *th_fun (void *arg) {while (1) sleep (1);}    int main (void) {pthread_t tid;    int err, detachstate, i = 1;    pthread_attr_t attr;    size_t stacksize;    void *stackaddr;                                   Pthread_attr_init (&AMP;ATTR);       Initialize thread properties Pthread_attr_getstack (&attr, &stackaddr, &stacksize);           Get information about the stack pthread_attr_getdetachstate (&attr, &detachstate);    Gets the discrete state information if (detachstate = = pthread_create_detached)//If it is a detached printf ("Thread detached\n");    else if (detachstate = = pthread_create_joinable)//If it is not detached printf ("Thread join\n");    else printf ("Thread unknown\n");    Pthread_attr_setdetachstate (&attr, pthread_create_detached);       Sets the thread to the detached state while (1) {stackaddr = malloc (SIZE);          Request Memory if (stackaddr = = NULL) {perror ("malloc");  Exit (1);        } stacksize = SIZE; Pthread_attr_setstack (&attr, stackaddr, stacksize);        Set stack Size err = pthread_create (&tid, &attr, Th_fun, NULL);            if (err! = 0) {printf ("%s\n", strerror (err));        Exit (1);    } printf ("%d\n", i++);    } Pthread_attr_destroy (&attr); return 0;}

Thread Usage Considerations:
1.malloc and Mmap requested memory can be freed by other threads (because of heap space sharing)
2. Avoid zombie threads and waste resources
3. If you call fork in multiple threads and do not immediately exec, all other threads will be pthread_exit except for the thread that calls fork.

UNIX threading Concepts, control primitives, properties

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.