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