作者:TASK_RUNNING
链接:https://www.jianshu.com/p/60e7238876a2
我们在驱动编程时,如果程序内使用了死循环,则一般会使CPU的占用率达到100%,某些情况下,我们希望降低CPU使用率,那应该怎么办呢?
1. schedule_timeout
schedule_timeout,做了两件事:
- 设置timer
- 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 。
原创文章,作者:carmelaweatherly,如若转载,请注明出处:https://blog.ytso.com/tech/aiops/245198.html