建立网站可以赚钱吗,域名购买是什么意思,江苏丹阳建设公司网站,wordpress问卷调查目录 一、什么是任务
二、创建任务---xTaskCreate函数
三、任务的删除 四、任务优先级 1.阻塞状态(Blocked)
2.暂停状态(Suspended)
3.就绪状态(Ready)
五、Delay
六、调度算法 一、什么是任务
在FreeRTOS中#xff0c;任务就是一个函数#xff0c;原型如下#xff…目录 一、什么是任务
二、创建任务---xTaskCreate函数
三、任务的删除 四、任务优先级 1.阻塞状态(Blocked)
2.暂停状态(Suspended)
3.就绪状态(Ready)
五、Delay
六、调度算法 一、什么是任务
在FreeRTOS中任务就是一个函数原型如下
void ATaskFunction( void *pvParameters );
要注意的是 这个函数不能返回 同一个函数可以用来创建多个任务换句话说多个任务可以运行同一个函数 函数内部尽量使用局部变量 每个任务都有自己的栈 每个任务运行这个函数时 任务A的局部变量放在任务A的栈里、任务B的局部变量放在任务B的栈里 不同任务的局部变量有自己的副本 任务示例如下
void ATaskFunction( void *pvParameters )
{
/* 对于不同的任务局部变量放在任务的栈里有各自的副本 */
int32_t lVariableExample 0;
/* 任务函数通常实现为一个无限循环 */
for( ;; )
{
/* 任务的代码 */
}
/* 如果程序从循环中退出一定要使用vTaskDelete删除自己
* NULL表示删除的是自己
*/
vTaskDelete( NULL );
/* 程序不会执行到这里, 如果执行到这里就出错了 */
}
二、创建任务---xTaskCreate函数
BaseType_t xTaskCreate( TaskFunction_t pxTaskCode, // 函数指针, 任务函数
const char * const pcName, // 任务的名字
const configSTACK_DEPTH_TYPE usStackDepth, // 栈大小,单位为word,10表示40字节
void * const pvParameters, // 调用任务函数时传入的参数
UBaseType_t uxPriority, // 优先级
TaskHandle_t * const pxCreatedTask ); // 任务句柄, 以后使用它来操作这个任务
参数描述 pvTaskCode 函数指针可以简单地认为任务就是一个C函数。 它稍微特殊一点永远不退出或者退出时要调用vTaskDelete(NULL) pcName 任务的名字FreeRTOS内部不使用它仅仅起调试作用。 长度为configMAX_TASK_NAME_LEN usStackDepth 每个任务都有自己的栈这里指定栈大小。 单位是word比如传入100表示栈大小为100 word也就是400字节。 最大值为uint16_t的最大值。 怎么确定栈的大小并不容易很多时候是估计。 精确的办法是看反汇编码。 pvParameters 调用pvTaskCode函数指针时用到pvTaskCode(pvParameters) uxPriority 优先级范围0~(configMAX_PRIORITIES – 1) 数值越小优先级越低更高优先级的、或者后面创建的任务先运行。 如果传入过大的值xTaskCreate会把它调整为(configMAX_PRIORITIES – 1) pxCreatedTask 用来保存xTaskCreate的输出结果task handle。 以后如果想操作这个任务比如修改它的优先级就需要这个handle。 如果不想使用该handle可以传入NULL。 返回值 成功pdPASS 失败errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY(失败原因只有内存不足) 注意返回值是pdFAIL不对。 pdFAIL是0errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY是-1。
多个任务可以使用同一个函数;
void vTaskFunction( void *pvParameters )
{const char *pcTaskText pvParameters;volatile uint32_t ul; /* volatile用来避免被优化掉 *//* 任务函数的主体一般都是无限循环 */for( ;; ){/* 打印任务的信息 */printf(pcTaskText);/* 延迟一会(比较简单粗暴) */for( ul 0; ul mainDELAY_LOOP_COUNT; ul ){}}
}
static const char *pcTextForTask1 T1 run\r\n;
static const char *pcTextForTask2 T2 run\r\n;
int main( void )
{prvSetupHardware();xTaskCreate(vTaskFunction, Task 1, 1000, (void *)pcTextForTask1, 1, NULL);xTaskCreate(vTaskFunction, Task 2, 1000, (void *)pcTextForTask2, 1, NULL);/* 启动调度器 */vTaskStartScheduler();/* 如果程序运行到了这里就表示出错了, 一般是内存不足 */return 0;
}
三、任务的删除 删除任务时使用的函数如下
void vTaskDelete( TaskHandle_t xTaskToDelete );
pvTaskCode 任务句柄使用xTaskCreate创建任务时可以得到一个句柄。 也可传入NULL这表示删除自己。 自杀 vTaskDelete(NULL) 被杀别的任务执行vTaskDelete(pvTaskCode) pvTaskCode是自己的句柄 杀人执行vTaskDelete(pvTaskCode) pvTaskCode是别的任务的句柄 FreeRTOS一天一个小知识之任务延时函数vTaskDelay-CSDN博客https://blog.csdn.net/simplemethane/article/details/116998825以下是这篇文章中谈到的延迟的内容 Dealy的延时是通过CPU做循环的方式来延时CPU在延时中是做不了其他东西的大大浪费了CPU的效率而且非常危险 所以大家在裸机中如果要需要很长时间延时的话建议用定时器来延时。
void vTaskDelay( const TickType_t xTicksToDelay ){BaseType_t xAlreadyYielded pdFALSE;/* A delay time of zero just forces a reschedule. */if( xTicksToDelay ( TickType_t ) 0U ){configASSERT( uxSchedulerSuspended 0 );vTaskSuspendAll();{traceTASK_DELAY();/* A task that is removed from the event list while the* scheduler is suspended will not get placed in the ready* list or removed from the blocked list until the scheduler* is resumed.** This task cannot be in an event list as it is the currently* executing task. */prvAddCurrentTaskToDelayedList( xTicksToDelay, pdFALSE );}xAlreadyYielded xTaskResumeAll();}else{mtCOVERAGE_TEST_MARKER();}/* Force a reschedule if xTaskResumeAll has not already done so, we may* have put ourselves to sleep. */if( xAlreadyYielded pdFALSE ){portYIELD_WITHIN_API();}else{mtCOVERAGE_TEST_MARKER();}}
FreeRTOS这个任务执行是这样的。首先TASK1创建然后在创建TASK2 TASK先执行 执行到GPIO_SetBits(GPIOC,GPIO_Pin_2); 下一句vTaskDelay(500); 延时500ms其实就是任务挂起500msCPU此时不会执行TASK的任务去执行处于就绪态的TASK2 当TASK2的GPIO_ResetBits(GPIOC,GPIO_Pin_3); 执行好了之后执行下一条 vTaskDelay(200);此时TASK1延时500msTASK延时200ms。 这时候FreeRTOS是没有执行处于就绪态的任务的只有执行空闲任务 。此时由于TASK2是延时200ms比TASK2延时的500ms要快所以TASK2比TASK1更早进入就绪态此时CPU执行 GPIO_SetBits(GPIOC,GPIO_Pin_3); 这一语句执行好了之后TASK2又延时800ms进入挂起态。当TASK1延时500ms到TASK1进入就绪态 执行GPIO_ResetBits(GPIOC,GPIO_Pin_2); i;语句执行完之后TASK1又进入500ms的延时进入挂起态~
【
任务堆栈 任务堆栈用来保存任务现场(CPU寄存器值)创建任务的时候需要指定任务堆栈任务堆栈的变量类型为StackType_t再次运行任务时会从上次中断的地方开始运行
】 所以在FreeRTOS中的延时函数只是任务挂起和任务恢复而已 //任务一
void vTask1( void *pvParameters )
{
const TickType_t xDelay100ms pdMS_TO_TICKS( 100UL );
BaseType_t ret;
/* 任务函数的主体一般都是无限循环 */
for( ;; )
{
/* 打印任务的信息 */
printf(Task1 is running\r\n);
ret xTaskCreate( vTask2, Task 2, 1000, NULL, 2, xTask2Handle );
if (ret ! pdPASS)
printf(Create Task2 Failed\r\n);
// 如果不休眠的话, Idle任务无法得到执行
// Idel任务会清理任务2使用的内存
// 如果不休眠则Idle任务无法执行, 最后内存耗尽
vTaskDelay( xDelay100ms );
}//任务二
void vTask2( void *pvParameters )
{
/* 打印任务的信息 */
printf(Task2 is running and about to delete itself\r\n);
// 可以直接传入参数NULL, 这里只是为了演示函数用法
vTaskDelete(xTask2Handle);
}//main函数
int main( void )
{
prvSetupHardware();
xTaskCreate(vTask1, Task 1, 1000, NULL, 1, NULL);
/* 启动调度器 */
vTaskStartScheduler();
/* 如果程序运行到了这里就表示出错了, 一般是内存不足 */
return 0;
} main函数中创建任务1优先级为1。任务1运行时它创建任务2任务2的优先级是2。
任务2的优先级最高它马上执行。
任务2打印一句话后就删除了自己。
任务2被删除后任务1的优先级最高轮到任务1继续运行它调用vTaskDelay() 进入Block状
态
任务1 Block期间轮到Idle任务执行它释放任务2的内存(TCB、栈)
时间到后任务1变为最高优先级的任务继续执行。
如此循环。 在任务1的函数中如果不调用vTaskDelay则Idle任务用于没有机会执行它就无法释放创建任务2是分配的内存。而任务1在不断地创建任务不断地消耗内存最终内存耗尽再也无法创建新的任务。 四、任务优先级 高优先级的任务先运行。 优先级的取值范围是0~(configMAX_PRIORITIES – 1)数值越大优先级越高。 FreeRTOS会确保最高优先级的、可运行的任务马上就能执行 对于相同优先级的、可运行的任务轮流执行 举例子 厨房着火了当然优先灭火 喂饭、回复信息同样重要轮流做
对于同优先级的任务它们“轮流”执行。怎么轮流你执行一会我执行一会。 一会怎么定义 人有心跳心跳间隔基本恒定。 FreeRTOS中也有心跳它使用定时器产生固定间隔的中断。这叫Tick、滴答比如每10ms发生一次时钟中断。
假设t1、t2、t3发生时钟中断 两次中断之间的时间被称为时间片(time slice、tick period) 时间片的长度由configTICK_RATE_HZ 决定假设configTICK_RATE_HZ为100那么时间片长度就是10ms 相同优先级的任务怎么切换呢请看下图 任务2从t1执行到t2 在t2发生tick中断进入tick中断处理函数 选择下一个要运行的任务 执行完中断处理函数后切换到新的任务任务1 任务1从t2执行到t3 从图中可以看出任务运行的时间并不是严格从t1,t2,t3哪里开始 在FreeRTOS中系统时钟节拍的特点就是周期性中断既然要产生中断那就需要定时器所以在这里就是使用了一个24位的定时器采用向下计数的方式然后可以产生周期性的中断。 系统在使用的时候一般是在FreeRTOSConfig.h里面进行配置 #define configTICK_RATE_HZ ( ( TickType_t ) 1000 ) 这是一个常用的配置系统的节拍频率设置为1000也就是说系统的节拍周期为1ms这也是最为典型的一种设置。
vTaskDelay(2); // 等待2个Tick假设configTICK_RATE_HZ100, Tick周期时10ms, 等待20ms
// 还可以使用pdMS_TO_TICKS宏把ms转换为tick
vTaskDelay(pdMS_TO_TICKS(100)); // 等待100ms 注意基于Tick实现的延时并不精确比如vTaskDelay(2) 的本意是延迟2个Tick周期有可能经过1个Tick多一点就返回了。 使用vTaskDelay函数时建议以ms为单位使用pdMS_TO_TICKS把时间转换为Tick。 将毫秒数换算成了tick数 #define pdMS_TO_TICKS( xTimeInMs ) ( ( TickType_t ) ( ( ( TickType_t ) ( xTimeInMs ) * ( TickType_t ) configTICK_RATE_HZ ) / ( TickType_t ) 1000U ) ) SysTick 定时器被捆绑在 NVIC 中用于产生 SysTick 异常异常号 15 滴答定时器是一个 24 位的递减计数器支持中断。 使用比较简单 专门用于给操作系统提供时钟节拍。 FreeRTOS 的系统时钟节拍可以在配置文件 FreeRTOSConfig.h 里面设置 #define configTICK_RATE_HZ ( ( TickType_t ) 1000 ) 如上所示的宏定义配置表示系统时钟节拍是 1KHz即 1ms。
void vTask3( void *pvParameters )
{
const TickType_t xDelay3000ms pdMS_TO_TICKS( 3000UL );
/* 任务函数的主体一般都是无限循环 */
for( ;; )
{
/* 打印任务的信息 */
printf(T3\r\n);
// 如果不休眠的话, 其他任务无法得到执行
vTaskDelay( xDelay3000ms );
}
}
修改优先级
使用uxTaskPriorityGet来获得任务的优先级
UBaseType_t uxTaskPriorityGet( const TaskHandle_t xTask );
使用参数xTask来指定任务设置为NULL表示获取自己的优先级。 使用vTaskPrioritySet 来设置任务的优先级
void vTaskPrioritySet( TaskHandle_t xTask,
UBaseType_t uxNewPriority );
使用参数xTask来指定任务设置为NULL表示设置自己的优先级 参数uxNewPriority表示新的优先级取值范围是0~(configMAX_PRIORITIES – 1)。
五、任务状态
void vTask1( void *pvParameters )
{
/* 任务函数的主体一般都是无限循环 */
for( ;; )
{
/* 打印任务的信息 */
printf(T1\r\n);
}
}
void vTask2( void *pvParameters )
{
/* 任务函数的主体一般都是无限循环 */
for( ;; )
{
/* 打印任务的信息 */
printf(T2\r\n);
}
}
void vTask3( void *pvParameters )
{
const TickType_t xDelay3000ms pdMS_TO_TICKS( 3000UL );
/* 任务函数的主体一般都是无限循环 */
for( ;; )
{
/* 打印任务的信息 */
printf(T3\r\n);
// 如果不休眠的话, 其他任务无法得到执行
vTaskDelay( xDelay3000ms );
}
}
/***********************************************/
//main函数
int main()
{
prvSetupHardware();
xTaskCreate(vTask1, Task 1, 1000, NULL, 1, NULL);
xTaskCreate(vTask2, Task 2, 1000, NULL, 1, NULL);
xTaskCreate(vTask3, Task 3, 1000, NULL, 2, NULL);
/* 启动调度器 */
vTaskStartScheduler();
/* 如果程序运行到了这里就表示出错了, 一般是内存不足 */
return 0;
} 如果把任务3中的vTaskDelay调用注释掉那么任务1、任务2根本没有执行的机会任务1、任务2被饿死了(starve)。 1.阻塞状态(Blocked)
在实际产品中我们不会让一个任务一直运行而是使用事件驱动的方法让它运行任务要等待某个事件事件发生后它才能运行在等待事件过程中它不消耗CPU资源在等待事件的过程中这个任务就处于阻塞状态(Blocked)
在阻塞状态的任务它可以等待两种类型的事件
时间相关的事件可以等待一段时间我等2分钟也可以一直等待直到某个绝对时间我等到下午3点
同步事件这事件由别的任务或者是中断程序产生例子1任务A等待任务B给它发送数据例子2任务A等待用户按下按键
在等待一个同步事件时可以加上超时时间。 比如等待队里数据超时时间设为10ms 10ms之内有数据到来成功返回 10ms到了还是没有数据超时返回
2.暂停状态(Suspended)
在日常生活的例子中母亲正在电脑前跟同事沟通母亲可以暂停 好烦啊我暂停一会 领导说你暂停一下 FreeRTOS中的任务也可以进入暂停状态唯一的方法是通过vTaskSuspend函数。函数原型如下
void vTaskSuspend( TaskHandle_t xTaskToSuspend ); 参数xTaskToSuspend表示要暂停的任务如果为NULL表示暂停自己。 要退出暂停状态只能由别人来操作 别的任务调用vTaskResume 中断程序调用xTaskResumeFromISR 实际开发中暂停状态用得不多。
3.就绪状态(Ready) 这个任务完全准备好了随时可以运行只是还轮不到它。这时它就处于就绪态(Ready)。
五、Delay
有两个Delay函数 vTaskDelay至少等待指定个数的Tick Interrupt才能变为就绪状态 vTaskDelayUntil等待到指定的绝对时刻才能变为就绪态。
void vTaskDelay( const TickType_t xTicksToDelay ); /* xTicksToDelay: 等待多少给
Tick */
/* pxPreviousWakeTime: 上一次被唤醒的时间
* xTimeIncrement: 要阻塞到(pxPreviousWakeTime xTimeIncrement)
* 单位都是Tick Count
*/
BaseType_t xTaskDelayUntil( TickType_t * const pxPreviousWakeTime,
const TickType_t xTimeIncrement ); 使用vTaskDelay(n)时进入、退出vTaskDelay的时间间隔至少是n个Tick中断 使用xTaskDelayUntil(Pre, n)时前后两次退出xTaskDelayUntil的时间至少是n个Tick中断退出xTaskDelayUntil时任务就进入的就绪状态一般都能得到执行机会所以可以使用xTaskDelayUntil来让任务周期性地运行 int main( void )
{
prvSetupHardware();
/* Task1的优先级更高, Task1先执行 */
xTaskCreate( vTask1, Task 1, 1000, NULL, 2, NULL );
xTaskCreate( vTask2, Task 2, 1000, NULL, 1, NULL );
/* 启动调度器 */
vTaskStartScheduler();
/* 如果程序运行到了这里就表示出错了, 一般是内存不足 */
return 0;
}
void vTask1( void *pvParameters )
{
const TickType_t xDelay50ms pdMS_TO_TICKS( 50UL );
TickType_t xLastWakeTime;
int i;
/* 获得当前的Tick Count */
xLastWakeTime xTaskGetTickCount();
for( ;; )
{
flag 1;
/* 故意加入多个循环让程序运行时间长一点 */
for (i 0; i 5; i)
printf( Task 1 is running\r\n );
##if 1
vTaskDelay(xDelay50ms);
##else
vTaskDelayUntil(xLastWakeTime, xDelay50ms);
##endif
}
}
void vTask2( void *pvParameters )
{
for( ;; )
{
flag 0;
printf( Task 2 is running\r\n );
}
}
使用Keil的逻辑分析观察flag变量的bit波形如下 flag为1时表示Task1在运行flag为0时表示Task2在运行也就是Task1处于阻塞状态 vTaskDelay指定的是阻塞的时间 vTaskDelayUntil指定的是任务执行的间隔、周期 六、调度算法
static volatile int flagIdleTaskrun 0; // 空闲任务运行时flagIdleTaskrun1
static volatile int flagTask1run 0; // 任务1运行时flagTask1run1
static volatile int flagTask2run 0; // 任务2运行时flagTask2run1
static volatile int flagTask3run 0; // 任务3运行时flagTask3run1
int main( void )
{
prvSetupHardware();
xTaskCreate(vTask1, Task 1, 1000, NULL, 0, NULL);
xTaskCreate(vTask2, Task 2, 1000, NULL, 0, NULL);
xTaskCreate(vTask3, Task 3, 1000, NULL, 2, NULL);
/* 启动调度器 */
vTaskStartScheduler();
/* 如果程序运行到了这里就表示出错了, 一般是内存不足 */
return 0;
}
void vTask1( void *pvParameters )
{
/* 任务函数的主体一般都是无限循环 */for( ;; ){flagIdleTaskrun 0;flagTask1run 1;flagTask2run 0;flagTask3run 0;/* 打印任务的信息 */printf(T1\r\n);}
}
void vTask2( void *pvParameters )
{
/* 任务函数的主体一般都是无限循环 */for( ;; ){flagIdleTaskrun 0;flagTask1run 0;flagTask2run 1;flagTask3run 0;/* 打印任务的信息 */printf(T2\r\n);}
}
void vTask3( void *pvParameters )
{const TickType_t xDelay5ms pdMS_TO_TICKS( 5UL );/* 任务函数的主体一般都是无限循环 */for( ;; ){flagIdleTaskrun 0;flagTask1run 0;flagTask2run 0;flagTask3run 1;/* 打印任务的信息 */printf(T3\r\n);// 如果不休眠的话, 其他任务无法得到执行vTaskDelay( xDelay5ms );}
} 提供了一个空闲任务的钩子函数
void vApplicationIdleHook(void)
{flagIdleTaskrun 1;flagTask1run 0;flagTask2run 0;flagTask3run 0;/* 故意加入打印让flagIdleTaskrun变为1的时间维持长一点 */printf(Id\r\n);
} 抢占时高优先级任务就绪时就可以马上执行 不抢占时优先级失去意义了既然不能抢占就只能协商了图中任务1一直在运行(一点都没有协商精神)其他任务都无法执行。即使任务3的vTaskDelay 已经超时、即使它的优先级更高都没办法执行。 文章转载自: http://www.morning.rwzc.cn.gov.cn.rwzc.cn http://www.morning.bhpsz.cn.gov.cn.bhpsz.cn http://www.morning.yfffg.cn.gov.cn.yfffg.cn http://www.morning.gdljq.cn.gov.cn.gdljq.cn http://www.morning.rfgkf.cn.gov.cn.rfgkf.cn http://www.morning.rdng.cn.gov.cn.rdng.cn http://www.morning.gcqs.cn.gov.cn.gcqs.cn http://www.morning.c7625.cn.gov.cn.c7625.cn http://www.morning.yrdkl.cn.gov.cn.yrdkl.cn http://www.morning.xcxj.cn.gov.cn.xcxj.cn http://www.morning.bhqlj.cn.gov.cn.bhqlj.cn http://www.morning.rmyqj.cn.gov.cn.rmyqj.cn http://www.morning.sfhjx.cn.gov.cn.sfhjx.cn http://www.morning.kpgft.cn.gov.cn.kpgft.cn http://www.morning.lhxkl.cn.gov.cn.lhxkl.cn http://www.morning.qgxnw.cn.gov.cn.qgxnw.cn http://www.morning.xdmsq.cn.gov.cn.xdmsq.cn http://www.morning.qsy39.cn.gov.cn.qsy39.cn http://www.morning.xqspn.cn.gov.cn.xqspn.cn http://www.morning.yxbrn.cn.gov.cn.yxbrn.cn http://www.morning.ghrhb.cn.gov.cn.ghrhb.cn http://www.morning.rmpfh.cn.gov.cn.rmpfh.cn http://www.morning.ntwxt.cn.gov.cn.ntwxt.cn http://www.morning.pwqyd.cn.gov.cn.pwqyd.cn http://www.morning.stcds.cn.gov.cn.stcds.cn http://www.morning.lwxsy.cn.gov.cn.lwxsy.cn http://www.morning.ygztf.cn.gov.cn.ygztf.cn http://www.morning.mnkhk.cn.gov.cn.mnkhk.cn http://www.morning.rnqrl.cn.gov.cn.rnqrl.cn http://www.morning.twpq.cn.gov.cn.twpq.cn http://www.morning.rggky.cn.gov.cn.rggky.cn http://www.morning.qsmdd.cn.gov.cn.qsmdd.cn http://www.morning.rxtxf.cn.gov.cn.rxtxf.cn http://www.morning.wcqkp.cn.gov.cn.wcqkp.cn http://www.morning.fwzjs.cn.gov.cn.fwzjs.cn http://www.morning.nlmm.cn.gov.cn.nlmm.cn http://www.morning.snygg.cn.gov.cn.snygg.cn http://www.morning.trqhd.cn.gov.cn.trqhd.cn http://www.morning.rgrdd.cn.gov.cn.rgrdd.cn http://www.morning.rydbs.cn.gov.cn.rydbs.cn http://www.morning.ttxnj.cn.gov.cn.ttxnj.cn http://www.morning.grtwn.cn.gov.cn.grtwn.cn http://www.morning.hxxwq.cn.gov.cn.hxxwq.cn http://www.morning.yxzfl.cn.gov.cn.yxzfl.cn http://www.morning.zzaxr.cn.gov.cn.zzaxr.cn http://www.morning.cyysq.cn.gov.cn.cyysq.cn http://www.morning.pnmtk.cn.gov.cn.pnmtk.cn http://www.morning.wnkqt.cn.gov.cn.wnkqt.cn http://www.morning.ddrdt.cn.gov.cn.ddrdt.cn http://www.morning.fqqcd.cn.gov.cn.fqqcd.cn http://www.morning.ygkk.cn.gov.cn.ygkk.cn http://www.morning.crxdn.cn.gov.cn.crxdn.cn http://www.morning.jhyfb.cn.gov.cn.jhyfb.cn http://www.morning.hpxxq.cn.gov.cn.hpxxq.cn http://www.morning.rnrwq.cn.gov.cn.rnrwq.cn http://www.morning.rbnj.cn.gov.cn.rbnj.cn http://www.morning.lskyz.cn.gov.cn.lskyz.cn http://www.morning.stbfy.cn.gov.cn.stbfy.cn http://www.morning.kchwr.cn.gov.cn.kchwr.cn http://www.morning.qmwzr.cn.gov.cn.qmwzr.cn http://www.morning.nrll.cn.gov.cn.nrll.cn http://www.morning.txzmy.cn.gov.cn.txzmy.cn http://www.morning.nrzbq.cn.gov.cn.nrzbq.cn http://www.morning.xmyrn.cn.gov.cn.xmyrn.cn http://www.morning.ppqjh.cn.gov.cn.ppqjh.cn http://www.morning.xnkh.cn.gov.cn.xnkh.cn http://www.morning.bmnm.cn.gov.cn.bmnm.cn http://www.morning.kfwrq.cn.gov.cn.kfwrq.cn http://www.morning.znrlg.cn.gov.cn.znrlg.cn http://www.morning.tgnwt.cn.gov.cn.tgnwt.cn http://www.morning.ttxnj.cn.gov.cn.ttxnj.cn http://www.morning.mqnbm.cn.gov.cn.mqnbm.cn http://www.morning.rknsp.cn.gov.cn.rknsp.cn http://www.morning.frllr.cn.gov.cn.frllr.cn http://www.morning.dansj.com.gov.cn.dansj.com http://www.morning.nrftd.cn.gov.cn.nrftd.cn http://www.morning.kcbml.cn.gov.cn.kcbml.cn http://www.morning.mypxm.com.gov.cn.mypxm.com http://www.morning.ckhpg.cn.gov.cn.ckhpg.cn http://www.morning.rfyff.cn.gov.cn.rfyff.cn