c语言中线程的调度,线程、进程及其调度简介

知识需要不断总结、验证、迭代,知其然,知其所以然。

1、进程和线程

进程和线程的区别与联系:

进程:资源申请的最小单位

线程:资源调度的最小单位,进程的一部分,描述指令流的执行状态。

内核中,描述进程的数据结构PCB:进程控制块,描述线程的数据结构 TCB:线程控制块。

e01fdd4af3a8de177282cc7eaea59712.png

图1 单线程进程

3d38e8557963cd9f99ad81dc5acdbe21.png

图2 多线程进程

进程主要设计目的是隔离,和其他进程地址空间隔离开来;线程是进程的一部分,主要设计目的是通信和并发,隔离不是主要目的。

进程/线程生命周期:

ae8b37cc6d9c727276e030d5c65e88a1.png

图3 进程生命周期

2、线程的调度

调度算法最基本的一类是基于线程优先级的,线程的一种分类角度为:普通线程(SCHED_OTHER)和实时线程(SCHED_RR/SCHED_FIFO)。实时线程的优先级高于普通线程。操作系统每次从就绪队列中选择线程调度,占有cpu。

关于优先级,在TCB中有三个字段描述优先级:

A、静态优先级,static_proi,和nice的值(-20~19)相关

B、动态优先级,  proi

C、实时优先级,  rt_priority

普通线程使用,A、B,实时线程使用的参数A、C。

在分时线程中,操作系统根据动态优先级选定下一个待执行的线程,静态优先级是动态优先级的一个基准。即B会在A的基础上浮动,同时A决定了线程调度的时间片。

在实时线程中,操作系统不计算动态优先级,只根据C即实时优先级选定下一个待执行的线程。如果是FIFO则没有时间片(要么主动放弃cpu、要么被高优先级线程抢占),如果RR,可以理解为带时间片轮转的FIFO。

1、假设系统中只有:OTHER的线程,A、B、C、D、E、F…

那么系统会根据动态优先级高低来调用其中的线程,

动态优先级 = max(100, min(静态优先级 – bonus + 5, 139))(参考深入理解linux内核)。

同时每个线程执行的时间片,也是和静态优先级强相关的。

2、假设系统中只有RR类型的线程,A、B、C、D、E、F…

操作系统每次调用就只会根据实时优先级的高低选择带执行的线程,假如A在执行,这个时候B等待的资源满足了,B的实时优先级比A高,那A就会B抢占。B结束有三种可能:1、B的时间用完了;2、B主动放弃cpu(等待某种资源);3、B被更高优先级线程抢占。

3、假设系统中只有FIFO类型的线程,A、B、C、D、E、F….

操作系统同样每次直选实时优先级最高的线程执行,假如A正在执行,这个时候B等待的资源满足了,B的优先级 >  A的优先级,那同样B就抢占A。B结束的条件是:1、主动放弃cpu;2、被更高优先级抢占。FIFO线程没有时间片的概念,如果需要它会一直占着cpu,直到被抢占或者主动放弃。

4、如果系统中三类线程都有会是什么情况呢?

首先,实时线程 > 普通线程,优先选择实时线程且普通线程还会被实时线程抢占。

实时线程中,选择优先级高的执行,在执行过程中,也会被更高优先级的线程抢占。假如有两个FIFO线程A和B,优先级都是80,如果A在执行且一直占用cpu,那么B就无法执行,产生饥饿,直到A主动放弃cpu。如果他们不是FIFO而是RR的,那么A和B就是时间片轮转执行,大家都有机会拿到cpu。

参考:深入理解linux内核

Linux内核设计与实现

在线课程:《操作系统》—清华大学向勇

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 C 语言中,线程是通过操作系统提供的线程库来实现的。线程可以让程序同时执行多个任务,从而提高程序的并发性和效率。 任务调度是指操作系统根据一定的策略将 CPU 的执行时间分配给不同的线程或进程。在 C 语言中,任务调度是由操作系统完成的,程序员只需要编写线程的代码,然后将线程交给操作系统进行调度。 通常情况下,线程的调度是基于优先级的。操作系统会将 CPU 时间分配给具有最高优先级的线程,直到该线程完成或被阻塞。当该线程完成或被阻塞后,操作系统会选择下一个具有最高优先级的线程运行。如果没有线程处于运行状态,那么操作系统会将 CPU 时间分配给等待队列中的线程。 线程在 C 语言中的使用需要包含头文件 pthread.h,并使用 pthread_create() 函数创建线程,该函数会返回一个线程 ID,然后使用 pthread_join() 函数等待线程结束。 下面是一个简单的例子,它创建了两个线程并让它们同时执行: ``` #include <stdio.h> #include <pthread.h> void* thread_function(void* arg) { printf("Thread %d is running\n", *((int*)arg)); return NULL; } int main() { pthread_t thread1, thread2; int thread1_id = 1, thread2_id = 2; pthread_create(&thread1, NULL, thread_function, &thread1_id); pthread_create(&thread2, NULL, thread_function, &thread2_id); pthread_join(thread1, NULL); pthread_join(thread2, NULL); return 0; } ``` 在上面的例子中,我们首先定义了一个函数 thread_function(),它将作为线程的入口点。然后我们使用 pthread_create() 函数创建了两个线程,并将它们分别赋值给 thread1 和 thread2 变量。每个线程都将调用 thread_function() 函数,并传递一个整数参数作为线程 ID。最后,我们使用 pthread_join() 函数等待线程结束。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值