FreeRTOS 의 소스 코드 개인 분석 (KEIL 에서 STM32F 103 의 Demo 기반) 5

list. c 와 list. h 의 소스 코드 분석
이 편 이 list 의 내용 을 말 하 는 이 유 는 다른 코드 를 분석 하기 위해 서 입 니 다. list 는 FreeRTOS 의 체인 데이터 구조 이 고 많은 변 수 는 이런 데이터 구 조 를 사용 합 니 다. 예 를 들 어 Ready 퀘 스 트 표, pending 퀘 스 트 표 와 delayd 퀘 스 트 표 등 입 니 다.이런 데이터 구 조 는 FreeRTOS 에서 광범 위 하 게 사용 되 기 때문에 여기 서 먼저 이러한 데이터 구조의 구성 과 실현 원 리 를 분석한다.
list.h
먼저 list. h 이 파일 을 보 세 요. 이 파일 은 시작 하 자마자 매크로 정의 가 있 습 니 다.
#ifndef configLIST_VOLATILE
    #define configLIST_VOLATILE
#endif /* configSUPPORT_CROSS_MODULE_OPTIMISATION */

여 기 는 판단 configLISTVOLATILE 가 정의 되 었 는 지, 없 으 면 비어 있 는 지, Demo 는 기본적으로 정의 되 지 않 았 기 때문에 뒤에 이 매크로 가 나 올 때 아무것도 하지 않 습 니 다.이 매크로 는 정의 되면 일반적으로 정의 된다.
#define configLIST_VOLATILE     volatile

그 다음 에 또 하나의 큰 매크로 정의 입 니 다.
#if( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 0 )
    /* Define the macros to do nothing. */
    #define listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE
    #define listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE
    #define listFIRST_LIST_INTEGRITY_CHECK_VALUE
    #define listSECOND_LIST_INTEGRITY_CHECK_VALUE
    #define listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem )
    #define listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem )
    #define listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList )
    #define listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList )
    #define listTEST_LIST_ITEM_INTEGRITY( pxItem )
    #define listTEST_LIST_INTEGRITY( pxList )
#else
    /* Define macros that add new members into the list structures. */
    #define listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE               TickType_t xListItemIntegrityValue1;
    #define listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE              TickType_t xListItemIntegrityValue2;
    #define listFIRST_LIST_INTEGRITY_CHECK_VALUE                    TickType_t xListIntegrityValue1;
    #define listSECOND_LIST_INTEGRITY_CHECK_VALUE                   TickType_t xListIntegrityValue2;

    /* Define macros that set the new structure members to known values. */
    #define listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem )     ( pxItem )->xListItemIntegrityValue1 = pdINTEGRITY_CHECK_VALUE
    #define listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem )    ( pxItem )->xListItemIntegrityValue2 = pdINTEGRITY_CHECK_VALUE
    #define listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList )      ( pxList )->xListIntegrityValue1 = pdINTEGRITY_CHECK_VALUE
    #define listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList )      ( pxList )->xListIntegrityValue2 = pdINTEGRITY_CHECK_VALUE

    /* Define macros that will assert if one of the structure members does not
    contain its expected value. */
    #define listTEST_LIST_ITEM_INTEGRITY( pxItem )      configASSERT( ( ( pxItem )->xListItemIntegrityValue1 == pdINTEGRITY_CHECK_VALUE ) && ( ( pxItem )->xListItemIntegrityValue2 == pdINTEGRITY_CHECK_VALUE ) )
    #define listTEST_LIST_INTEGRITY( pxList )           configASSERT( ( ( pxList )->xListIntegrityValue1 == pdINTEGRITY_CHECK_VALUE ) && ( ( pxList )->xListIntegrityValue2 == pdINTEGRITY_CHECK_VALUE ) )
#endif /* configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES */

