Switching of Threads
Before we look at the process switch, let's look at the thread switching.
This article is mainly about user-level thread switching.
Because the switch of the process = resource switch + instruction performs sequence switching.
Separate the resource and instruction sequence, and if you switch from one execution instruction sequence to another, this is the thread switch.
The thread retains the advantage of concurrency (an alternate execution of multiple programs on a CPU), avoids the cost of process switching, does not need to cut resources (mapping tables), but simply executes instruction sequences. The essence of thread switching is that the mapping table is unchanged and the PC pointer changes.
switching of user-level threads
A Web browser
A thread is used to receive data from the server
A thread used to display text
Start implementing this viewer ...
void WebExplorer(){ char URL[]="http://cms.hit.edu.cn"; char buffer[1000]; pthread_create(...,GetData,URL,buffer); pthread_create(...,Show,buffer);}void GetData(char* URL,char *p){...};void Show(char* p){...};
After we have downloaded the data for a period of time, we cut out to execute another thread, display the text, and then cut back to continue the download.
yield and create
Pthread_create () allows multiple threads to trigger at the same time, and yield () completes the thread switching, allowing the thread to be executed alternately.
Now there are two execution sequences, which we want to execute after a period of time, jump to the other to execute, and then cut back. (Switching of threads)
Yiled jump from 100 to 300
//B中的YieldvoidYield(){ 找到300; 300;}//D中的YieldvoidYield(){ 找到204; jmp204;}
two execution sequences with one stack ...
Starting from 100, in a function to encounter the call of the B function, B's return address is the next instruction of the address 104 compression stack, and in B encountered a yield () call, yield () return address 204 compression stack. In b the yield () in JMP to 300, executes the C function, encounters a D () call in C, 304 presses the stack, executes D (), encounters the yield () call in D, and yields () The return address of the 404 compression stack.
After the yield () in D is executed, jump to 204
200:B(){ Yield(); 204:}
204 Start execution encountered "}", the stack, stack top element 404 is ejected execution 404, there is a problem, we have just returned to 100 that thread, and now cut to 300 that thread.
So a stack of two sequences is not possible.
one stack to two stacks
Each sequence corresponds to a stack, and yield toggles the first tangent of the stack.
//D中的Yieldvoid Yield(){ TCB2.esp=esp; esp=TCB1.esp; jmp204;}
Now the case for two stacks is:
Perform the yield in D, so that the stack completes the switchover, esp=1000. But when you hit JMP 204 and jump to 204, yield () never returns.
//D中的YieldvoidYield(){ TCB2.esp=esp; esp=TCB1.esp; //jmp 204;}
The JMP 204 is removed, at this time the stack has completed the switch esp=1000, and then yield execution encountered "}", the stack, at this time pop stack top element 204, execute 204 ("}" equivalent to RET), and RET, the stack is 104.
So two threads look like: Two TCB, two stacks, switched PCs in the stack.
The core of threadcreate is to apply a stack, a TCB (thread control block), and then associate the stack with the TCB.
void ThreadCreate(A){ TCB* tcb=malloc(); *stack=malloc(); *stack=A;//100 执行线程的起始地址 tcb.esp=stack;//栈和TCB关联}
in comprehensive
void ThreadCreate(func,arg1){ 申请栈; 申请TCB; func等入栈; 关联TCB与栈;}void GetData(char* URL,char *p){ 连接URL; 下载; Yield(); ...}void Yield(){ 压入现场; esp放在当前TCB中; Next();//调度函数,对系统影响很大,可优先调度Show 从下个TCB取出esp; 弹栈切换线程;}
User-level threads
Because the yield,create here is the user program, does not enter the kernel, so is the user-level thread.
User-level threads are not visible to the kernel.
If a thread of a process enters the kernel and blocks, it is not visible to the kernel that there are other threads in that process, so it will be cut directly to the other process to execute. At this point, the concurrency of user-level threads is useless.
For example
GetData(){ 连接URL发起请求; 等待网卡IO... 进程阻塞}Show(){ 显示文本和连接; ...}
User-level threads can only be cut at the user level Che, not into the kernel.
User-level threads