freeRTOS源碼解析4--tasks.c 6

来源:https://www.cnblogs.com/freeManX1807/p/18436676
-Advertisement-
Play Games

#版本信息: NAME="openEuler"VERSION="22.03 (LTS-SP4)" #網卡信息: cat /etc/sysconfig/network-scripts/ifcfg-enp125s0f1TYPE=EthernetPROXY_METHOD=noneBROWSER_ONLY= ...


4.2.14 退出阻塞--xTaskAbortDelay

介面:
BaseType_t xTaskAbortDelay( TaskHandle_t xTask )
形參1:xTask ,想要退出阻塞態的任務;
返回:pdPASS:退出成功;pdFAIL:退出失敗。

 1 BaseType_t xTaskAbortDelay( TaskHandle_t xTask )
 2 {
 3     TCB_t * pxTCB = xTask;
 4     BaseType_t xReturn;
 5 
 6     configASSERT( pxTCB );
 7 
 8     vTaskSuspendAll();
 9     {
10         /* A task can only be prematurely removed from the Blocked state if
11          * it is actually in the Blocked state. */
12         /* 任務只有真的在阻塞態才能提前移出阻塞態 */
13         if( eTaskGetState( xTask ) == eBlocked )
14         {
15             xReturn = pdPASS;
16 
17             /* Remove the reference to the task from the blocked list.  An
18              * interrupt won't touch the xStateListItem because the
19              * scheduler is suspended. */
20             ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
21 
22             /* Is the task waiting on an event also?  If so remove it from
23              * the event list too.  Interrupts can touch the event list item,
24              * even though the scheduler is suspended, so a critical section
25              * is used. */
26             /* 如果任務在等待事件, 則移出事件列表, 因為調度器暫停時, 中斷仍
27              * 能訪問事件列表, 所以需要進入臨界區 */
28             taskENTER_CRITICAL();
29             {
30                 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
31                 {
32                     ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
33 
34                     /* This lets the task know it was forcibly removed from the
35                      * blocked state so it should not re-evaluate its block time and
36                      * then block again. */
37                     /* 讓任務知道是被強制移出阻塞態的, 防止被重新計算阻塞時間再次進入
38                      * 阻塞態 */
39                     pxTCB->ucDelayAborted = ( uint8_t ) pdTRUE;
40                 }
41                 else
42                 {
43                     mtCOVERAGE_TEST_MARKER();
44                 }
45             }
46             taskEXIT_CRITICAL();
47 
48             /* Place the unblocked task into the appropriate ready list. */
49             prvAddTaskToReadyList( pxTCB );
50 
51             /* A task being unblocked cannot cause an immediate context
52              * switch if preemption is turned off. */
53             #if ( configUSE_PREEMPTION == 1 )
54             {
55                 #if ( configNUMBER_OF_CORES == 1 )
56                 {
57                     /* Preemption is on, but a context switch should only be
58                      * performed if the unblocked task has a priority that is
59                      * higher than the currently executing task. */
60                     /* 比當前任務優先順序高, 等調度器運行後, 需要進行yield */
61                     if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
62                     {
63                         /* Pend the yield to be performed when the scheduler
64                          * is unsuspended. */
65                         xYieldPendings[ 0 ] = pdTRUE;
66                     }
67                     else
68                     {
69                         mtCOVERAGE_TEST_MARKER();
70                     }
71                 }
72                 #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
73             }
74             #endif /* #if ( configUSE_PREEMPTION == 1 ) */
75         }
76         else
77         {
78             xReturn = pdFAIL;
79         }
80     }
81     ( void ) xTaskResumeAll();
82 
83     return xReturn;
84 }
xTaskAbortDelay

 這個介面主要就是強制將在阻塞態的任務變成就緒態。

4.2.15 系統滴答時鐘處理--xTaskIncrementTick

