This article describes the basic use of threads on Linux.
1. Preface
Difference between threads and processes (1) Process: It is the smallest unit of OS scheduling. ps, top, etc. commands can be used to view the details of processes under Linux. (2) Thread: It is the smallest unit of process scheduling, each process has a main thread. The main thing to do in the process is the thread.
(3) In the whole system, the process ID is the unique identifier, and the management of processes is done by PID. When a process is created, a structure is created in the kernel to store all the information about the process, and each node that stores the process information also stores its own PID, which is used to manage the process when it is needed (e.g., sending signals). When a child process ends and needs to be recycled (when it calls exit() to exit or when code execution is finished), it needs to be done with the wait() system call, and the unrecovered extinct process becomes a zombie process that no longer exists as a process entity, but takes up PID resources, so recycling is necessary.
For threads, to actively terminate you need to call pthread_exit() and the main thread needs to call pthread_join() to recycle (provided the thread does not have the “detach property” set). Signaling a thread like a thread sends a thread signal is also implemented via the thread ID.
Communication methods between processes: A. Shared memory B. Message queues C. Semaphore D. Named pipes E. Nameless pipes F. Signals G. Files H. Sockets Communication methods between threads: A. Mutual exclusion B. Spin locks C. Conditional variables D. Read/write locks E. Thread signals F. Global variables
The communication method used between processes either requires switching the kernel context or accessing with peripherals (famous pipes, files). So it will be slower. If threads use their own specific communication method, it is basically done in their own process space, there is no switching, so the communication speed will be faster. In other words, there is a difference in speed between the communication methods used by processes and threads, in addition to the difference in type.
Note: When a process running multiple threads catches a signal, it will only block the main thread, while other sub-threads will not be affected and will continue to execute.
2. Introduction to thread-related functions
2.1 Creating threads
pthread_create is a function for creating threads for Unix operating systems (Unix, Linux, etc.). Compile time requires specifying the link library: -lpthread function prototype.
Parameter introduction
The first parameter is a pointer to the thread identifier. The second parameter is used to set the thread property. The third parameter is the starting address of the thread running function. The last parameter is the argument of the run function. The last argument is the argument to run the function. NULL is not required. see function help under Linux: # man pthread_create
Return Value: Returns 0 if the thread creation was successful, or the error number if the thread creation failed. After a successful thread creation, the attr parameter is used to specify various different thread properties. The newly created thread starts at the address of the start_rtn function, which has only one universal pointer argument arg. If more than one argument needs to be passed to the thread work function, then these arguments need to be put into a structure, and the address of this structure is passed in as an argument to arg.
Example:
|
|
2.2 Exiting a thread
A thread terminates execution by calling the pthread_exit function in the same way that a process calls the exit function at the end. This function terminates the thread that called it and returns a pointer to an object.
This function terminates the thread that called it and returns a pointer to an object, the return value of which can be obtained from the second argument of the pthread_join function.
Prototype function
Parameter resolution The address of the thread to return to. Note: The thread stack must be freed at the end of the thread, that is, the thread function must call pthread_exit() to end it, otherwise it is not freed until the main process function exits.
2.3 Waiting for a thread to finish
The pthread_join() function waits in a blocking fashion for the thread specified by thread to finish. When the function returns, the resources of the thread being waited for are retrieved. If the thread has already finished, then the function returns immediately. The thread specified by thread must have the joinable property. Prototype function.
Parameters First parameter: thread identifier, i.e. thread ID, which identifies a unique thread. Last parameter: user-defined pointer to store the address of the thread being waited for. Return value 0 means success. For failure, an error number is returned. Example of receiving a thread return value:
2.4 Thread separation property
The default state for creating a thread is joinable (join property). If a thread finishes running without calling pthread_join, its state is similar to that of a Zombie Process in a process, i.e. there are still some resources that have not been recovered (exit status code), so the person creating the thread should pthread_join to wait for the thread to finish running and get the exit code of the thread to recover its resources (similar to wait,waitpid of a process). But after calling the pthread_join(pthread_id) function, if the thread does not finish running, the caller will be blocked, which in some cases we don’t want.
The pthread_detach function sets the state of the thread to detached, which automatically releases all resources when the thread finishes running. Prototype function
Parameters Thread identifier Return value 0 means success. Error returns an error code. EINVAL thread is not a joinable thread. esrch has no thread ID to be found.
2.5 Getting the identifier of the current thread
The pthread_self function gets the ID of the thread itself. Prototype function
return value The identifier of the current thread. pthread_t is of type unsigned long int, so use the %lu method when printing, otherwise there will be problems displaying the results.
2.6 Automatic thread resource cleanup
A thread can schedule functions to be called when it exits. Such functions are called thread cleanup handlers. This is used to do some post-exit resource cleanup when the program exits abnormally. A pthread_cleanup_push()/pthread_cleanup_pop()
function is provided in the POSIX thread API to automatically release resources. Termination actions (including calls to pthread_exit()
and exception termination) in the segment between the point of call of pthread_cleanup_push()
and pthread_cleanup_pop()
will execute the cleanup function specified by pthread_cleanup_push()
.
Note: The pthread_cleanup_push
function needs to be called in pairs with the pthread_cleanup_pop
function. function prototype
parameters void (*routine)(void *)
: The function entry for the handler. void *arg
: The formal parameter passed to the handler. int execute : The status value of execute. 0 indicates that the cleanup function is not called. 1 indicates that the cleanup function is called.
Conditions that cause the cleanup function to be called:
- pthread_exit() function is called
- pthread_cleanup_pop has a formal reference of 1. Note: return does not result in a cleanup function call.
2.7 Auto-cleanup thread sample code
|
|
2.8 Thread cancellation functions
The pthread_cancel function is a thread cancellation function, which is used to cancel other threads in the same process.