User-level threads and kernel-level threads, can you tell the difference?

This article is a supplement to the previous blog, which aims to complete the "user-level threads and kernel-level threads" that were not clearly explained. I hope readers can have a better understanding of threads.


Xiaobai is learning multi-threaded programming recently.

There is a lot of information about multithreading on the Internet. Xiaobai quickly understood the basic concepts of threads, but she couldn't understand the concepts of "user-level threads and kernel-level threads", so she had to solidify the foundation of the operating system. Xiao Ming asked for advice.

For Xiaobai's question, Xiaoming will always answer patiently: "These two concepts in threads are indeed difficult to understand. Let me tell you about user-level threads first."

User level thread

"Since you said you've seen the basic concepts of threads, I'll just skip this part.

A long, long time ago, the concept of threads appeared, but operating system manufacturers cannot directly modify the kernel of the operating system, because for them, stability is the most important thing. What should I do if I rashly add unverified things to the kernel? So if you want to verify the availability of threads, you have to find another way. "

"I know, I know, those researchers wrote a function library about threads, and used the function library to implement threads !" Xiaobai said proudly: "I just saw this on the Internet."

"Yes, they put functions such as creating threads and terminating threads in this thread library , and users can call these functions to achieve the required functions." Xiao Ming found a piece of paper and wrote a few functions: pthread_creat, pthread_exit, pthread_join, , pthread_yieldand then said: "These are several important functions. You should be able to guess the functions of these functions, right?"

"Emmmm, let me think about it, pthread_creatit's creating a new thread, pthread_exitit's ending a thread, well pthread_join, I guess it's preparing to run a thread and adding it to the ready queue . I don't know the last function."

"It doesn't matter if you don't know, you will understand in a while." Xiao Ming continued: "You must know that the thread library we just mentioned is located in user space, and the operating system kernel knows nothing about this library , so from the kernel's From an angle, it's still managed in the normal way."

Xiaobai asked: "That is to say, the operating system still only sees processes ? Then a multi-threaded process I wrote with the thread library can only run on one CPU core at a time?"

Xiao Ming nodded and said: "You're right, this is actually a disadvantage of user-level threads. These threads can only occupy one core, so parallel acceleration cannot be achieved, and due to the transparency of user threads , the operating system cannot Actively switch threads , in other words, if A and B are two threads of the same process, when A is running, if thread B wants to run, it can only wait for A to actively give up the CPU, that is, actively call the pthread_yieldfunction ."

tobe Note: User-level threads are invisible to the operating system , also known as transparency .

"Stop, let me think about it," Xiaobai quickly thought about Xiao Ming's words, "Does it mean that even if there is a thread library, user-level threads can't do round- robin scheduling like processes ?"

"Very correct! It seems that you have a very clear concept of the process. However, although round-robin scheduling is not possible, user-level threads also have their own advantages - you can customize the scheduling algorithm for your application , after all, when You have the final say in exiting the thread. Just said, because the operating system can only see the existence of the process, if a thread is blocked , what do you think will happen?"

"In the eyes of the operating system, if the process is blocked, then the entire process will enter the blocking state . Before the blocking operation ends, the process will not be able to obtain CPU resources. That is equivalent to that all threads are blocked ." White proudly answered.

"Yes, so if the thread is allowed to block the operation, the efficiency of the process will be greatly affected, so in this process, an alternative solution - jacket appears . The so-called jacket is to convert a blocking system call into into a non-blocking system call."

Xiaobai asked in surprise: "How can this be done? Can a call that should be blocked still become unblocked?"

Xiao Ming replied: "Let me give an example, instead of calling a system I/O routine directly, it calls an application-level I/O jacket routine. The code in this jacket routine checks and determines the I/O routine. O device is busy, if it is busy, block the thread in user mode , and then hand over control to another thread. Check the I/O device again after a period of time. As you said, in the end Blocking calls will be executed, but using a jacket can shorten the blocking time. However, there are cases where it can be unblocked, depending on the specific implementation."

Xiao Ming paused for a while and said, "There are so many concepts of user-level threads. Let's talk about kernel-level threads next."

kernel-level threads

"With the foreshadowing of user-level threads, kernel-level threads are much easier to talk about. Now we know that many operating systems already support kernel-level threads. In order to implement threads, the kernel needs to have threads that record all threads in the system. Table. When a new thread needs to be created, a system call needs to be made , and then the thread table is updated by the operating system . Of course, there are still traditional process tables. Think about it, if the operating system "sees See" thread, what's the benefit? "

Xiaobai replied confidently: "If the operating system kernel knows the existence of threads, it can be like scheduling multiple processes, putting these threads on several CPU cores, and it can achieve actual parallelism ."

"One more thing you didn't say, if the thread is visible, then if thread A is blocked, the thread that belongs to the same process as him will not be blocked . This is the absolute advantage of kernel-level threads."

"Isn't there any downside to kernel-level threads?"

"Of course there are disadvantages. If you think about it, letting the operating system perform thread scheduling means that every time you switch threads, you need to " fall into " the kernel state, and the transition of the operating system from user state to kernel state is expensive. , so the cost of kernel-level thread switching is greater than that of user-level threads . There is also a very important point - the thread table is stored in the fixed table space or stack space of the operating system, so the number of kernel-level threads is limited, and the scalability is not as good as that of user-level threads. "

"Kernel-level threads are just such a little thing. I will leave you a picture at the end. If you can understand it, it means that you understand today's concept."

two thread model

Xiaobai said proudly: "Of course I understand, thank you Xiaoming!"


Hope you get something after reading my article.

Thanks for reading, we'll have an appointment later!

Disclaimer: Original article, unauthorized reproduction is prohibited

{{o.name}}
{{m.name}}

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=324040575&siteId=291194637