介面:
BaseType_t xTaskIncrementTick( void )
返回:pdPASS:需要切換上下文;pdFAIL:不需要切換上下文。
介面代碼如下:

  1 BaseType_t xTaskIncrementTick( void )
  2 {
  3     TCB_t * pxTCB;
  4     TickType_t xItemValue;
  5     BaseType_t xSwitchRequired = pdFALSE;
  6 
  7     /* Tick increment should occur on every kernel timer event. Core 0 has the
  8      * responsibility to increment the tick, or increment the pended ticks if the
  9      * scheduler is suspended.  If pended ticks is greater than zero, the core that
 10      * calls xTaskResumeAll has the responsibility to increment the tick. */
 11     if( uxSchedulerSuspended == ( UBaseType_t ) 0U )
 12     {
 13         /* Minor optimisation.  The tick count cannot change in this
 14          * block. */
 15         const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1;
 16 
 17         /* Increment the RTOS tick, switching the delayed and overflowed
 18          * delayed lists if it wraps to 0. */
 19         xTickCount = xConstTickCount;
 20 
 21         /* tick溢出了, 交換下delay列表 */
 22         if( xConstTickCount == ( TickType_t ) 0U )
 23         {
 24             taskSWITCH_DELAYED_LISTS();
 25         }
 26         else
 27         {
 28             mtCOVERAGE_TEST_MARKER();
 29         }
 30 
 31         /* See if this tick has made a timeout expire.  Tasks are stored in
 32          * the  queue in the order of their wake time - meaning once one task
 33          * has been found whose block time has not expired there is no need to
 34          * look any further down the list. */
 35         /* 因為delay列表的項是按喚醒時間從小到大排序的, 所以遍歷過程中一旦發現
 36          * 任務喚醒時間沒到, 就可以停止了 */
 37         if( xConstTickCount >= xNextTaskUnblockTime )
 38         {
 39             for( ; ; )
 40             {
 41                 if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
 42                 {
 43                     /* The delayed list is empty.  Set xNextTaskUnblockTime
 44                      * to the maximum possible value so it is extremely
 45                      * unlikely that the
 46                      * if( xTickCount >= xNextTaskUnblockTime ) test will pass
 47                      * next time through. */
 48                     xNextTaskUnblockTime = portMAX_DELAY;
 49                     break;
 50                 }
 51                 else
 52                 {
 53                     /* The delayed list is not empty, get the value of the
 54                      * item at the head of the delayed list.  This is the time
 55                      * at which the task at the head of the delayed list must
 56                      * be removed from the Blocked state. */
 57                     /* MISRA Ref 11.5.3 [Void pointer assignment] */
 58                     /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
 59                     /* coverity[misra_c_2012_rule_11_5_violation] */
 60                     pxTCB = listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );
 61                     xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xStateListItem ) );
 62 
 63                     if( xConstTickCount < xItemValue )
 64                     {
 65                         /* It is not time to unblock this item yet, but the
 66                          * item value is the time at which the task at the head
 67                          * of the blocked list must be removed from the Blocked
 68                          * state -  so record the item value in
 69                          * xNextTaskUnblockTime. */
 70                         /* 這個任務未到喚醒時間, 但因為前面的都移出了, 所以這一定
 71                          * 是下次最近喚醒的時間, 記錄下來 */
 72                         xNextTaskUnblockTime = xItemValue;
 73                         break;
 74                     }
 75                     else
 76                     {
 77                         mtCOVERAGE_TEST_MARKER();
 78                     }
 79 
 80                     /* It is time to remove the item from the Blocked state. */
 81                     listREMOVE_ITEM( &( pxTCB->xStateListItem ) );
 82 
 83                     /* Is the task waiting on an event also?  If so remove
 84                      * it from the event list. */
 85                     /* 等待事件的話, 移出事件列表 */
 86                     if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
 87                     {
 88                         listREMOVE_ITEM( &( pxTCB->xEventListItem ) );
 89                     }
 90                     else
 91                     {
 92                         mtCOVERAGE_TEST_MARKER();
 93                     }
 94 
 95                     /* Place the unblocked task into the appropriate ready
 96                      * list. */
 97                     prvAddTaskToReadyList( pxTCB );
 98 
 99                     /* A task being unblocked cannot cause an immediate
100                      * context switch if preemption is turned off. */
101                     #if ( configUSE_PREEMPTION == 1 )
102                     {
103                         #if ( configNUMBER_OF_CORES == 1 )
104                         {
105                             /* Preemption is on, but a context switch should
106                              * only be performed if the unblocked task's
107                              * priority is higher than the currently executing
108                              * task.
109                              * The case of equal priority tasks sharing
110                              * processing time (which happens when both
111                              * preemption and time slicing are on) is
112                              * handled below.*/
113                             /* 移出的任務優先順序比當前運行的任務高, 需要上下文切換 */
114                             if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
115                             {
116                                 xSwitchRequired = pdTRUE;
117                             }
118                             else
119                             {
120                                 mtCOVERAGE_TEST_MARKER();
121                             }
122                         }
123                         #endif /* #if( configNUMBER_OF_CORES == 1 ) */
124                     }
125                     #endif /* #if ( configUSE_PREEMPTION == 1 ) */
126                 }
127             }
128         }
129 
130         /* Tasks of equal priority to the currently running task will share
131          * processing time (time slice) if preemption is on, and the application
132          * writer has not explicitly turned time slicing off. */
133         /* 相同優先順序的任務用時間片運行, 每個時間片長是一個tick. 這裡不用管更高
134          * 優先順序的任務是否喚醒, 一是上面已經判斷過了, 二是只是需要知道是否要上
135          * 下文切換, 這樣判斷就足夠了, 在上下文切換的時候自然會選擇合適的任務運行 */
136         #if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) )
137         {
138             #if ( configNUMBER_OF_CORES == 1 )
139             {
140                 if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB->uxPriority ] ) ) > 1U )
141                 {
142                     xSwitchRequired = pdTRUE;
143                 }
144                 else
145                 {
146                     mtCOVERAGE_TEST_MARKER();
147                 }
148             }
149             #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
150         }
151         #endif /* #if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) */
152 
153         #if ( configUSE_TICK_HOOK == 1 )
154         {
155             /* Guard against the tick hook being called when the pended tick
156              * count is being unwound (when the scheduler is being unlocked). */
157             if( xPendedTicks == ( TickType_t ) 0 )
158             {
159                 vApplicationTickHook();
160             }
161             else
162             {
163                 mtCOVERAGE_TEST_MARKER();
164             }
165         }
166         #endif /* configUSE_TICK_HOOK */
167 
168         #if ( configUSE_PREEMPTION == 1 )
169         {
170             #if ( configNUMBER_OF_CORES == 1 )
171             {
172                 /* For single core the core ID is always 0. */
173                 if( xYieldPendings[ 0 ] != pdFALSE )
174                 {
175                     xSwitchRequired = pdTRUE;
176                 }
177                 else
178                 {
179                     mtCOVERAGE_TEST_MARKER();
180                 }
181             }
182             #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
183         }
184         #endif /* #if ( configUSE_PREEMPTION == 1 ) */
185     }
186     else
187     {
188         /* 調度器處於暫停中, 在xTaskResumeAll介面中檢查xPendedTicks的值,
189          * 並調用本介面處理tick值. */
190         xPendedTicks += 1U;
191 
192         /* The tick hook gets called at regular intervals, even if the
193          * scheduler is locked. */
194         #if ( configUSE_TICK_HOOK == 1 )
195         {
196             vApplicationTickHook();
197         }
198         #endif
199     }
200 
201     return xSwitchRequired;
202 }
xTaskIncrementTick

   介面比較複雜,流程圖就不貼了,太長。這個介面簡單來講就是如果調度器未停止,就檢查每個阻塞的任務是否到了等待時間,包括本身延遲的時間和等待事件的超時時間,並加入到就緒列表中。

 