configUSE 때문에LIST_DATA_INTEGRITY_CHECK_BYTES 는 Demo 에서 도 기본적으로 0 으로 설정 되 어 있 습 니 다. 그러면 실제 이 일련의 홍 도 는 비어 있 고 효과 가 없습니다.간단하게 보기 위해 서 는 기본 설정 을 사용 합 니 다. 먼저 이러한 각종 Check 매크로 를 상관 하지 않 고 나중에 익숙해 진 후에 필요 할 때 분석 하면 됩 니 다.
/*
 * Definition of the only type of object that a list can contain.
 */
struct xLIST_ITEM
{
    listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE           /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
    configLIST_VOLATILE TickType_t xItemValue;          /*< The value being listed.  In most cases this is used to sort the list in descending order. */
    struct xLIST_ITEM * configLIST_VOLATILE pxNext;     /*< Pointer to the next ListItem_t in the list. */
    struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; /*< Pointer to the previous ListItem_t in the list. */
    void * pvOwner;                                     /*< Pointer to the object (normally a TCB) that contains the list item.  There is therefore a two way link between the object containing the list item and the list item itself. */
    void * configLIST_VOLATILE pvContainer;             /*< Pointer to the list in which this list item is placed (if any). */
    listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE          /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
};
typedef struct xLIST_ITEM ListItem_t;                   /* For some reason lint wants this as two separate definitions. */

다음은 xlistITEM 이라는 데이터 형식 은 구조 체 로 정의 되 었 습 니 다. 맨 위 에 있 는 한 마디 를 주의 하 십시오. 이 데이터 형식 은 list 데이터 구조 에 유일 하 게 존재 하 는 유형 입 니 다.시작 과 끝 에 있 는 홍 정 이 앞에서 비 었 다 고 말 하고 무시 하고 그 안에 있 는 configLISTVOLATILE 도 비어 있 고 무시 할 수도 있 습 니 다.옆 에 있 는 영문 주석 을 통 해 알 수 있 듯 이 첫 번 째 멤버 인 xItemValue 는 이 Item 의 값 을 대표 합 니 다. 보통 이 Item 이 list 에 있 는 위 치 는 이 값 으로 정렬 됩 니 다.Delayed TaskList 를 예 로 들 면, 이 list 에서, 모든 Item 은 지 연 된 작업 의 제어 블록 에 대응 하 는 Item, 그 Item 을 대표 합 니 다.Value 는 delay 의 값 을 대표 합 니 다. tick 단위 입 니 다.이 list 는 이 Delay 값 을 내림차 순 으로 배열 합 니 다. 작은 것 일수 록 뒤에 있 습 니 다.pxNext 와 pxPrevious 는 모두 Item 의 지침 입 니 다. 이름 을 보면 같은 list 에서 다음 Item 을 가리 키 는 지침 과 이전 Item 을 가리 키 는 지침 을 알 수 있 습 니 다.pvOwner 는 이 Item 이 대표 하 는 목 표를 역방향 으로 가리 키 는 것 입 니 다. 예 를 들 어 작업 제어 블록 (TCB) 입 니 다.마지막 pvContainer 는 이 아 이 템 이 있 는 list 를 가리 키 고 있 습 니 다.
struct xMINI_LIST_ITEM
{
    listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE           /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
    configLIST_VOLATILE TickType_t xItemValue;
    struct xLIST_ITEM * configLIST_VOLATILE pxNext;
    struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;
};
typedef struct xMINI_LIST_ITEM MiniListItem_t;

이 미니 아 이 템 은 사실 간단 한 아 이 템 입 니 다. pvOwner 와 pvContainer 를 제거 하고 보통 list 에 사용 되 는 마지막 특별한 아 이 템 입 니 다.
typedef struct xLIST
{
    listFIRST_LIST_INTEGRITY_CHECK_VALUE                /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
    configLIST_VOLATILE UBaseType_t uxNumberOfItems;
    ListItem_t * configLIST_VOLATILE pxIndex;           /*< Used to walk through the list.  Points to the last item returned by a call to listGET_OWNER_OF_NEXT_ENTRY (). */
    MiniListItem_t xListEnd;                            /*< List item that contains the maximum possible item value meaning it is always at the end of the list and is therefore used as a marker. */
    listSECOND_LIST_INTEGRITY_CHECK_VALUE               /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
} List_t;

