Arm Linux Kernel Hacks

rousalome.egloos.com

포토로그 Kernel Crash


통계 위젯 (화이트)

41107
469
422673


[리눅스커널] 시간관리: msecs_to_jiffies 함수란 8. 커널 타이머 관리

msecs_to_jiffies() 함수는 밀리초를 입력으로 받아 jiffies 단위 시각 정보를 반환합니다. 리눅스 커널에서 실행 시간 기준으로 흐름을 제어할 때 많이 씁니다.

msecs_to_jiffies() 함수 세부 코드 분석에 앞서 이 함수를 왜 쓰는지 알아봅시다.

당연한 이야기지만 개발자들은 실행 시간을 '초'나 '밀리 초' 단위로 생각하는 습관이 있습니다.
 
100밀리 초 후에 이미 실행한 함수가 1을 반환하면 어떻게 예외 처리를 할까?” 
200밀리 초 정도 딜레이를 줘야 할까?”

그런데 커널은 HZ 단위로 실행 시간을 관리합니다. 따라서 커널이 시간을 처리하는 단위로 시간 정보를 변환시켜야 합니다. 이를 위해 msecs_to_jiffies() 함수를 호출해야 합니다. 이 함수는 가독성도 높습니다. 함수 이름처럼 ‘밀리초를 지피스로 바꾸는’ 기능이라고 유추할 수 있습니다.  

* 강의 동영상도 있으니 같이 들으시면 좋습니다.





#커널 시간관리 목차
커널 타이머 관리 주요 개념 소개
jiffies란
커널 타이머 제어
동적 타이머 초기화
동적 타이머 등록하기
동적 타이머는 누가 언제 실행하나?
라즈베리파이 커널 타이머 실습 및 로그 분석

"혹시 궁금점이 있으면 댓글로 질문 남겨주세요. 아는 한 성실히 답글 올려드리겠습니다!"
 

# Reference: For more information on 'Linux Kernel';

디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 1

디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 2



repository:
http://rousalome.egloos.com/10025674



핑백

덧글

  • eunwoo 2021/03/25 22:07 # 삭제 답글

    안녕하세요!! 디버깅을 통해 배우는 리눅스 커널의 구조와 원리 8단원 타이머 공부도중 궁금한게 생겨서 댓글을 남깁니다!!

    msecs_to_jiffies 함수를 분석하는 도중 21페이지에 있는 MAX_JIFFY_OFFSET 매크로 부분이 이해가 가지 않습니다

    #define MAX_JIFFY_OFFEST ((LONG_MAX) >> 1 - 1)
    #define LONG_MAX ((long)(~0UL>>1))

    여기서 LONG_MAX의 값이 아래와 같이 변환이 된다면
    ~0UL >> 1 == 0xFFFFFFFF >> 1 == 0x7FFFFFFF 이와같이 될 것이며 이를 MAX_JIFFY_OFFSET에 넣는다면

    #define MAX_JIFFY_OFFEST (0x7FFFFFFF >> 1 - 1) 이와같이 되어서 결국엔 0x3FFFFFFF - 1 == 0x3FFFFFFE 가 되는게 아닌가요??

    우측 쉬프트연산이 총 2번 일어나는데 0xFFFFFFFF에서 0x1FFFFFFF로 바뀌는 이유를 알고싶습니다!
  • AustinKim 2021/03/27 01:18 #

    지적하신 내용이 맞습니다. 이미 다른 개발자가 이 부분의 수식에 오류가 있고 지적했는데요.
    블로그에 공지를 하지 못한 점 사과드립니다. 이 내용은 수정해 2쇄에 반영될 예정입니다.

    참고로, MAX_JIFFY_OFFSET의 정체를 확인하기 위해 아래와 같은 코드를 작성해 봤는데요.

    diff --git a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c
    index a5f183c..b7e8fd8 100644
    --- a/arch/arm/kernel/sys_arm.c
    +++ b/arch/arm/kernel/sys_arm.c
    @@ -24,6 +24,15 @@
    #include <linux/ipc.h>
    #include <linux/uaccess.h>
    #include <linux/slab.h>
    +#include <linux/jiffies.h>
    +
    +void trace_time_func(void)
    +{
    + unsigned long time_val = MAX_JIFFY_OFFSET;
    + printk("val = %lu n", time_val);
    +}

    /*
    * Since loff_t is a 64 bit type we avoid a lot of ABI hassle
    @@ -32,5 +41,6 @@
    asmlinkage long sys_arm_fadvise64_64(int fd, int advice,
    loff_t offset, loff_t len)
    {
    + trace_time_func();
    return ksys_fadvise64_64(fd, offset, len, advice);
    }

    trace_time_func() 함수의 어셈블리 코드는 다음과 같은데요.

    8010c0ac <trace_time_func>:
    8010c0ac: e1a0c00d mov ip, sp
    8010c0b0: e92dd800 push {fp, ip, lr, pc}
    8010c0b4: e24cb004 sub fp, ip, #4
    8010c0b8: e52de004 push {lr} ; (str lr, [sp, #-4]!)
    8010c0bc: eb000ef6 bl 8010fc9c <__gnu_mcount_nc>
    8010c0c0: e30408b0 movw r0, #18608 ; 0x48b0
    8010c0c4: e3e01107 mvn r1, #-1073741823 ; 0xc0000001
    8010c0c8: e34800bf movt r0, #32959 ; 0x80bf
    8010c0cc: eb23890d bl 809ee508 <printk>
    8010c0d0: e89da800 ldm sp, {fp, sp, pc}

    'mvn r1, #-1073741823' 코드가 실행되면 r1(MAX_JIFFY_OFFSET)는 0x3FFFFFFE로 업데이트됩니다.

    감사합니다.
댓글 입력 영역