The system creates a task_struct for each user process to describe the process. The struct contains a virtual address space ing table pointing to the process. In fact, the task_struct and address space ing tables are used together to represent a process.
Because the address space of a process is private, the system overhead is large during context switching between processes. to improve system performance, many operating system specifications introduce the concept of lightweight processes, thread
Threads created in the same process share the address space of the process. sask_struct is also used in Linux to describe a thread. Both threads and processes are involved in unified system scheduling. A thread is a task that shares the same address space.
Advantages of using threads:
This greatly improves the task switching efficiency and avoids extra TLB & cache refresh.
Multithreading is implemented through a third-party thread Library:
New POSIX thread Library (nptl)
It is an early improvement of Linux threads and adopts the thread model, which significantly improves the running efficiency and improves the signal processing efficiency.
Multiple Threads in a process share the following resources:
1. executable commands
2. Static Data
3. file descriptor opened in the process
4. Signal Processing functions
5. current working directory
6. User ID and user group ID
In addition, each process has private resources: thread ID, PC (program counter) and related registers, stacks, error numbers, signal masks and priorities, execution status and attributes.
The nptl thread Library provides several basic operations for creating, deleting, and controlling threads. Since multiple threads share a process resource, we need to consider the mutex during resource sharing and the synchronization between processes.
The synchronization and mutex mechanisms between threads are semaphores, mutex locks, or condition variables.
Create a process function:
Required header file: # include <pthread. h>
Function prototype: int pthread_create (pthread_t % thread, const pthread_attr_t * ATTR, void * (* routine) (void *), void * Arg)
Function parameter: thread created by thread
ATTR thread attribute. null indicates that the default attribute is used.
Functions executed by the routine thread
Parameters of the function passed to the thread for execution by ARG
Returned value: Success 0, failure-1;
Thread wait function:
Required header file: # include <pthread. h>
Function prototype: int pthread_join (pthread_t thread, void ** retval );
The first parameter is the identifier of the waiting thread;
The second parameter is a user-defined pointer that can be used to store the return values of the waiting thread.
This function is a thread-blocking function. The function called will wait until the end of the waiting thread. When the function returns, the resources of the waiting thread will be reclaimed.
If the execution is successful, 0 is returned. If the execution fails, an error number is returned.
In Linux, by default, after a thread is created, you must use this function to recycle resources of the created thread. However, you can set threads attributes to set when a thread ends,
Directly Reclaim the system resources occupied by this thread. For more information, see threads attributes.
In Linux, the new thread is not in the original process, but the system calls clone () through a system (). The system copies a process that is exactly the same as the original process,
And execute the thread function in this process. However, this copy process is different from that of fork.
The copied process shares all the variables and runtime environment with the original process. In this way, the variable changes in the original process can be reflected in the copy process.
Without pthread_join in the Code, the main thread will soon end and the entire process will end, so that the created thread will end without a chance to start execution. After pthread_join is added,
The main thread will wait until the waiting thread ends, giving the created thread the opportunity to execute.
All threads have a thread ID. Its type is pthread_t. Call the pthread_self () function to obtain its own thread number.
Thread exit function:
Function prototype: int pthread_exit (void * value_ptr );
Function parameter: value_ptr stores the value returned when the thread exits.
The thread terminates execution by calling the pthread_exit function, just as the process calls the exit function at the end.
Returned value: Success 0, failure-1;
Sending thread cancellation function:
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 this thread to the cancel signal. The State has two values: pthread_cancel_enable (default) and pthread_cancel_disable,
It indicates that after receiving the signal, it 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 status 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,
Valid only 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 shipping.
Void pthread_testcancel (void)
Check whether the thread is in the canceld status. If yes, cancel the operation. Otherwise, return directly.
Because multithreading is implemented based on a third-party thread library, you must load links to the library during compilation. For example:
# Gcc-O example. C-lpthread-d_reentrant
-Lpthread: links to the pthread library.
-D_reentrant: Generate reentrant code
Pthread_cond_wait ()
Pthread_cond_wait () is used to block the current thread and wait for other threads to wake up with pthread_cond_signal () or pthread_cond_broadcast. Pthread_cond_wait () must be used together with pthread_mutex. The pthread_cond_wait () function automatically releases mutex as soon as it enters the wait status. When other threads use pthread_cond_signal () or pthread_cond_broadcast to wake up the thread and make pthread_cond_wait () Pass (return), the thread automatically obtains the mutex.
The pthread_cond_signal function is used to send a signal to another thread in the blocked wait state, so that it is out of the blocking state and continues execution. if no thread is in the blocked wait state, pthread_cond_signal will also return success. When pthread_cond_signal is used, it generally does not generate a "Shocking group phenomenon". It only sends signals to one thread at most. If multiple threads are blocking and waiting for this condition variable, determine which thread receives the signal based on the priority of each waiting thread to continue execution. If the priority of each thread is the same, the thread obtains the signal based on the length of wait time. However, a maximum of one pthread_cond_signal call can be sent once. However, pthread_cond_signal may wake up multiple threads at the same time on a multi-processor. When you have only one thread to process a task, other awakened threads need to continue wait, in addition, the specification requires that pthread_cond_signal wake up at least one thread on pthread_cond_wait. In fact, some implementations also wake up multiple threads on a single processor. in addition, some applications, such as the thread pool, pthread_cond_broadcast, wake up all threads, but we usually only need some threads to execute the task, so other threads need to continue wait. therefore, we strongly recommend that you use the while loop for condition judgment on pthread_cond_wait. it can also be controlled by good control conditions.