15_FreeRtos计数信号量优先级翻转互斥信号量
创始人
2024-05-26 05:15:00
0

目录

计数型信号量

计数型信号量相关API函数

计数型信号量实验源码

优先级翻转简介

优先级翻转实验源码

互斥信号量

互斥信号量相关API函数

互斥信号量实验源码


计数型信号量

计数型信号量相当于队列长度大于1的队列,因此计数型信号量能够容纳多个资源,这在计数型信号量被创建的时候确定的

计数型信号量适用场合:

事件计数

当每次事件发生后,在事件处理函数中释放计数型信号量(计数值+1) ,其他任务会获取计数型信号量(计数值-1),这种场合一般在创建时将初始计数值设置为 0

资源管理

信号量表示有效的资源数目。任务必须先获取信号量(信号量计数值-1)才能获取资源控制权。当计数值减为零时表示没有的资源。当任务使用完资源后,必须释放信号量(信号量计数值+1)。信号量创建时计数值应等于最大资源数目

计数型信号量相关API函数

使用计数型信号量的过程:创建计数型信号量 → 释放信号量 → 获取信号量

 计数型信号量的释放和获取与二值信号量相同!

此函数用于创建一个计数型信号量。

#definexSemaphoreCreateCounting( uxMaxCount , uxInitialCount )  \
xQueueCreateCountingSemaphore( ( uxMaxCount), ( uxlnitialCount ))

此函数用于获取信号量当前计数值大小 

#defineuxSemaphoreGetCount( xSemaphore) \uxQueueMessagesWaiting( (QueueHandle_t) (xSemaphore ))

计数型信号量实验源码

将设计三个任务: start_task、task1、task2

start_task :用来创建task1和task2任务

Task1:用于按键扫描,当检测到按键KEY0被按下时,释放计数型信号量

task2:每过一秒获取一次计数型信号量,当成功获取后打印信号量计数值

