Yangshazhou
October 2001
This is a column for POSIX thread programming. The author will tell you the POSIX thread library API on the basis of clarifying the concept. This article is the first one will tell you about the creation and cancellation of the thread.
First, thread creation
1.1 Threads and processes are relatively relative to the process, thread is a more close to the concept of the actuet, which can share data with other threads in the process, but have its own stack space, with independent execution sequences. Based on the serial program, the process is introduced to improve the procedure of the program, thereby improving the program running efficiency and response time.
Threads and processes have advantages and disadvantages in use: thread execution overhead is small, but it is not conducive to the management and protection of resources; and the process is opposite. At the same time, the thread is suitable for running on the SMP machine, while the process can migrate across the robot.
1.2 Creating a thread POSIX Create a thread through a pthread_create () function, the API is defined as follows:
INT pthread_create (pthread_t * thread, pthread_attr_t * attr,
Void * (* st_routine) (void *), void * arg)
Unlike the method of creating a process, the thread created by pthread_create () does not have the same execution sequence with the main thread (ie, call pthread_create (), but to run the start_routine (arg) function. Thread returns the created thread ID, and Attr is the thread properties set when creating a thread (see below). The return value of pthread_create () indicates whether the thread creation is successful. Although Arg is a VOID * type variable, it can also be transmitted to the Start_Routine () function as any type of parameters; at the same time, start_routine () can return a VOID * type return value, and this return value can be other types, And is obtained by pthread_join ().
1.3 Thread Create Attribute Pthread_create () ATTR parameter in pthread_create is a structural pointer, and the elements in the structure correspond to the operating properties of the new thread, including the following:
__detachstate, indicating whether the new thread is detached from other threads in the process, and if set, the new thread cannot be synchronized with pthread_join (), and the resource occupied by itself when exiting. The default is the pthread_create_joinable state. This attribute can also be set by thread creation and running with pthread_detach (), and once set to pthread_create_detach status (whether it is created or runtime settings), it cannot be restored to the pthread_create_joinable state.
__schedpolicy, indicating the scheduling strategy of the new thread, mainly including SCHED_OTHER (normal, non-real time), SCHED_RR (real time, rotation) and SCHED_FIFO (real time, first in first out), default is SCHED_OTHER, the latter two scheduling strategies are only Super users are valid. It can be changed by PTHREAD_SETSCHEDPARAM () while running.
__schedparam, a struct sched_param structure, currently only one sched_priority integer variable indicates the running priority of the thread. This parameter is only valid only when the scheduling policy is real-time (ie, SCHED_RR or SCHED_FIFO), and can be changed by the pthread_setschedparam () function at runtime.
__inheritsched, there are two values to choose from: pthread_explicit_sched and pthread_inherit_sched, the former indicates that the new thread uses explicitly specifies the scheduling policy and scheduling parameters (ie, the value in the ATTR), and the latter represents the value of inheriting the caller thread. The default is pthread_explicit_sched. __scope, indicating the range of competition CPUs between threads, that is, the effective range of thread priority. Two values are defined in the standard: pthread_scope_system and pthread_scope_process, the former represents all the threads in the system compete with all the CPU time, indicating that only the thread competition in the same process. CPU Currently LinuXThreads implements only PTHREAD_SCOPE_SYSTEM.
There are also some values in the pthread_attr_t structure, but do not use pthread_create () to set.
To set these properties, POSIX defines a series of attribute setting functions, including pthread_attr_init (), pthread_attr_destroy (), and PTHREAD_ATTR_GET --- / pthread_attr_set --- function related to each property.
1.4 Linux implementation of threads We know that Linux's thread implementation is in addition to the vernocratic, the core is provided to create the interface DO_FORK (). The kernel provides two system calls __clone () and fork (), eventually call the DO_FORK () core API in different parameters. Of course, if you want to implement thread, there is no core to share data segments for multi-process (actually a lightweight process). Therefore, do_fork () provides a lot of parameters, including clone_vm (shared memory space), Clone_FS (shared) File system information), clone_files, clone_sighand (shared signal handle table), and clone_pid (shared process ID, only the nuclear process, namely the No. 0 process is valid). When using the Fork system call, the kernel call do_fork () does not use any shared properties, the process has a stand-alone operating environment, and use pthread_create () to create a thread, then all of these properties are finally set to call __clone (), and These parameters are all transmitted to DO_FORK () to the nucleus, and the "process" created "process" has a shared running environment, and only the stack is independent and is incorporated by __clone ().
The Linux thread is in the form of a lightweight process, with independent processes, and all operations are performed in the nuclear PTHREAD library. The PTHREAD library uses a management thread (__pthread_manager (), each process independently and unique) to manage the creation and termination of the thread, assign threads to thread ID, send thread-related signals (such as Cancel), while the main thread (pthread_create ()) The caller will pass the request information to the management thread through the pipeline.
Second, thread cancellation
2.1 Definition of thread cancellation In general, the thread will automatically terminate at its main function function, but it can also be forced to terminate because of the termination (cancel) request sent by another thread.
2.2 Semantic thread cancellation method is to send the CANCEL signal to the target line, but how to deal with the CANCEL signal, or ignore itself, or terminate it immediately, or continue to run to cancelation-point, Decide by different Cancelation status. The thread receives the default process of the CANCEL signal (ie pThread_create () creation thread default state) is to continue to run to the cancellation point, that is, set a Canceled status, thread continues to run, only when running to cancelation-point drop out.
2.3 Cancellation points according to POSIX standards, pthread_join (), pthread_testcancel (), pthread_cond_wait (), pthread_cond_timedwait (), SEM_WAIT (), Sigwait () and other functions and read (), write (), etc. can cause blocking system calls Is canceled-point, while other PTHREAD functions will cause the cancelation action. However, PTHREAD_CANCEL's man page claims that since the LinuxThread library is not well combined with the C library, the current C library function is not canceled-point; but the CANCEL signal will exit from the blocking system call, and set the EINTR error code, so You can call pthread_testcancel () before and after calling as a Cancelation-Point, thereby reaching the goal required by the POSIX standard, namely the following code segment:
pthread_testcancel ();
Retcode = Read (FD, Buffer, Length);
pthread_testcancel ();
2.4 Program Design Consideration If the thread is in an infinite loop, and the inevitable path of the cancellation point is not executed, the thread cannot be terminated by the cancel request of the external other threads. Therefore, PTHREAD_TESTCANCEL () call should be added to the path of such cycles.
2.5 Cancellation related PTHREAD function int pthread_cancel (pthread_t thread) sends a termination signal to the Thread thread, returns 0 if success, otherwise it is a non-zero value. The success of sending does not mean that Thread will terminate.
INT PTHREAD_SETCANCELSTATATE (int State, int * OldState) Sets this thread to the CANCEL signal, State has two values: pthread_cancel_enable (default) and pthread_cancel_disable, indicating that the received signal is set to CANCLED status and ignore the CANCEL signal to continue operation; Old_State If not null, the original CANCEL status is stored in order to recover.
INT PTHREAD_SETCANCELTYPE (INT TYPE, INT * OLDTYPE) Sets the execution timing of this thread cancel action, Type is valid by two values: pthread_cancel_deffered and pthread_cancel_asychronous, only when the CANCEL state is enable, respectively, indicating that the signal is not running to the next The cancellation point is re-exited and immediately performs the cancel action (exit); OldType If not NULL is stored in the unspecite type value.
Void pthread_testcancel (void) Check if this thread is in the Canceld status, if yes, the cancel action is canceled, otherwise it will return directly.