다시 말 하면 list 의 구조 체 정의 입 니 다. 똑 같이 잘못된 매크로 를 제거 한 후에 세 명의 구성원 만 있 습 니 다. uxNumberOfItems 는 이 list 의 모든 Item 의 수량 (list 의 마지막 특수 한 Item 은 포함 되 지 않 습 니 다) 을 대표 합 니 다.px Index 는 list 이 목록 에 있 는 현재 Item 을 가리 키 며, 배열 의 아래 표 에 해당 합 니 다.xListend 는 MiniItem, 이것 은 모든 list 에 있 는 특수 한 Item 이 며, 항상 list 와 의 끝 이 존재 하 며, 이 endItem 의 다음 next Item 은 list 의 첫 번 째 Item 을 가리 키 며, 이렇게 하여 하나의 링 list 를 형성 합 니 다.
list. h 파일 아래 에 있 는 것 은 함수 설명 을 제외 하고 일련의 매크로 로 이 루어 진 기능 함수 입 니 다. 이런 함수 들 은 비교적 간단 하고 매크로 로 이 루어 지 는 것 도 쉬 우 며 함수 보다 빨리 실 행 됩 니 다.위 에 있 는 모든 것 은 영어 로 주석 을 쓰 는데, 여 기 는 기본적으로 간단하게 번역 하면 알 수 있다.
#define listSET_LIST_ITEM_OWNER( pxListItem, pxOwner )      ( ( pxListItem )->pvOwner = ( void * ) ( pxOwner ) )
#define listGET_LIST_ITEM_OWNER( pxListItem )   ( ( pxListItem )->pvOwner )

이 두 개의 매크로 중 하 나 는 Item 의 소속 Owner 를 설정 하 는 데 사 용 됩 니 다. 전에 도 말 했 듯 이 특정한 작업 제어 블록 TCB 를 말 합 니 다.또 하 나 는 이름 만 봐 도 아 이 템 이 소 속 된 Owner 지침 을 거꾸로 받 았 다 는 것 을 알 수 있다.
#define listSET_LIST_ITEM_VALUE( pxListItem, xValue )   ( ( pxListItem )->xItemValue = ( xValue ) )
#define listGET_LIST_ITEM_VALUE( pxListItem )   ( ( pxListItem )->xItemValue )

이 두 개의 매크로 중 하 나 는 Item 의 xItemValue 값 을 설정 하고 하 나 는 이 값 을 가 져 옵 니 다.
#define listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxList )  ( ( ( pxList )->xListEnd ).pxNext->xItemValue )
#define listGET_HEAD_ENTRY( pxList )    ( ( ( pxList )->xListEnd ).pxNext )

이 두 개의 매크로, 아래 의 것 은 list 의 첫 번 째 아 이 템 을 가 져 오 는 것 입 니 다. 위 에 있 는 것 은 이 첫 번 째 아 이 템 에 대응 하 는 Value 값 을 가 져 오 는 것 입 니 다. 실현 방법 은 간단 합 니 다. list 의 끝 에 있 는 특수 한 아 이 템 의 다음 을 가 져 오 는 것 입 니 다. 앞에서 도 말 했 듯 이 꼬리 에 있 는 특수 한 아 이 템 의 다음 은 list 의 첫 번 째 를 가리 키 는 것 입 니 다.
#define listGET_NEXT( pxListItem )  ( ( pxListItem )->pxNext )
#define listGET_END_MARKER( pxList )    ( ( ListItem_t const * ) ( &( ( pxList )->xListEnd ) ) )
#define listLIST_IS_EMPTY( pxList ) ( ( BaseType_t ) ( ( pxList )->uxNumberOfItems == ( UBaseType_t ) 0 ) )
#define listCURRENT_LIST_LENGTH( pxList )   ( ( pxList )->uxNumberOfItems )

