共计 3496 个字符,预计需要花费 9 分钟才能阅读完成。
先抛出问题:
有一全局变量,一个工作读,一个工作写,有没有问题?
先抛出答案,不倡议这么做。
临界资源:各工作 / 线程采取互斥的形式,实现共享的资源称作临界资源。属于临界资源的硬件串口打印、显示等, 软件有音讯缓冲队列、变量、数组、缓冲区等。多任务 / 线程间应采取互斥形式,从而实现对这种资源的共享。
多任务 / 多线程状况下在写模块时,只须要封装进爱护机制即可。常见的爱护机制无关中断、信号量、互斥锁等。
最近做的几个我的项目遇到的一些非凡场景:
1. 校时
定义全局变量
typedef struct{
/* 应用软件工夫 */
unsigned int year;
unsigned char month;
unsigned char day;
unsigned char hour; /* 时 */
unsigned char minute; /* 分 */
unsigned char second; /* 秒 */
unsigned int millisecond; /* 毫秒 */
unsigned int microsecond; /* 微秒 */
unsigned int nanosecond; /* 纳秒 */
unsigned int u40mic;
int delta; /* 日历时与本地 RTC 的差值 */
int delta_rtc; /* 同步 RTC 与本地 RTC 的差值 */
int delta_year; /* 用于操作系统年份保护 */
int timeElapse; /* 零碎上电后运行了多少秒 */
char DateValid; /* 年月日无效标识,1 为无效 */
char TimeValid; /* 时分秒无效标记,1 为无效 */
char BusVaild; /* 总线工夫无效, 1 为无效, 用于飞参授时及文件夹创立 */
}STRUCT_CORE_TIME;
STRUCT_CORE_TIME gst_TimeState;
int TIME_Regulate_Time(int year, int month, int date, int hour, int minute, int second)
{
struct timespec NewSetTime;
struct tm DownTime;
SYSTEM_TIME_TYPE sys_Time = 0;
RETURN_CODE_TYPE retCode;
if((year < 2000)||(year > 2255))
return -1;
if((month < 1) || (month > 12))
return -2;
if((date < 1) || (date>31))
return -3;
if((hour > 23) || (minute > 59) || (second > 59))
return -4;
/* 当超出年限时,获取 delta*/
if(year > 2100){if(((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)){
gst_TimeState.delta_year = year - 2096;
year = 2096;
}else{
gst_TimeState.delta_year = year - 2100;
year = 2100;
}
}else{gst_TimeState.delta_year = 0;}
GET_TIME(&sys_Time, &retCode);
DownTime.tm_hour = hour;
DownTime.tm_min = minute;
DownTime.tm_sec = second;
DownTime.tm_mday = date;
DownTime.tm_mon = month - 1;
DownTime.tm_year = year - 1900;
DownTime.tm_isdst = 0; /* 设置为非夏令时 */
NewSetTime.tv_sec = mktime(&DownTime);
/* 工夫间接用 delta 保护,不波及零碎工夫 */
gst_TimeState.delta = NewSetTime.tv_sec - sys_Time / Time_1S;
/*LOG4C 日志零碎工夫更新 */
sd_settimeofday(gst_TimeState.delta);
gst_TimeState.TimeValid = 1;
gst_TimeState.DateValid = 1;
return 0;
}
void TIME_Gather_Time()
{
struct timespec NewSetTime;
struct tm DownTime;
SYSTEM_TIME_TYPE sys_Time = 0;
RETURN_CODE_TYPE retCode;
GET_TIME(&sys_Time, &retCode);
NewSetTime.tv_sec = sys_Time / Time_1S + gst_TimeState.delta;
localtime_r(&NewSetTime.tv_sec, &DownTime);
gst_TimeState.year = DownTime.tm_year + 1900 + gst_TimeState.delta_year;
gst_TimeState.month = DownTime.tm_mon + 1;
gst_TimeState.day = DownTime.tm_mday;
gst_TimeState.hour = DownTime.tm_hour;
gst_TimeState.minute = DownTime.tm_min;
gst_TimeState.second = DownTime.tm_sec;
gst_TimeState.millisecond = sys_Time / 1000000 % 1000;
gst_TimeState.microsecond = sys_Time / 1000 % 1000;
gst_TimeState.nanosecond = sys_Time % 1000;
gst_TimeState.u40mic = ((gst_TimeState.hour * 3600 + gst_TimeState.minute * 60 + gst_TimeState.second)*1000
+ gst_TimeState.millisecond)*25;
}
校时线程做如下的周期调用:
if(stBusTime.delta 和 gst_TimeState.delta 相差 2 秒)
{
/* 校对利用工夫 */
Ret = TIME_Regulate_Time(stBusTime.year + 2000, stBusTime.month, stBusTime.day, stBusTime.hour, stBusTime.minute, stBusTime.second);
/* 只有 VCM 校时,就给 DLR 也校时。有的时候音视频文件创建太早,导致视频头内容有问题 */
TIME_Gather_Time(); /* 立即 TIME_Gather_Time 数据,更新 gst_TimeState 构造体所有内容 */}
另一个线程间接取全局变量 gst_TimeState 内的年月日时分秒。
这种状况实际上是不加爱护的一个线程读,另一个线程写,然而不加爱护也能应用的起因有两点:
1. 外界有卫星相对工夫更新 gst_TimeState 本地工夫
2. 对工夫的精度要求不高
获取卡状态
嵌入式零碎下,工作 1 进行获取卡状态操作:
static void Msg_04_Process(void * const Handler, unsigned char * const Message, int const LenBytes)
{DEVICE_INNER_TYPE *pDevice = (DEVICE_INNER_TYPE*)Handler;
/*04 音讯解决(周期接管)*/
memcpy(&DLR_2_CPM_04, Message, sizeof(DLR_2_CPM_04));
/*IDR 端的定义是相同的 */
pDevice->CardState = !DLR_2_CPM_04.Card_State;
}
工作 2 周期获取卡状态,并进行一些操作
int PSSS_DLR_Card_State(void * const Handler)
{DEVICE_INNER_TYPE *pDevice = (DEVICE_INNER_TYPE*)Handler;
int cardState = 0;
cardState = pDevice->CardState;
return cardState;
}
利用场景:
Msg_04_Process 获取卡号的周期是 2 秒,而 PSSS_DLR_Card_State 大概 20ms 就要被调用一次。
计划:
1. 给 pDevice->CardState 加信号量爱护
2.PSSS_DLR_Card_State 中屡次判断 pDevice->CardState 的值,例如间断 3 次是同一个值才示意获取胜利
正文完