커널 지연 함수
5144 단어 android/linux 커널운영 체제전원 관리
void msleep(unsigned int msecs)
{
unsigned long timeout = msecs_to_jiffies(msecs) + 1;
while (timeout)
timeout = schedule_timeout_uninterruptible(timeout);
}
왜 jiffies로 전환할 때 +1을 해야 하나요?앞에서 우리가 말한 바와 같이 이 지연시간은 최소한 지연전환의 jiffies 시간을 확보해야 한다. 한 jiffies는 10밀리초이다. 예를 들어 우리는 10개의 수를 찾아서 하나의 jiffies를 표시할 수 있다. 5까지 세었을 때 msleep을 호출했다. 그러면 분명히 우리는 이 jiffies가 시시각각 돌아올 수 없다. 적어도 지연설정의 jiffies 원칙을 위반했기 때문에 jiffies+1으로 전환하는 것이 비교적 적합하다.내부 핵에서도 특별히 해석을 했다.
unsigned long msecs_to_jiffies(const unsigned int m)
{
/*
* Negative value, means infinite timeout:
*/
if ((int)m < 0)
return MAX_JIFFY_OFFSET;
。
。
。
}
/*
* Change timeval to jiffies, trying to avoid the
* most obvious overflows..
*
* And some not so obvious.
*
* Note that we don't want to return LONG_MAX, because
* for various timeout reasons we often end up having
* to wait "jiffies+1" in order to guarantee that we wait
* at _least_ "jiffies" - so "jiffies+1" had better still
* be positive.
*/
#define MAX_JIFFY_OFFSET ((LONG_MAX >> 1)-1)
2)msleep_interruptible: 밀리초급 시간 지연, 이 시간 지연 함수는 신호가 끊기면 시간 초과, 남은 시간을 되돌려주고 CPU를 양보할 수 있습니다
unsigned long msleep_interruptible(unsigned int msecs)
{
unsigned long timeout = msecs_to_jiffies(msecs) + 1;
while (timeout && !signal_pending(current))
timeout = schedule_timeout_interruptible(timeout);
return jiffies_to_msecs(timeout);
}
3) ssleep: 초급 지연 시간, msleep 호출을 통해 CPU 내보내기
static inline void ssleep(unsigned int seconds)
{
msleep(seconds * 1000);
}
4)usleep_range: 이 시간 지연 함수는 마이크로초급 시간 지연을 실현하는데 특히 시간 초과 범위를 설정할 수 있다. 원본 코드를 보면 이 함수가 작업 상태를 ASK 로 설정하는 것을 알 수 있다.UNNTERRUPTIBLE, 즉, 이 지연은 최소한 min 마이크로초의 지연이 끊기지 않도록 보장합니다.CPU가 나가요.
/**
* usleep_range - Drop in replacement for udelay where wakeup is flexible
* @min: Minimum time in usecs to sleep
* @max: Maximum time in usecs to sleep
*/
void usleep_range(unsigned long min, unsigned long max)
{
__set_current_state(TASK_UNINTERRUPTIBLE);
do_usleep_range(min, max);
}
5) ndelay: CPU를 허용하지 않는 나노초 지연 시간
static inline void ndelay(unsigned long x)
{
udelay(DIV_ROUND_UP(x, 1000));
}
6) udelay: CPU를 허용하지 않는 마이크로초 지연 시간
/*
* division by multiplication: you don't have to worry about
* loss of precision.
*
* Use only for very small delays ( < 2 msec). Should probably use a
* lookup table, really, as the multiplications take much too long with
* short delays. This is a "reasonable" implementation, though (and the
* first constant multiplications gets optimized away if the delay is
* a constant)
*/
#define __udelay(n) arm_delay_ops.udelay(n)
#define __const_udelay(n) arm_delay_ops.const_udelay(n)
#define udelay(n) \
(__builtin_constant_p(n) ? \
((n) > (MAX_UDELAY_MS * 1000) ? __bad_udelay() : \
__const_udelay((n) * UDELAY_MULT)) : \
__udelay(n))
정보builtin_constant_p(x), 정확한 정의는 다음과 같다. 만약 x의 값이 컴파일할 때 확정된다면 이 함수는 1로 되돌아온다.
armdelay_ops에서 말하자면, 내핵에는 기본적인 리셋 함수가 있다
/*
* Default to the loop-based delay implementation.
*/
struct arm_delay_ops arm_delay_ops = {
.delay = __loop_delay,
.const_udelay = __loop_const_udelay,
.udelay = __loop_udelay,
};
그러나 대부분의 제조업체들은 일반적으로timer를 등록하여 시간 지연 사용을 제공하는데 구체적으로arch/arm/lib/delay를 참고할 수 있다.실현
/*
* Default to the loop-based delay implementation.
*/
struct arm_delay_ops arm_delay_ops = {
.delay = __loop_delay,
.const_udelay = __loop_const_udelay,
.udelay = __loop_udelay,
};
#ifdef ARCH_HAS_READ_CURRENT_TIMER
static void __timer_delay(unsigned long cycles)
{
cycles_t start = get_cycles();
while ((get_cycles() - start) < cycles)
cpu_relax();
}
static void __timer_const_udelay(unsigned long xloops)
{
unsigned long long loops = xloops;
loops *= loops_per_jiffy;
__timer_delay(loops >> UDELAY_SHIFT);
}
static void __timer_udelay(unsigned long usecs)
{
__timer_const_udelay(usecs * UDELAY_MULT);
}
void __init init_current_timer_delay(unsigned long freq)
{
pr_info("Switching to timer-based delay loop
");
lpj_fine = freq / HZ;// jiffy
loops_per_jiffy = lpj_fine;
arm_delay_ops.delay = __timer_delay;
arm_delay_ops.const_udelay = __timer_const_udelay;
arm_delay_ops.udelay = __timer_udelay;
}
unsigned long __cpuinit calibrate_delay_is_known(void)
{
return lpj_fine;
}
#endif
7) mdelay: 밀리초급 지연 시간, ndelay의 1000배, CPU를 양보하지 않음
#ifndef mdelay
#define mdelay(n) (\
(__builtin_constant_p(n) && (n)<=MAX_UDELAY_MS) ? udelay((n)*1000) : \
({unsigned long __ms=(n); while (__ms--) udelay(1000);}))
#endif
지연 함수가 CPU를 양보할 수 있는지에 대해 사용 시 주의해야 한다. 일반적으로 지연 시간에 대한 요구가 매우 정확하고 CPU를 양보하지 않는 지연 함수를 사용한다.지연 시간에 대한 요구가 정확하지 않기 때문에 CPU를 양보하는 지연 함수를 사용할 수 있다. 지연 시 시스템이 수면에 들어가지 않도록 하기 위해 보통 CPU를 양보하는 지연 시간을 사용하기 전에 웨이크록 자물쇠를 달아서 수면을 막아야 한다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
C# 스레드 풀 기능 자체 구현(1)다중 스레드 기술은 주로 프로세서 단원 내의 여러 스레드가 집행되는 문제를 해결하는데 이것은 프로세서 단원의 유휴 시간을 현저하게 줄이고 프로세서 단원의 삼키기 능력을 증가시킬 수 있다.그러나 다중 루틴을 잘못 적용...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.