이 몇 개의 매크로 기능 은 이름 을 봐 도 알 수 있 습 니 다. 실현 도 매우 간단 합 니 다. 각각 Item 의 다음 지향, list 의 끝 특수 Item, list 의 uxNumberOfItems 가 0 인지 여 부 를 통 해 list 가 비어 있 는 지 판단 합 니 다 (주의, 모든 list 는 하나의 끝 특수 Item 을 포함 하고 있 습 니 다. 이것 은 이 Number 에 포함 되 지 않 습 니 다). 그리고 이 Number 값 을 얻 습 니 다.
#define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList )                                        \
{                                                                                           \
List_t * const pxConstList = ( pxList );                                                    \
    /* Increment the index to the next item and return the item, ensuring */                \
    /* we don't return the marker used at the end of the list.  */                          \
    ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext;                            \
    if( ( void * ) ( pxConstList )->pxIndex == ( void * ) &( ( pxConstList )->xListEnd ) )  \
    {                                                                                       \
        ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext;                        \
    }                                                                                       \
    ( pxTCB ) = ( pxConstList )->pxIndex->pvOwner;                                          \
}

이 매크로 는 조금 복잡 합 니 다. list 의 다음 Item 을 가 져 오고 이 Item 이 가리 키 는 Owner 를 매개 변수 pxTCB 에 할당 해 야 합 니 다. 즉, 이 매크로 의 주요 역할 은 list 의 다음 Item 에 속 하 는 TCB 를 가 져 오 는 동시에 Index 에 값 을 다시 부여 하 는 것 입 니 다.구현 코드 를 보면 알 수 있 습 니 다. list 구성원 Index 의 다음 지향 은 list 의 다음 Item 입 니 다. 이 매크로 함 수 를 호출 하여 다음 Item 을 가 져 올 때 Index 를 다음 지향 으로 다시 할당 한 다음 에 이 새로운 지향 이 list 의 끝 에 있 는 특수 Item 인지 판단 합 니 다. 그렇다면 다음 지향 으로 다시 할당 합 니 다.이 때 얻 는 것 은 list 의 첫 번 째 아 이 템 입 니 다.그리고 이 Item 에 대응 하 는 Owner 를 매개 변수 pxTCB 에 할당 합 니 다.
#define listGET_OWNER_OF_HEAD_ENTRY( pxList )  ( (&( ( pxList )->xListEnd ))->pxNext->pvOwner )
#define listIS_CONTAINED_WITHIN( pxList, pxListItem ) ( ( BaseType_t ) ( ( pxListItem )->pvContainer == ( void * ) ( pxList ) ) )
#define listLIST_ITEM_CONTAINER( pxListItem ) ( ( pxListItem )->pvContainer )
#define listLIST_IS_INITIALISED( pxList ) ( ( pxList )->xListEnd.xItemValue == portMAX_DELAY )

나머지 네 개의 매크로 도 간단 한 실현 입 니 다. 이름 을 봐 도 용 도 를 알 수 있 습 니 다. 쉽게 말 하면 list 를 얻 은 첫 번 째 Item 의 소속 (TCB) 입 니 다. Item 이 지정 한 list 에 있 는 지, Item 이 있 는 list 와 list 가 초기 화 되 었 는 지 여 부 를 지정 합 니 다.(이 판단 은 list 의 끝 에 있 는 특수 Item 의 value 가 portMAX DELAY 인지 확인 하 는 것 입 니 다. 이것 은 list 가 초기 화 될 때 지정 합 니 다. 그렇지 않 으 면 보통 0 입 니 다.)
다음 몇 줄 은 list. c 에서 정의 한 몇 가지 실현 함수 의 설명 입 니 다. 이것 은 다음 분석 입 니 다.

좋은 웹페이지 즐겨찾기