Thread Creation
1.1 threads and processes
A thread is a concept closer to the execution body. It can share data with other threads in the same process, but has its own stack space and independent execution sequence. Threads and processes are introduced on the basis of a serial program to improve program concurrency and program running efficiency and response time.
The use of threads and processes has their own advantages and disadvantages: the thread execution overhead is small, but it is not conducive to resource management and protection. The process is the opposite. At the same time, threads are suitable for running on SMP machines, while processes can be migrated across machines.
1.2 create thread
POSIX creates a thread through the pthread_create () function. The API definition is as follows:
int pthread_create(pthread_t * thread, pthread_attr_t * attr, void * (*start_routine)(void *), void * arg) |
Unlike fork () calling to create a process, the thread created by pthread_create () does not have the same execution sequence as the main thread (that is, the thread that calls pthread_create, instead, run the start_routine (arg) function. The thread returns the ID of the created thread, while the attr is the thread attribute set when the thread is created (see below ). The return value of pthread_create () indicates whether the thread is successfully created. Although arg is a void * type variable, it can also be passed to the start_routine () function as any type of parameter. At the same time, start_routine () can return a void * type return value, the returned value can also be of another type and is obtained by pthread_join.
1.3 attributes created by threads
The attr parameter in pthread_create () is a structure pointer. The elements in the structure correspond to the running attributes of the new thread, including the following items:
_ Detachstate indicates whether the new thread is out of sync with other threads in the process. If it is set to a bit, the new thread cannot use pthread_join () for synchronization, and the occupied resources are automatically released upon exit. The default value is PTHREAD_CREATE_JOINABLE. This attribute can also be set with pthread_detach () after the thread is created and run, and once set to PTHREAD_CREATE_DETACH status (whether set at creation or runtime) then it cannot be restored to the PTHREAD_CREATE_JOINABLE state.
_ Schedpolicy indicates the scheduling policy of the new thread, which mainly includes SCHED_OTHER (normal, non-real-time), SCHED_RR (real-time, rotation method), and SCHED_FIFO (real-time, first-in-first-out, the default value is SCHED_OTHER. The last two scheduling policies are only valid for Super Users. You can use pthread_setschedparam () to change the value during running.
_ Schedparam is a struct sched_param structure. Currently, only one sched_priority integer variable represents the priority of the thread. This parameter is valid only when the scheduling policy is real-time (SCHED_RR or SCHED_FIFO) and can be changed through the pthread_setschedparam () function at runtime. The default value is 0.
_ Inheritsched. Two values are available: PTHREAD_EXPLICIT_SCHED and PTHREAD_INHERIT_SCHED. The former indicates that the new thread uses explicitly specified Scheduling Policies and scheduling parameters (values in attr ), the latter indicates inheriting the value of the caller thread. The default value is PTHREAD_EXPLICIT_SCHED.
_ Scope indicates the range of CPU competition among threads, that is, the valid range of thread priority. The POSIX standard defines two values: PTHREAD_SCOPE_SYSTEM and PTHREAD_SCOPE_PROCESS. The former indicates competition for CPU time with all threads in the system, and the latter indicates competition for CPU only with the threads in the same process. Currently, LinuxThreads only implements the PTHREAD_SCOPE_SYSTEM value.
There are some values in the pthread_attr_t structure, but pthread_create () is not used.
To set these attributes, POSIX defines a series of attribute setting functions, including pthread_attr_init (), pthread_attr_destroy (), and pthread_attr_get ---/pthread_attr_set --- functions related to each attribute.
1.4 Linux implementation created by threads
We know that the Linux thread implementation is performed outside the kernel, and the kernel provides the do_fork () interface for creating processes (). The kernel provides two system calls _ clone () and fork (), and finally calls the do_fork () core API with different parameters. Of course, to implement threads, there is no core support for multi-process (actually Lightweight Process) shared data segments. Therefore, do_fork () provides many parameters, including CLONE_VM (shared memory space), CLONE_FS (shared file system information), CLONE_FILES (shared file descriptor table), CLONE_SIGHAND (shared signal handle table), and CLONE_PID (shared process ID, only for processes in the kernel, that is, processes 0 ). When fork is used for system calling, the kernel calls do_fork () without any shared attributes. The process has an independent runtime environment and uses pthread_create () to create a thread, finally, all these attributes are set to call _ clone (), and all these parameters are passed to the do_fork () in the kernel, so that the created "process" has a shared runtime environment, only stacks are independent and passed in by _ clone.
A Linux thread exists as a lightweight process in the kernel and has an independent process entry. All creation, synchronization, and deletion operations are performed in the pthread Library outside the kernel. The pthread library uses a management thread (_ pthread_manager (), each process is independent and unique) to manage the creation and termination of threads and assign thread IDs to threads, sending thread-related Signals (such as Cancel), while the caller of the main thread (pthread_create () transmits the request information to the management thread through the pipeline.
Back to Top
Thread canceled
2.1 Definition of thread Cancellation
Generally, the thread automatically terminates when the main function exits, but it can also be forcibly terminated by receiving the termination (Cancellation) request from another thread.
2.2 semantics of thread Cancellation
The method for canceling a thread is to send a Cancel signal to the target thread, but how to handle the Cancel signal is determined by the target thread, or ignore, or terminate immediately, or continue running to Cancelation-point, which is determined by different Cancelation statuses.
The default processing of the CANCEL signal received by the thread (that is, the default status of the Creation thread of pthread_create () is to continue running to the cancellation point, that is, to set a CANCELED status and the thread continues running, it will exit only when it runs to Cancelation-point.
2.3 cancellation point
According to POSIX standards, pthread_join (), pthread_testcancel (), pthread_cond_wait (), pthread_cond_timedwait (), sem_wait (), sigwait (), and read (), write () system calls that cause blocking are all Cancelation-point, while other pthread functions do not cause Cancelation. However, the pthread_cancel manual page claims that, due to the poor combination of the LinuxThread Library and the C library, the current C library functions are not Cancelation-point; however, the CANCEL signal will cause the thread to exit from the blocked system call and set the EINTR error code. Therefore, you can call pthread_testcancel () before and after the system call to be used as the Cancelation-point (), to meet the requirements of the POSIX standard, that is, the following code segment:
pthread_testcancel(); retcode = read(fd, buffer, length); pthread_testcancel(); |
2.4 program design considerations
If the thread is in an infinite loop and the loop body does not execute the inevitable path to the cancellation point, the thread cannot terminate the cancellation request from other external threads. Therefore, you must add pthread_testcancel () to the required path of such a loop body.
2.5 pthread functions related to thread Cancellation
Int pthread_cancel (pthread_t thread)
Send the termination signal to the thread. If the signal is successful, 0 is returned. Otherwise, the value is not 0. Successful sending does not mean that the thread will terminate.
Int pthread_setcancelstate (int state, int * oldstate)
Sets the response of the thread to the Cancel signal. The state has two values: PTHREAD_CANCEL_ENABLE (default) and PTHREAD_CANCEL_DISABLE, indicating that the signal is set to the CANCLED status and the CANCEL signal is ignored to continue running; if the old_state is not NULL, it is saved to the original Cancel state for recovery.
Int pthread_setcanceltype (int type, int * oldtype)
Set the execution time of the canceling action of this thread. The type can be PTHREAD_CANCEL_DEFFERED or PTHREAD_CANCEL_ASYCHRONOUS, which is only valid when the Cancel status is Enable, it indicates that after receiving the signal, it continues to run until the next cancellation point and then exits and immediately executes the cancellation action (exit). If the oldtype is not NULL, it is saved to the canceled action type value of the shipment.
Void pthread_testcancel (void)
Check whether the thread is in the Canceld status. If yes, cancel the operation. Otherwise, return directly.