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

2022/4/18 7:13:01

本文主要是介绍进程调度-【转载】schedule_timeout和schedule_timeout_interruptible让出CPU,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

 

作者: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 。

 



这篇关于进程调度-【转载】schedule_timeout和schedule_timeout_interruptible让出CPU的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程