4.2.16 切換上下文--vTaskSwitchContext

切換上下文,主要作用是挑選出需要切換過去的任務。
介面:
void vTaskSwitchContext( void )
介面代碼如下:

 1 void vTaskSwitchContext( void )
 2 {
 3     if( uxSchedulerSuspended != ( UBaseType_t ) 0U )
 4     {
 5         /* The scheduler is currently suspended - do not allow a context
 6          * switch. */
 7         /* 調度器暫停時, 不允許上下文切換 */
 8         xYieldPendings[ 0 ] = pdTRUE;
 9     }
10     else
11     {
12         xYieldPendings[ 0 ] = pdFALSE;
13 
14         /* Check for stack overflow, if configured. */
15         /* 就是檢查當前棧的位置有沒有超過棧頂位置 */
16         taskCHECK_FOR_STACK_OVERFLOW();
17 
18         /* Before the currently running task is switched out, save its errno. */
19         #if ( configUSE_POSIX_ERRNO == 1 )
20         {
21             pxCurrentTCB->iTaskErrno = FreeRTOS_errno;
22         }
23         #endif
24 
25         /* Select a new task to run using either the generic C or port
26          * optimised asm code. */
27         /* MISRA Ref 11.5.3 [Void pointer assignment] */
28         /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
29         /* coverity[misra_c_2012_rule_11_5_violation] */
30         /* 選擇就緒列表中優先順序最高的任務 */
31         taskSELECT_HIGHEST_PRIORITY_TASK();
32 
33         /* Macro to inject port specific behaviour immediately after
34          * switching tasks, such as setting an end of stack watchpoint
35          * or reconfiguring the MPU. */
36         portTASK_SWITCH_HOOK( pxCurrentTCB );
37 
38         /* After the new task is switched in, update the global errno. */
39         #if ( configUSE_POSIX_ERRNO == 1 )
40         {
41             FreeRTOS_errno = pxCurrentTCB->iTaskErrno;
42         }
43         #endif
44     }
45 }
vTaskSwitchContext

  最核心的就是“taskSELECT_HIGHEST_PRIORITY_TASK();”調用。

  4.2.17 加入到事件列表--vTaskPlaceOnEventList

