Process scheduling is an important kernel function in Linux systems. It can allocate CPU usage rights among multiple processes so that each process can get a reasonable running time, thereby improving the concurrency and response of the system. sex. The effect of process scheduling directly affects system performance and user experience. Therefore, it is very necessary to understand process scheduling in Linux systems. But, do you really understand process scheduling in Linux systems? Do you know its concepts, principles and methods? Do you know how to use and configure process scheduling under Linux? This article will introduce you to the relevant knowledge of process scheduling in Linux systems in detail, allowing you to better use and understand this powerful kernel function under Linux.
In the Linux kernel, completion is a simple synchronization mechanism that marks "things may proceed".
To use completion, you must include
This variable can be declared and initialized statically:
DECLARE_COMPLETION(my_comp);
Or dynamic initialization:
1. **struct** completion my_comp; 2. init_completion(&my_comp);
If the driver wants to wait for the completion of a process before performing subsequent operations, it can call wait_for_completion with the event to be completed as a parameter:
wait_for_completion waits on completion. If interruptible is added, it means that the thread waiting can be interrupted by signals sent from the outside; if killable is added, it means that the thread can only be interrupted by the kill signal; if timeout is added, it means that the waiting will automatically end after waiting for a certain period of time. The unit of timeout is the time slice jiffies used by the system (mostly 1ms).
If other parts of the code can determine that the event has been completed, one of the following two functions can be called to wake up the process waiting for the event:
1. **void** complete(**struct** completion *comp); 2. **void** complete_all(**struct** completion *comp); /* Linux 2.5.x以上版本 */
The former function will only wake up one waiting process, and the latter function will wake up all processes waiting for the event. Because of the way completion is implemented, complete will work even if it is called before wait_for_competion.
For example, in the MD device driver implementation, there is a recovery thread md_recovery_thread. The driver registers and unregisters recovery threads through md_register_thread and md_unregister_thread. The execution logic of restoring the thread is in the md_thread function, which is roughly as follows:
1. **int** md_thread(**void** * arg) 2. { 3. 线程初始化; 4. **while** (运行) { 5. 处理逻辑; 6. 接收信号; 7. } 8. **return** 0; 9. }
md_register_thread will create a recovery thread, which must return the thread pointer after the thread is actually initialized. Therefore, the logic is:
1. mdk_thread_t *md_register_thread(**void** (*run) (**void** *), **void** *data, **const** **char** *name) 2. { 3. mdk_thread_t ***thread**; 4. …… 5. **struct** completion event; 6. /* 为线程分配空间 */ 7. **thread** = (mdk_thread_t *) kmalloc (**sizeof**(mdk_thread_t), GFP_KERNEL); 8. …… 9. init_completion(&event); 10. …… 11. **thread**->event = &event; 12. /* 创建内核线程 */ 13. ret = kernel_thread(md_thread, **thread**, 0); 14. /* 等待线程初始化结束 */ 15. …… 16. wait_for_completion(&event); 17. /* 返回线程指针 */ 18. **return** **thread**; 19. }
And md_unregister_thread logs out and resumes the thread by sending the SIGKILL signal to the thread. It also needs to release the memory occupied by the thread after the thread actually exits. Therefore, the logic is:
1. **void** md_unregister_thread(mdk_thread_t ***thread**) 2. { 3. **struct** completion event; 4. init_completion(&event); 5. **thread**->event = &event; 6. …… 7. /* 向线程发送SIGKILL信号终止其运行 */ 8. md_interrupt_thread(**thread**); 9. /* 等待线程退出 */ 10. wait_for_completion(&event); 11. /* 释放线程所占用的内存 */ 12. kfree(**thread**); 13. }
If you consider completion, the logic of md_thread is:
1. **int** md_thread(**void** * arg) 2. { 3. 线程初始化; 4. complete(**thread**->event); 5. **while** (运行) { 6. 处理逻辑; 7. 接收信号; 8. } 9. complete(**thread**->event); 10. **return** 0; 11. }
It should be noted that since the wait event is a shared resource in the driver and recovery thread, it must be a global variable, or as in the implementation code, defined as a local variable, and its pointer is placed in the recovery thread. in the thread structure.
typedef struct mdk_thread_s { …… struct completion *event; …… } mdk_thread_t;
Through this article, you should have an in-depth understanding of process scheduling in Linux systems and know its concepts, principles and methods. You should also understand the role and impact of process scheduling, and how to correctly use and configure process scheduling under Linux. We recommend that you use process scheduling to improve system concurrency and responsiveness when using a Linux system. At the same time, we also remind you to pay attention to some potential problems and challenges when using process scheduling, such as process priority, load balancing, real-time performance, etc. I hope this article can help you better use the Linux system and allow you to enjoy the advantages and convenience of process scheduling under Linux.
The above is the detailed content of Process Scheduling in Linux Systems: Concepts, Principles and Methods. For more information, please follow other related articles on the PHP Chinese website!