/********************************************************************************* @file           : user_mian.h* @brief          : V1.00******************************************************************************* @attention********************************************************************************//* Include 包含---------------------------------------------------------------*/
#include "stm32f10x.h"
#include 
#include "user_gpio.h"
#include "user_delay.h"
#include "user_rcc_config.h"
#include "user_uart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "user_key.h"
/* Typedef 类型----------------------------------------------------------------*/
/* Define  定义----------------------------------------------------------------*/
/* Macro   宏------------------------------------------------------------------*/
/*二值信号量句柄*/
QueueHandle_t count_semphore_handle;
/* Variables 变量--------------------------------------------------------------*/ 
/* Constants 常量--------------------------------------------------------------*/
/* Function  函数--------------------------------------------------------------*///任务优先级
#define START_TASK_PRIO		1
//任务堆栈大小	
#define START_STK_SIZE 		128  
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);//任务优先级
#define TASK1_PRIO			3
//任务堆栈大小	
#define TASK1_STK_SIZE 		100  
//任务句柄
TaskHandle_t Task1_Handler;
//任务函数
void task1(void *pvParameters);//任务优先级
#define TASK2_PRIO			3
//任务堆栈大小	
#define TASK2_STK_SIZE 		100  
//任务句柄
TaskHandle_t Task2_Handler;
//任务函数
void task2(void *pvParameters);int main(void){	/*配置系统中断分组为4位抢占*/NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);/*延时函数初始化*/delay_init();/*RCC配置*/Rcc_config();/*GPIO初始化*/ Gpio_Init();/*USART1初始化*/Uart1_Init(9600);/*创建计数型信号量最大值100,初始化值为0*/count_semphore_handle = xSemaphoreCreateCounting(100,0); if(count_semphore_handle != NULL){printf("计数型信号量创建成功初始值为0\r\n\r\n");}/*创建开始任务*/xTaskCreate((TaskFunction_t )start_task,            //任务函数(const char*    )"start_task",          //任务名称(uint16_t       )START_STK_SIZE,        //任务堆栈大小(void*          )NULL,                  //传递给任务函数的参数(UBaseType_t    )START_TASK_PRIO,       //任务优先级(TaskHandle_t*  )&StartTask_Handler);   //任务句柄              vTaskStartScheduler();          //开启任务调度}/*!\brief		开始任务函数\param[in]	传递形参,创建任务时用户自己传入\param[out]	none\retval 	none
*/
void start_task(void *pvParameters)
{taskENTER_CRITICAL();           //进入临界区//创建任务1xTaskCreate((TaskFunction_t )task1,     	(const char*    )"task1",   	(uint16_t       )TASK1_STK_SIZE, (void*          )NULL,				(UBaseType_t    )TASK1_PRIO,	(TaskHandle_t*  )&Task1_Handler);   //创建任务2xTaskCreate((TaskFunction_t )task2,     (const char*    )"task2",   (uint16_t       )TASK2_STK_SIZE, (void*          )NULL,(UBaseType_t    )TASK2_PRIO,(TaskHandle_t*  )&Task2_Handler); vTaskDelete(StartTask_Handler); //删除开始任务taskEXIT_CRITICAL();            //退出临界区
}/*!\brief		task1释放计数型信号量\param[in]	传递形参,创建任务时用户自己传入\param[out]	none\retval 	none
*/
void task1(void *pvParameters)
{uint8_t key = 0;while(1){	/*获取按键值*/key = Key_Scan(0);if(key == KEY0_PRES){if(count_semphore_handle != NULL){					 if(xSemaphoreGive(count_semphore_handle)){taskENTER_CRITICAL();           //进入临界区printf("计数型信号量释放成功当前值为%d\r\n\r\n",(int)uxSemaphoreGetCount(count_semphore_handle));taskEXIT_CRITICAL();            //退出临界区}}		}vTaskDelay(10);}
} /*!\brief		task2获取计数型信号量\param[in]	传递形参,创建任务时用户自己传入\param[out]	none\retval 	none
*/
void task2(void *pvParameters)
{BaseType_t err;while(1){/*获取信号量死等,进入阻塞态*/err = xSemaphoreTake(count_semphore_handle,portMAX_DELAY);	if(err == pdTRUE){taskENTER_CRITICAL();           //进入临界区	printf("信号量的计数值为:%d\r\n\r\n",(int)uxSemaphoreGetCount(count_semphore_handle));		taskEXIT_CRITICAL();            //退出临界区}vTaskDelay(1000);}
}/************************************************************** END OF FILE ****/

 

优先级翻转简介

优先级翻转:高优先级的任务反而慢执行,低优先级的任务反而优先执行

优先级翻转在抢占式内核中是非常常见的,但是在实时操作系统中是不允许出现优先级翻转的,因为优先级翻转会破坏任务的预期顺序,可能会导致未知的严重后果。

在使用二值信号量的时候,经常会遇到优先级翻转的问题。

举例:

任务H 优先级最高 任务M优先级中等  任务L优先级最低

假设任务L正在运行获取了信号量,其他2任务在阻塞状态,此时任务H就绪抢占了任务L,任务H也是获取信号量,发现信号量没有了进入阻塞态,继续执行任务L(优先级翻转了),然后任务M就绪抢占了任务L,任务M执行完后,进入阻塞态,任务H一直在等信号量所以一直在阻塞态,任务L继续运行,直到释放了信号量后,任何H才会从阻塞态变成就绪态执行。

高优先级任务被低优先级任务阻塞,导致高优先级任务迟迟得不到调度,但其他中等优先级的任务却能抢到CPU资源。从现象上看,就像是中优先级的任务比高优先级任务具有更高的优先权(即优先级翻转)

优先级翻转实验源码

在使用二值信号量的时候会存在优先级翻转的问题,本实验通过模拟的方式实现优先级翻转,观察优先级翻转对抢占式内核的影响。

将设计四个任务:start_task、high_task、middle_task, low_task

start_task:用来创建其它任务

high_task:高优先级任务,会获取二值信号量,获取成功以后打印提示信息,处理完后释放信号量

middle_task:中等优先级任务,简单的应用任务

low_task:低优先级任务,同高优先级一样的操作,不同的是低优先级任务占用信号量的时间久一点

/********************************************************************************* @file           : user_mian.h* @brief          : V1.00******************************************************************************* @attention********************************************************************************//* Include 包含---------------------------------------------------------------*/
#include "stm32f10x.h"
#include 
#include "user_gpio.h"
#include "user_delay.h"
#include "user_rcc_config.h"
#include "user_uart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "user_key.h"
/* Typedef 类型----------------------------------------------------------------*/
/* Define  定义----------------------------------------------------------------*/
/* Macro   宏------------------------------------------------------------------*/
/*二值信号量句柄*/
QueueHandle_t semphore_handle;
/* Variables 变量--------------------------------------------------------------*/ 
/* Constants 常量--------------------------------------------------------------*/
/* Function  函数--------------------------------------------------------------*///任务优先级
#define START_TASK_PRIO		1
//任务堆栈大小	
#define START_STK_SIZE 		128  
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);//任务优先级
#define HIGH_PRIO			4
//任务堆栈大小	
#define HIGH_STK_SIZE 		100  
//任务句柄
TaskHandle_t HIGH_Handler;
//任务函数
void high_task(void *pvParameters);//任务优先级
#define MIDDLE_PRIO			3
//任务堆栈大小	
#define MIDDLE_STK_SIZE 		100  
//任务句柄
TaskHandle_t MIDDLE_Handler;
//任务函数
void middle_task(void *pvParameters);//任务优先级
#define LOW_PRIO			2
//任务堆栈大小	
#define LOW_STK_SIZE 		100  
//任务句柄
TaskHandle_t LOW_Handler;
//任务函数
void low_task(void *pvParameters);int main(void){	/*配置系统中断分组为4位抢占*/NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);/*延时函数初始化*/delay_init();/*RCC配置*/Rcc_config();/*GPIO初始化*/ Gpio_Init();/*USART1初始化*/Uart1_Init(9600);/*创建二值信号量*/semphore_handle = xSemaphoreCreateBinary(); if(semphore_handle == NULL){printf("二值信号量创建不成功\r\n\r\n");}else{printf("二值信号量创建成功\r\n\r\n");}/*二值释放信号量*/xSemaphoreGive(semphore_handle);/*创建开始任务*/xTaskCreate((TaskFunction_t )start_task,            //任务函数(const char*    )"start_task",          //任务名称(uint16_t       )START_STK_SIZE,        //任务堆栈大小(void*          )NULL,                  //传递给任务函数的参数(UBaseType_t    )START_TASK_PRIO,       //任务优先级(TaskHandle_t*  )&StartTask_Handler);   //任务句柄              vTaskStartScheduler();          //开启任务调度}/*!\brief		开始任务函数\param[in]	传递形参,创建任务时用户自己传入\param[out]	none\retval 	none
*/
void start_task(void *pvParameters)
{taskENTER_CRITICAL();           //进入临界区//创建高优先级任务xTaskCreate((TaskFunction_t )high_task,     	(const char*    )"high_task",   	(uint16_t       )HIGH_STK_SIZE, (void*          )NULL,				(UBaseType_t    )HIGH_PRIO,	(TaskHandle_t*  )&HIGH_Handler);   //创建中优先级任务xTaskCreate((TaskFunction_t )middle_task,     (const char*    )"middle_task",   (uint16_t       )MIDDLE_STK_SIZE, (void*          )NULL,(UBaseType_t    )MIDDLE_PRIO,(TaskHandle_t*  )&MIDDLE_Handler); //创建低优先级任务xTaskCreate((TaskFunction_t )low_task,     (const char*    )"low_task",   (uint16_t       )LOW_STK_SIZE, (void*          )NULL,(UBaseType_t    )LOW_PRIO,(TaskHandle_t*  )&LOW_Handler); vTaskDelete(StartTask_Handler); //删除开始任务taskEXIT_CRITICAL();            //退出临界区
}/*!\brief		高优先级任务\param[in]	传递形参,创建任务时用户自己传入\param[out]	none\retval 	none
*/
void high_task(void *pvParameters)
{while(1){	taskENTER_CRITICAL();           //进入临界区printf("high_task获取信号量\r\n\r\n");taskEXIT_CRITICAL();            //退出临界区/*获取二值信号量,并死等方式*/xSemaphoreTake(semphore_handle,portMAX_DELAY);taskENTER_CRITICAL();           //进入临界区printf("high_task正在运行\r\n\r\n");taskEXIT_CRITICAL();            //退出临界区delay_xms(1000);/*释放二值信号量*/taskENTER_CRITICAL();           //进入临界区printf("high_task释放信号量\r\n\r\n");taskEXIT_CRITICAL();            //退出临界区xSemaphoreGive(semphore_handle);vTaskDelay(10);}
} /*!\brief		中优先级任务\param[in]	传递形参,创建任务时用户自己传入\param[out]	none\retval 	none
*/
void middle_task(void *pvParameters)
{while(1){taskENTER_CRITICAL();           //进入临界区printf("middle_task正在运行\r\n\r\n");taskEXIT_CRITICAL();            //退出临界区vTaskDelay(1000);}
}/*!\brief		低优先级任务\param[in]	传递形参,创建任务时用户自己传入\param[out]	none\retval 	none
*/
void low_task(void *pvParameters)
{while(1){    taskENTER_CRITICAL();           //进入临界区printf("low_task获取信号量\r\n\r\n");taskEXIT_CRITICAL();            //退出临界区/*获取二值信号量,并死等方式*/xSemaphoreTake(semphore_handle,portMAX_DELAY);taskENTER_CRITICAL();           //进入临界区		printf("low_task正在运行\r\n\r\n");taskEXIT_CRITICAL();            //退出临界区delay_xms(3000);/*释放二值信号量*/taskENTER_CRITICAL();           //进入临界区printf("low_task释放信号量\r\n\r\n");taskEXIT_CRITICAL();            //退出临界区xSemaphoreGive(semphore_handle);vTaskDelay(1000);		}}/************************************************************** END OF FILE ****/

互斥信号量

互斥信号量其实就是一个拥有优先级继承的二值信号量,在同步的应用中二值信号量最适合。互斥信号量适合用于那些需要互斥访问的应用中!

优先级继承:当一个互斥信号量正在被一个低优先级的任务持有时,如果此时有个高优先级的任务也尝试获取这个互斥信号量,那么这个高优先级的任务就会被阻塞。不过这个高优先级的任务会将低优先级任务的优先级提升到与自己相同的优先级。

 此时任务H的阻塞时间仅仅是任务L的执行时间,将优先级翻转的危害降到了最低

优先级继承并不能完全的消除优先级翻转的问题,它只是尽可能的降低优先级翻转带来的影响

注意:互斥信号量不能用于中断服务函数中,原因如下:

  1. 互斥信号量有任务优先级继承的机制,但是中断不是任务,没有任务优先级,所以互斥信号量只能用与任务中,不能用于中断服务函数。
  2. 中断服务函数中不能因为要等待互斥信号量而设置阻塞时间进入阻塞态。

互斥信号量相关API函数

使用互斥信号量:首先将宏configUSE_MUTEXES置一

使用流程:创建互斥信号量→ (task)获取信号量→ (give)释放信号量

创建互斥信号量函数

 互斥信号量的释放和获取函数与二值信号量相同!只不过互斥信号量不支持中断中调用

注意:创建互斥信号量时,会主动释放一次信号量

#define xSemaphoreCreateMutex()  xQueueCreateMutex( queueQUEUE_TYPE_MUTEX)

此函数用于创建互斥信号量

互斥信号量实验源码

在优先级翻转实验的基础,加入互斥信号量,解决优先级翻转问题

/********************************************************************************* @file           : user_mian.h* @brief          : V1.00******************************************************************************* @attention********************************************************************************//* Include 包含---------------------------------------------------------------*/
#include "stm32f10x.h"
#include 
#include "user_gpio.h"
#include "user_delay.h"
#include "user_rcc_config.h"
#include "user_uart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "user_key.h"
/* Typedef 类型----------------------------------------------------------------*/
/* Define  定义----------------------------------------------------------------*/
/* Macro   宏------------------------------------------------------------------*/
/*二值信号量句柄*/
QueueHandle_t mutex_semphore_handle;
/* Variables 变量--------------------------------------------------------------*/ 
/* Constants 常量--------------------------------------------------------------*/
/* Function  函数--------------------------------------------------------------*///任务优先级
#define START_TASK_PRIO		1
//任务堆栈大小	
#define START_STK_SIZE 		128  
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);//任务优先级
#define HIGH_PRIO			4
//任务堆栈大小	
#define HIGH_STK_SIZE 		100  
//任务句柄
TaskHandle_t HIGH_Handler;
//任务函数
void high_task(void *pvParameters);//任务优先级
#define MIDDLE_PRIO			3
//任务堆栈大小	
#define MIDDLE_STK_SIZE 		100  
//任务句柄
TaskHandle_t MIDDLE_Handler;
//任务函数
void middle_task(void *pvParameters);//任务优先级
#define LOW_PRIO			2
//任务堆栈大小	
#define LOW_STK_SIZE 		100  
//任务句柄
TaskHandle_t LOW_Handler;
//任务函数
void low_task(void *pvParameters);int main(void){	/*配置系统中断分组为4位抢占*/NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);/*延时函数初始化*/delay_init();/*RCC配置*/Rcc_config();/*GPIO初始化*/ Gpio_Init();/*USART1初始化*/Uart1_Init(9600);/*创建互斥信号量,默认释放一次*/mutex_semphore_handle = xSemaphoreCreateMutex(); if(mutex_semphore_handle == NULL){printf("互斥信号量创建不成功\r\n\r\n");}else{printf("互斥信号量创建成功\r\n\r\n");}/*创建开始任务*/xTaskCreate((TaskFunction_t )start_task,            //任务函数(const char*    )"start_task",          //任务名称(uint16_t       )START_STK_SIZE,        //任务堆栈大小(void*          )NULL,                  //传递给任务函数的参数(UBaseType_t    )START_TASK_PRIO,       //任务优先级(TaskHandle_t*  )&StartTask_Handler);   //任务句柄              vTaskStartScheduler();          //开启任务调度}/*!\brief		开始任务函数\param[in]	传递形参,创建任务时用户自己传入\param[out]	none\retval 	none
*/
void start_task(void *pvParameters)
{taskENTER_CRITICAL();           //进入临界区//创建高优先级任务xTaskCreate((TaskFunction_t )high_task,     	(const char*    )"high_task",   	(uint16_t       )HIGH_STK_SIZE, (void*          )NULL,				(UBaseType_t    )HIGH_PRIO,	(TaskHandle_t*  )&HIGH_Handler);   //创建中优先级任务xTaskCreate((TaskFunction_t )middle_task,     (const char*    )"middle_task",   (uint16_t       )MIDDLE_STK_SIZE, (void*          )NULL,(UBaseType_t    )MIDDLE_PRIO,(TaskHandle_t*  )&MIDDLE_Handler); //创建低优先级任务xTaskCreate((TaskFunction_t )low_task,     (const char*    )"low_task",   (uint16_t       )LOW_STK_SIZE, (void*          )NULL,(UBaseType_t    )LOW_PRIO,(TaskHandle_t*  )&LOW_Handler); vTaskDelete(StartTask_Handler); //删除开始任务taskEXIT_CRITICAL();            //退出临界区
}/*!\brief		高优先级任务\param[in]	传递形参,创建任务时用户自己传入\param[out]	none\retval 	none
*/
void high_task(void *pvParameters)
{while(1){	taskENTER_CRITICAL();           //进入临界区printf("high_task获取信号量\r\n\r\n");taskEXIT_CRITICAL();            //退出临界区/*获取二值信号量,并死等方式*/xSemaphoreTake(mutex_semphore_handle,portMAX_DELAY);taskENTER_CRITICAL();           //进入临界区printf("high_task正在运行\r\n\r\n");taskEXIT_CRITICAL();            //退出临界区delay_xms(1000);/*释放二值信号量*/taskENTER_CRITICAL();           //进入临界区printf("high_task释放信号量\r\n\r\n");taskEXIT_CRITICAL();            //退出临界区xSemaphoreGive(mutex_semphore_handle);vTaskDelay(10);}
} /*!\brief		中优先级任务\param[in]	传递形参,创建任务时用户自己传入\param[out]	none\retval 	none
*/
void middle_task(void *pvParameters)
{while(1){taskENTER_CRITICAL();           //进入临界区printf("middle_task正在运行\r\n\r\n");taskEXIT_CRITICAL();            //退出临界区vTaskDelay(1000);}
}/*!\brief		低优先级任务\param[in]	传递形参,创建任务时用户自己传入\param[out]	none\retval 	none
*/
void low_task(void *pvParameters)
{while(1){    taskENTER_CRITICAL();           //进入临界区printf("low_task获取信号量\r\n\r\n");taskEXIT_CRITICAL();            //退出临界区/*获取二值信号量,并死等方式*/xSemaphoreTake(mutex_semphore_handle,portMAX_DELAY);taskENTER_CRITICAL();           //进入临界区		printf("low_task正在运行\r\n\r\n");taskEXIT_CRITICAL();            //退出临界区delay_xms(3000);/*释放二值信号量*/taskENTER_CRITICAL();           //进入临界区printf("low_task释放信号量\r\n\r\n");taskEXIT_CRITICAL();            //退出临界区xSemaphoreGive(mutex_semphore_handle);vTaskDelay(1000);		}}/************************************************************** END OF FILE ****/

相关内容

热门资讯

Python|位运算|数组|动... 目录 1、只出现一次的数字(位运算,数组) 示例 选项代...
张岱的人物生平 张岱的人物生平张岱(414年-484年),字景山,吴郡吴县(今江苏苏州)人。南朝齐大臣。祖父张敞,东...
西游西后传演员女人物 西游西后传演员女人物西游西后传演员女人物 孙悟空 六小龄童 唐僧 徐少华 ...
名人故事中贾岛作诗内容简介 名人故事中贾岛作诗内容简介有一次,贾岛骑驴闯了官道.他正琢磨着一句诗,名叫《题李凝幽居》全诗如下:闲...
和男朋友一起优秀的文案? 和男朋友一起优秀的文案?1.希望是惟一所有的人都共同享有的好处;一无所有的人,仍拥有希望。2.生活,...
戴玉手镯的好处 戴玉手镯好还是... 戴玉手镯的好处 戴玉手镯好还是碧玺好 女人戴玉?戴玉好还是碧玺好点佩戴手镯,以和田玉手镯为佳!相嫌滑...
依然什么意思? 依然什么意思?依然(汉语词语)依然,汉语词汇。拼音:yī    rán基本解释:副词,指照往常、依旧...
高尔基的散文诗 高尔基的散文诗《海燕》、《大学》、《母亲》、《童年》这些都是比较出名的一些代表作。
心在飞扬作者简介 心在飞扬作者简介心在飞扬作者简介如下。根据相关公开资料查询,心在飞扬是一位优秀的小说作者,他的小说作...
卡什坦卡的故事赏析? 卡什坦卡的故事赏析?讲了一只小狗的故事, 我也是近来才读到这篇小说. 作家对动物的拟人描写真是惟妙...
林绍涛为简艾拿绿豆糕是哪一集 林绍涛为简艾拿绿豆糕是哪一集第三十二集。 贾宽认为是阎帅间接导致刘映霞住了院,第二天上班,他按捺不...
小爱同学是女生吗小安同学什么意... 小爱同学是女生吗小安同学什么意思 小爱同学,小安同学说你是女生。小安是男的。
内分泌失调导致脸上长斑,怎么调... 内分泌失调导致脸上长斑,怎么调理内分泌失调导致脸上长斑,怎么调理先调理内分泌,去看中医吧,另外用好的...
《魔幻仙境》刺客,骑士人物属性... 《魔幻仙境》刺客,骑士人物属性加点魔幻仙境骑士2功1体质
很喜欢她,该怎么办? 很喜欢她,该怎么办?太冷静了!! 太理智了!爱情是需要冲劲的~不要考虑着考虑那~否则缘...
言情小说作家 言情小说作家我比较喜欢匪我思存的,很虐,很悲,还有梅子黄时雨,笙离,叶萱,还有安宁的《温暖的玄》 小...
两个以名人的名字命名的风景名胜... 两个以名人的名字命名的风景名胜?快太白楼,李白。尚志公园,赵尚志。
幼儿教育的代表人物及其著作 幼儿教育的代表人物及其著作卡尔威特的《卡尔威特的教育》,小卡尔威特,他儿子成了天才后写的《小卡尔威特...
海贼王中为什么说路飞打凯多靠霸... 海贼王中为什么说路飞打凯多靠霸气升级?凯多是靠霸气升级吗?因为之前刚到时确实打不过人家因为路飞的实力...
运气不好拜财神有用吗运气不好拜... 运气不好拜财神有用吗运气不好拜财神有没有用1、运气不好拜财神有用。2、拜财神上香前先点蜡烛,照亮人神...