把當前任務放到事件列表中,主要用於隊列的實現。
介面:
void vTaskPlaceOnEventList( List_t * const pxEventList, const TickType_t xTicksToWait )
形參1:pxEventList,事件列表;
形參2:xTicksToWait ,最長等待時間。
介面代碼如下:

 1 void vTaskPlaceOnEventList( List_t * const pxEventList,
 2                             const TickType_t xTicksToWait )
 3 {
 4     configASSERT( pxEventList );
 5 
 6     /* THIS FUNCTION MUST BE CALLED WITH THE
 7      * SCHEDULER SUSPENDED AND THE QUEUE BEING ACCESSED LOCKED. */
 8 
 9     /* Place the event list item of the TCB in the appropriate event list.
10      * This is placed in the list in priority order so the highest priority task
11      * is the first to be woken by the event.
12      *
13      * Note: Lists are sorted in ascending order by ListItem_t.xItemValue.
14      * Normally, the xItemValue of a TCB's ListItem_t members is:
15      *      xItemValue = ( configMAX_PRIORITIES - uxPriority )
16      * Therefore, the event list is sorted in descending priority order.
17      *
18      * The queue that contains the event list is locked, preventing
19      * simultaneous access from interrupts. */
20     /* 將當前任務加入到事件列表, 列表是按升序存放的, 而一般情況下, 任務的
21      * xEventListItem的值是xItemValue=(configMAX_PRIORITIES-uxPriority),
22      * 所以事件列表是按優先順序降序排列的 */
23     vListInsert( pxEventList, &( pxCurrentTCB->xEventListItem ) );
24 
25     /* 還需要放到延遲列表中, 用於最大延遲時間的喚醒 */
26     prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
27 }
vTaskPlaceOnEventList

  4.2.18 加入到無序事件列表--vTaskPlaceOnUnorderedEventList

