失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > sleep睡眠时间的疑问

sleep睡眠时间的疑问

时间:2023-04-23 18:56:49

相关推荐

sleep睡眠时间的疑问

一、内核配置的tick频率一般是100HZ,即每隔10ms后产生一次始终中断,然后在时钟中断结束后会有一次进程的调度,选择最合适的进程实现调度。

menuconfig Kernel FeaturesTimer frequency

二、问题

那么问题来了。假如代码中使用usleep实现小于10ms的延时,比方说usleep(10),延时10us,那么等usleep睡眠10us结束后,会立马执行嘛?还是必须等到10ms后执行?因为,usleep,msleep,sleep等函数会主动让出CPU休眠。

1、编写段代码查看下多久后能运行,且默认任务的调度policy

#include <unistd.h>#include <stdio.h>#include <string.h>#include <sys/time.h>#include <sys/resource.h>#include <sched.h>int main(){struct timeval val;pid_t pid;int policy, priority;printf("__start.\n");pid = getpid();policy = sched_getscheduler(pid);priority = getpriority(0, 0);printf("pid=%d, policy=%d, priority=%d\n", pid, policy, priority);memset(&val, 0x00, sizeof(struct timeval));gettimeofday(&val, NULL);printf("before. second=%ld, us=%ld\n", val.tv_sec, val.tv_usec);memset(&val, 0x00, sizeof(struct timeval));sleep(1);gettimeofday(&val, NULL);printf("after. second=%ld, us=%ld\n", val.tv_sec, val.tv_usec);return 0;}

2、运行结果

调度策略的宏定义情况<include/uapi/linux/sched.h>:

普通的编译程序调用策略是SCHED_NORMAL

3、通过strace命令可以查看sleep的系统调用调用时nanosleep系统接口

最终会调用内核中的hrtimer_nanosleep函数中的do_nanosleep

long hrtimer_nanosleep(ktime_t rqtp, const enum hrtimer_mode mode, const clockid_t clockid)

等待休眠时间的结束,把任务重新挂在到runqueue中,等待重新调度。

4、提高调度成功的机会就需要设置任务成SCHED_FIFO模式,同时优先级设置最高。尝试设置应用程序调度策略和优先级。

#include <unistd.h>#include <stdio.h>#include <string.h>#include <sys/time.h>#include <sys/resource.h>#include <sched.h>int main(){int rt = -1;struct timeval val;pid_t pid;struct sched_param sparam;int policy, priority;printf("__start.\n");pid = getpid();policy = sched_getscheduler(pid);priority = getpriority(0, 0);printf("before settings. pid=%d, policy=%d, priority=%d\n", pid, policy, priority);memset(&sparam, 0x00, sizeof(struct sched_param));sparam.sched_priority = sched_get_priority_max(SCHED_FIFO);rt = sched_setscheduler(pid, SCHED_FIFO, &sparam);if (rt)printf("sched_setscheduler error.\n");policy = sched_getscheduler(pid);memset(&sparam, 0x00, sizeof(struct sched_param));rt = sched_getparam(pid, &sparam);if (rt)printf("sched_setscheduler error.\n");printf("after settings. pid=%d, policy=%d, priority=%d\n", pid, policy, sparam.sched_priority);memset(&val, 0x00, sizeof(struct timeval));gettimeofday(&val, NULL);printf("before. second=%ld, us=%ld\n", val.tv_sec, val.tv_usec);memset(&val, 0x00, sizeof(struct timeval));sleep(1);gettimeofday(&val, NULL);printf("after. second=%ld, us=%ld\n", val.tv_sec, val.tv_usec);return 0;}

运行结果

进程调度策略修改成SCHED_FIFO,且优先级是最高等级99,可以看出设置成FIFO调度策略的程序延时比NORMAL的低一些

三、PREEMPT配置相关宏定义

CONFIG_PREEMPT_NONE

CONFIG_PREEMPT和CONFIG_PREEMPT_VOLUNTARY都不会设置,表示在内核态既不会被抢占,调might_resched()函数也不会主动切换

CONFIG_PREEMPT_VOLUNTARY

might_resched()函数会主动切换,但是内核依旧不会被抢占。常见于桌面系统

CONFIG_PREEMPT

和CONFIG_PREEMPT_VOLUNTARY同时生效,在中断返回内核态时会检查TIF_NEEDRESCHED标志,如果需要调度,则会调schedule,内核态会被抢占。常见于实时性高的环境,如嵌入式系统

四、NORMAL和FIFO调度策略的任务会共存于系统中,假如FIFO调度策略的任务一直在运行,那是否NORMAL的任务无法调度到呢?

1、系统提供了/proc/sys/kernel/sched_rt_period_us和/proc/sys/kernel/sched_rt_runtime_us两个参数,默认状态sched_rt_period_us=1000000,sched_rt_runtime_us=950000

2、在sched_rt_period_us周期内给FIFO调度策略的任务运行时间是sched_rt_runtime_us,其余给其他调度策略的任务,因此不存在其他调度策略的任务无法获取CPU权限的情况。

如果觉得《sleep睡眠时间的疑问》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。