为什么我的时区在嵌入式 Linux 中没有更新?

问题描述 投票:0回答:1

我有一个嵌入式Linux,对所有系统文件夹(包括/etc)都有写锁,并且只有一个文件夹是可自由写入的,称为

/writable
/etc/localtime
是指向
/writable/localtime
的符号链接。

我的(测试)应用程序通过将不同的时区文件复制到

/writable/localtime
的位置来更改时区,然后调用
tzset()
并尝试读取
tzname

但是,无论我复制时区信息还是将文件转换为指向其他地方的符号链接,

tzset
都不会更改
tzname
,也不会更新偏移量(意味着使用
localtime
会产生相同的结果)。

只有重新启动应用程序后,新时区才会生效。

为什么?

c linux embedded-linux
1个回答
0
投票

TL;博士

结合使用

setenv
unsetenv
tzset
来强制其完成其工作。

(最小)示例代码:

#include <time.h>

int main(int, const char **)
{
    //Install new timezone file
    setenv("TZ", "UTC", 1);
    tzset();
    unsetenv("TZ");
    tzset();
    //Format time to check it worked.
}

发生什么事了?

这个问题让我困惑了很长一段时间,这就是为什么我想与社区分享我的发现。

在 glibc 的源代码中,我发现

tzset
在执行实际工作之前执行两项检查。
第一个检查是“查看环境变量”(
TZ
)。
如果设置,该函数会比较值及其(内部)缓存值,如果两者相等 (
strcmp
),tzset 就会中止。

但这里的情况并非如此,因为根本没有设置环境变量。

第二次检查,在确保上次调用期间未设置

TZ
后,通过评估其元数据(inode 编号、修改日期等)来比较时区文件 (
/etc/localtime
) 是否已更改。

这就是上述场景中的问题所在:您不更新

/etc/localtime
,而是更新它指向的位置,而
tzset
看起来并不那么远。 因此,通过使用上述逻辑,
tzset
推断,没有什么可做的。

通过设置环境变量并调用

tzset
,您可以更新其内部缓冲区。
tzset
现在知道您正在使用自定义时区字符串而不是文件。
通过在下一步中取消设置环境变量,第一次检查返回 false,因为缓存的时区值 (
UTC
) 与当前时区值 (
NULL
) 不同,第二次检查也返回 false,因为
the environment variable had been used before
,使其完全跳过文件检查。

所有这些仅适用于您无法直接操作

/etc/localtime
,但需要操作它指向的位置。否则
tzset
将检测到“文件已更改”,如上所述。

© www.soinside.com 2019 - 2024. All rights reserved.