把當前任務放到無序的事件列表中,主要用於事件組。
介面:
void vTaskPlaceOnUnorderedEventList( List_t * pxEventList,const TickType_t xItemValue, const TickType_t xTicksToWait )
形參1:pxEventList,事件列表;
形參2:xItemValue,設置的值
形參3:xTicksToWait ,最長等待時間。
介面代碼如下:

 1 void vTaskPlaceOnUnorderedEventList( List_t * pxEventList,
 2                                      const TickType_t xItemValue,
 3                                      const TickType_t xTicksToWait )
 4 {
 5     configASSERT( pxEventList );
 6 
 7     /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED.  It is used by
 8      * the event groups implementation. */
 9     configASSERT( uxSchedulerSuspended != ( UBaseType_t ) 0U );
10 
11     /* Store the item value in the event list item.  It is safe to access the
12      * event list item here as interrupts won't access the event list item of a
13      * task that is not in the Blocked state. */
14     /* 中斷只會訪問處於Blocked態的事件列表項, 這裡當前任務明顯還未進入Blocked態 */
15     listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ), xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE );
16 
17     /* Place the event list item of the TCB at the end of the appropriate event
18      * list.  It is safe to access the event list here because it is part of an
19      * event group implementation - and interrupts don't access event groups
20      * directly (instead they access them indirectly by pending function calls to
21      * the task level). */
22     /* 主要是用於事件組的實現, 中斷不會直接訪問. 無序存放, 所以直接放在最後 */
23     listINSERT_END( pxEventList, &( pxCurrentTCB->xEventListItem ) );
24 
25     prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
26 }
vTaskPlaceOnUnorderedEventList

  4.2.19 移出事件列表--xTaskRemoveFromEventList

將當前任務從事件列表中移出,主要用於隊列的實現。
介面:
BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList )
形參1:pxEventList,事件列表;
返回值:pdTRUE:需要進行上下文切換;pdFALSE:不需要。
介面代碼如下:

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • 本文是筆者研究生期間在閱讀《Linux命令行與shell腳本編程大全》之後總結出來的一些重點知識的記錄,在此重新整理輸出。以便在給上個帖子 涉及到的相關知識點進行一下講解,幫助自己複習 shell腳本的首行規範化應該是 #!/bin/bash # function description 其中第一行 ...
  • crontab -e 創建的定時任務使用的是系統時間。 什麼是系統時間? 系統時間是操作系統內部維護的一個時間戳,用於記錄系統啟動以來經過的時間,以及當前的日期和時間。 系統時間通常與硬體時鐘同步,以確保時間的準確性。 crontab 如何使用系統時間? crontab 在執行定時任務時,會根據系統 ...
  • shc介紹 shc是shell編譯器(Shell Compiler)的縮寫, 它可以對shell腳本進行編譯和加密。它能夠將shell腳本編譯為可執行的二進位文件,其中包含了腳本的功能和邏輯,而不暴露源代碼。可以說shc就是一個加密shell腳本的工具。shc的官方網址為:http://www.da ...
  • 在Linux伺服器的管理和維護過程中,掌握一些常用的命令是非常必要的。這些命令不僅可以幫助你更好地瞭解和控制系統,還能提高工作效率,減少錯誤發生的概率。本文將詳細介紹一些在Linux伺服器上常用的命令,覆蓋從基本的文件操作到高級的系統管理,力求內容全面,幫助讀者深入理解每一個命令的用法和原理。 一、 ...
  • 802.11 無線 WiFi 有 數據幀,管理幀、控制幀 三種類型幀。這些幀由 9 個部分組成:Frame Control,Duration ID,Address1,Address2,Address3,Seq-ctl,Address4,Frame Body,FCS。需要註意的是,有些組成部分在有些幀... ...
  • 位操作符: 可以直接操作二進位數位的內容;~是一個單目位操作符,它可以根據一個數字計算另外一個數字,這兩個數字所有二進位數位的內容都不同(按位取反),使用的時候這個符號應該寫在數字前面 雙目位操作符:包括按位與(&),按位或(|)以及按位異或(^),他們都可以把兩個數字對應二進位數位的內容做計算。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...