进程调度是 Linux 系统中一种重要的内核功能,它可以在多个进程之间分配 CPU 的使用权,使得每个进程都能得到合理的运行时间,从而提高系统的并发性和响应性。进程调度的效果直接影响到系统的性能和用户体验,因此,了解 Linux 系统中的进程调度是非常有必要的。但是,你真的了解 Linux 系统中的进程调度吗?你知道它的概念、原理和方法吗?你知道如何在 Linux 下使用和配置进程调度吗?本文将为你详细介绍 Linux 系统中的进程调度的相关知识,让你在 Linux 下更好地使用和理解这个强大的内核功能。
在Linux内核中,completion是一种简单的同步机制,标志”things may proceed”。
要使用completion,必须在文件中包含
-
这个变量可以静态地声明和初始化:
-
DECLARE_COMPLETION(my_comp);
-
或者动态初始化:
1. **struct** completion my_comp; 2. init_completion(&my_comp);
如果驱动程序要在执行后面操作之前等待某个过程的完成,它可以调用wait_for_completion ,以要完成的事件为参数:
-
void wait_for_completion(struct completion *comp);
wait_for_completion等待在completion上。如果加了interruptible,就表示线程等待可被外部发来的信号打断;如果加了killable,就表示线程只可被kill信号打断;如果加了timeout,表示等待超出一定时间会自动结束等待,timeout的单位是系统所用的时间片jiffies(多为1ms)。
如果其它部分代码可以确定事件已经完成,可以调用下面两个函数之一来唤醒等待该事件的进程:
1. **void** complete(**struct** completion *comp);
2. **void** complete_all(**struct** completion *comp); /* Linux 2.5.x以上版本 */
前一个函数将只唤醒一个等待进程,而后一个函数唤醒等待该事件的所以进程。由于completion的实现方式,即使complete在wait_for_competion之前调用,也可以正常工作。
例如,在MD设备驱动程序实现中,有一个恢复线程md_recovery_thread。驱动程序通过md_register_thread和md_unregister_thread来注册和注销恢复线程。恢复线程的执行逻辑在md_thread函数中,大致如下:
1. **int** md_thread(**void** * arg)
2. {
3. 线程初始化;
4. **while** (运行) {
5. 处理逻辑;
6. 接收信号;
7. }
8. **return** 0;
9. }
md_register_thread将创建一个恢复线程,它必须在线程真正初始化结束之后才能返回该线程的指针。因此,其逻辑是:
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. }
而md_unregister_thread通过向线程发送SIGKILL信号注销恢复线程,它也需要在线程真正退出后才能释放线程所占用的内存。因此,其逻辑是:
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. }
如果考虑completion,md_thread的逻辑是:
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. }
需要说明的是,由于等待事件是在驱动程序和恢复线程中的一个共享资源,它必须是一个全局变量,或者如实现代码中,定义为一个局部变量,而将其指针放在恢复线程结构中。
typedef struct mdk_thread_s {
……
struct completion *event;
……
} mdk_thread_t;
通过本文,你应该对 Linux 系统中的进程调度有了一个深入的了解,知道了它的概念、原理和方法。你也应该明白了进程调度的作用和影响,以及如何在 Linux 下正确地使用和配置进程调度。我们建议你在使用 Linux 系统时,使用进程调度来提高系统的并发性和响应性。同时,我们也提醒你在使用进程调度时要注意一些潜在的问题和挑战,如进程优先级、负载均衡、实时性等。希望本文能够帮助你更好地使用 Linux 系统,让你在 Linux 下享受进程调度的优势和便利。
以上就是良许教程网为各位朋友分享的Linu系统相关内容。想要了解更多Linux相关知识记得关注公众号“良许Linux”,或扫描下方二维码进行关注,更多干货等着你 !