ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

进程调度-【转载】schedule_timeout和schedule_timeout_interruptible让出CPU

2022-04-17 19:32:37  阅读:255  来源: 互联网

标签:__ current TASK schedule timer interruptible timeout


 

作者:TASK_RUNNING
链接:https://www.jianshu.com/p/60e7238876a2

 

我们在驱动编程时,如果程序内使用了死循环,则一般会使CPU的占用率达到100%,某些情况下,我们希望降低CPU使用率,那应该怎么办呢?

1. schedule_timeout

schedule_timeout,做了两件事:

  1. 设置timer
  2. schedule

此调用并没有改变进程的状态TASK_RUNNING,所以在__schedule()中,不会把进程从运行队列中移出去。当系统进行调度的时候,这个进程仍然会被调度进来。

2. schedule_timeout_interruptible

schedule_timeout_interruptible, 在调用schedule之前,会先调用set_current_state设置进程状态,所以会将进程移出运行队列。从而达到降低CPU使用率的作用。
类似的还有:
schedule_timeout_uninterruptible,  schedule_timeout_killable


源码分析
kernel/time/timer.c
1801/**
1802 * schedule_timeout - sleep until timeout
1803 * @timeout: timeout value in jiffies
1804 *
1805 * Make the current task sleep until @timeout jiffies have elapsed.
1806 * The function behavior depends on the current task state
1807 * (see also set_current_state() description):
1808 *
1809 * %TASK_RUNNING - the scheduler is called, but the task does not sleep
1810 * at all. That happens because sched_submit_work() does nothing for
1811 * tasks in %TASK_RUNNING state.
1812 *
1813 * %TASK_UNINTERRUPTIBLE - at least @timeout jiffies are guaranteed to
1814 * pass before the routine returns unless the current task is explicitly
1815 * woken up, (e.g. by wake_up_process()).
1816 *
1817 * %TASK_INTERRUPTIBLE - the routine may return early if a signal is
1818 * delivered to the current task or the current task is explicitly woken
1819 * up.
1820 *
1821 * The current task state is guaranteed to be %TASK_RUNNING when this
1822 * routine returns.
1823 *
1824 * Specifying a @timeout value of %MAX_SCHEDULE_TIMEOUT will schedule
1825 * the CPU away without a bound on the timeout. In this case the return
1826 * value will be %MAX_SCHEDULE_TIMEOUT.
1827 *
1828 * Returns 0 when the timer has expired otherwise the remaining time in
1829 * jiffies will be returned. In all cases the return value is guaranteed
1830 * to be non-negative.
1831 */
1832signed long __sched schedule_timeout(signed long timeout)
1833{
1834        struct process_timer timer;
1835        unsigned long expire;
1836
1837        switch (timeout)
1838        {
1839        case MAX_SCHEDULE_TIMEOUT:
1840                /*
1841                 * These two special cases are useful to be comfortable
1842                 * in the caller. Nothing more. We could take
1843                 * MAX_SCHEDULE_TIMEOUT from one of the negative value
1844                 * but I' d like to return a valid offset (>=0) to allow
1845                 * the caller to do everything it want with the retval.
1846                 */
1847                schedule();
1848                goto out;
1849        default:
1850                /*
1851                 * Another bit of PARANOID. Note that the retval will be
1852                 * 0 since no piece of kernel is supposed to do a check
1853                 * for a negative retval of schedule_timeout() (since it
1854                 * should never happens anyway). You just have the printk()
1855                 * that will tell you if something is gone wrong and where.
1856                 */
1857                if (timeout < 0) {
1858                        printk(KERN_ERR "schedule_timeout: wrong timeout "
1859                                "value %lx\n", timeout);
1860                        dump_stack();
1861                        current->state = TASK_RUNNING;
1862                        goto out;
1863                }
1864        }
1865
1866        expire = timeout + jiffies;
1867
1868        timer.task = current;
1869        timer_setup_on_stack(&timer.timer, process_timeout, 0);
1870        __mod_timer(&timer.timer, expire, MOD_TIMER_NOTPENDING);
1871        schedule();
1872        del_singleshot_timer_sync(&timer.timer);
1873
1874        /* Remove the timer from the object tracker */
1875        destroy_timer_on_stack(&timer.timer);
1876
1877        timeout = expire - jiffies;
1878
1879 out:
1880        return timeout < 0 ? 0 : timeout;
1881}
1882EXPORT_SYMBOL(schedule_timeout);
1883
1884/*
1885 * We can use __set_current_state() here because schedule_timeout() calls
1886 * schedule() unconditionally.
1887 */
1888signed long __sched schedule_timeout_interruptible(signed long timeout)
1889{
1890        __set_current_state(TASK_INTERRUPTIBLE);
1891        return schedule_timeout(timeout);
1892}
1893EXPORT_SYMBOL(schedule_timeout_interruptible);
1894
1895signed long __sched schedule_timeout_killable(signed long timeout)
1896{
1897        __set_current_state(TASK_KILLABLE);
1898        return schedule_timeout(timeout);
1899}
1900EXPORT_SYMBOL(schedule_timeout_killable);
1901
1902signed long __sched schedule_timeout_uninterruptible(signed long timeout)
1903{
1904        __set_current_state(TASK_UNINTERRUPTIBLE);
1905        return schedule_timeout(timeout);
1906}
1907EXPORT_SYMBOL(schedule_timeout_uninterruptible);

1834 定义一个 process_timer 对象

1868 ~ 1870 填充 timer 对象,然后将这个 timer  使用   __mod_timer 函数,加入 到系统中。

1071 调用 schedule 函数进行调度

 

1888 ~ 1907  schedule_timeout_interruptable /  schedule_timeout_uninterruptable  / schedule_timeout_killable   的实现,先设置状态,再调用  schedule_timeout 。

 

标签:__,current,TASK,schedule,timer,interruptible,timeout
来源: https://www.cnblogs.com/zhangzhiwei122/p/16156917.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有