Linux 时间和时区设置问题

原则上内核时钟和硬件时钟都应该存储 UTC 时间,有时间硬件时钟可能不住着本地时间,Windows 会这么干。这时就会出现时间设置不正确的 问题。

通常我们使用下面的命令从硬件读取时间和向硬件写入时间:

sudo hwclock --systz        # 读取硬件时钟
sudo hwclock --systohc  # 写入硬件时钟

问题在于 hwclock 读取和写入硬件时钟时怎么知道硬件时钟存储或应该存储什么类型的时间呢?UTC还是本地时间?这是需要用到 /etc/adjtime 文件,这个文件中描述了硬件时钟是存储或应该存储什么类型的时间。文件格式为

0.150763 1298445152 0.000000
1298445152
UTC

关键在第三行,UTC 表示存储着 UTC 时间,LOCAL 表示本地时间。

需要使 /etc/adjtime 文件中的时间类型和硬件时钟中存储时间类型一致,否则就会导致时间不对。

Over!

平台驱动中 backlight 相关部分

static int ls3a_get_intensity(struct backlight_device * bd)
{
	// 从 EC 获取 backlight 数据
 
	return ???;
}
 
static int ls3a_set_intensity(struct backlight_device * bd)
{
	int brightness = bd->props.brightness;
 
	// 调用 EC 设置 brightness
 
	return 0;
}
 
static struct backlight_ops ls3a_backlight_ops =
{
	.get_brightness = ls3a_get_intensity,
	.update_status = ls3a_set_intensity,
};
 
static int __init ls3a_init(void)
{
	// 注册平台驱动和设备
	platform_driver_register(...);
	platform_device_register(...);
 
	...
 
	// 通过 EC 查询 backlight 属性
	...
 
	// 注册 backlight 设备
	ls3a_backlight_device = backlight_device_register(...);
	...
	// 设置 backlight 设备属性
	ls3a_backlight_device->props.max_brightness = ????; // from EC
	ls3a_backlight_device->props.brightness = ????; // default value
	backlight_update_status(ls3a_backlight_device);	// update
 
	...
 
	return 0;
}
 
static void __exit ls3a_exit(void)
{
	// 注册 backlight 设备
	backlight_device_unregister(ls3a_backlight_device);
 
	...
 
	platform_device_unregister(ls3a_device);
	platform_driver_unregister(ls3a_driver);
}
 
module_init(ls3a_init);
module_exit(ls3a_exit);

Over!

无线设备状态的查询和控制

RfKill
内核使用 rfkill 模块管理无线设备,rfkill 提供两种类型的用户态接口用于查询和控制无线设备:
1. /dev/rfkill
这是一个标准的 I/O 设备,可以使用标准的 open(), close() ioctl() 等操作查询和控制每个无线设备的状态,相关的头文件 /usr/include/linux/rfkill.h

2. /sys/class/rfkill/
每个 rfkill 设备会在 sysfs 中创建自己的一个节点,都有下面文件:

  1. name : 接口或驱动名称,注册 rfkill 设备时指定。
  2. type : 设备类型, wlan | bluethooth …
  3. persistent : 从外存谋取的软限制状态
  4. state : 当前的无线设备状态
    • 0 : RFKILL_STATE_SOFT_BLOCKED 被软件关闭
    • 1 : RFKILL_STATE_UNBLOCKED 开启
    • 2 : RFKILL_STATE_HARD_BLOCKED 被硬件驱动关闭

设备禁用类型

  1. 软件禁用,由用户态应用程序触发,并通过 rfkill 接口关闭无线设备。
  2. 硬件驱动禁用,由内核硬件驱动程序触发的关闭,硬件驱动程序(平台驱动)调用 rfkill 接口通知硬件被关闭。

平台驱动中的 rfkill 相关部分

// 状态设备
static int ls3a_rfkill_set(void * data, bool blocked)
{
	// 调用 EC 设备无线设备状态
	...
}
 
// 状态查询
static void ls3a_rfkill_query(struct rfkill * rfkill, void * data)
{
	// 调用 EC 设备查询无线设备的状态
	...
 
	rfkill_set_sw_state(rfkill, state_soft);	// 设置 soft state
	rfkill_set_hw_state(rfkill, state_hard);	// 设备 hard state
}
 
// rfkill 操作函数
static const struct rfkill_ops ls3a_rfkill_ops =
{
	.set_block = ls3a_rfkill_set,
	.query = ls3a_rfkill_query,
};
 
 
static int __init ls3a_setup_rfkill(void)
{
	// wifi
	wifi_rfkill = rfkill_alloc("ls3a-wifi", ...);
	...
	rfkill_register(wifi_rfkill);
 
	// bluetooth
	bluetooth_rfkill = rfkill_alloc("ls3a-bluetooth", ...);
	...
	rfkill_register(bluetooth_rfkill);
 
	// wwan
	wwan_rfkill = rfkill_alloc("ls3a-wwan", ...);
	...
	rfkill_register(wwan_rfkill);
}
 
static void ls3a_cleanup_rfkill(void)
{
	// wifi
	rfkill_unregsiter(wifi_rfkill);
	rfkill_destroy(wifi_rfkill);
 
	// bluetooth
	rfkill_unregsiter(bluetooth_rfkill);
	rfkill_destroy(bluetooth_rfkill);
 
	// wwan
	rfkill_unregsiter(wwan_rfkill);
	rfkill_destroy(wwan_rfkill);
}
 
static int __init ls3a_init(void)
{
	// 注册平台驱动和其它设备初始化
	platform_device = platform_driver_register(&platform_driver);
	...
 
	// 设置 rfkill 设备
	ls3a_setup_rfkill();
 
	...
 
	return 0;
}
 
static void __exit ls3a_exit(void)
{
	// 注销平台设备和其它设备
	...
 
	// 清除 rfkill 设备
	ls3a_cleanup_rfkill();
}
 
module_init(ls3a_init);
module_exit(ls3a_exit);

Over!

自编译 Firefox 4.0b11 安装中文语言包

最近为龙芯平台编译了 Firefox 4.0b11,默认没有中文语言支持,需要手动安装。(现在己集成到 language-pack-zh-hans-base 包中)

下载语言包

wget http://releases.mozilla.org/pub/mozilla.org/firefox/releases/4.0b11/linux-i686/xpi/zh-CN.xpi

安装语言包
在 Firefox 菜单 -> 中打开文件 zh-CN.xpi,会自动进行安装,完成后重新启动 Firefox。

应用语言包
在安装完成后语言可能还没有被应用,需要手动修改配置。打开 about:config,设下面下列,并重启 Firefox。

general.useragent.locale = zh-CN
intl.accept_languages = zh-cn,zh

Over!

MySQL 5.5 禁用 InnoDB 引擎

升级 MySQL 至 5.5 出现了问题,skip-innodb 禁用 InnoDB 引擎导致服务不能启动。查看官网得知从 5.5.5 开始默认使用 InnoDB 引擎,问题应该在这里。InnoDB 引擎的性能可能不错,但是内存使用也不少,我的小内存 VPS 有点承受不起。

VPS 上的 MySQL 目前只跑 WordPress,查看导出的 sql 文件中创建表都使用了 MyISAM 引擎,果断禁用 InnoDB 之。

my.cnf

[mysqld]
...
default-storage-engine = MyISAM
 
...
skip-innodb
...

Over!

阻止 VPS Host OS 篡改 Arch Linux 配置文件 rc.conf

现在用的 VPS 是 PhotonVPS 的 OpenVZ 虚拟化方案,Guest OS 是 Arch Linux。这家 VPS 服务商对于 Arch Linux 的配置是错误的,IPv6 地址不能正确配置。而且还会在开机前将 Arch Linux 的配置文件 /etc/rc.conf 给篡改了,导致正确的配置文件被破坏。

这里我们用修改一下系统初始化脚本 /etc/rc.sysinit 以阻止被篡改的配置文件生效。

备份正确的配置文件 rc.conf 和初始化脚本 rc.sysinit

cp /etc/rc.conf /etc/.brc  # 不要命名为 rc.conf.bak
cp /etc/rc.sysinit /etc/rc.sysinit.bak

/etc/rc.sysinit

#!/bin/bash
#
# /etc/rc.sysinit
#
 
cp /etc/.brc /etc/rc.conf   # 增加这行,加载前还原 rc.conf
. /etc/rc.conf
. /etc/rc.d/functions

Over!

How to disable and delete wordpress post revisions

Disable post revisions
Insert it into wp-config.php

define('WP_POST_REVISIONS', false);

Delete exist revisions

mysqldump -u username dbname -p > backup-db.sql
echo "DELETE FROM wp_posts WHERE post_type = 'revision';" | mysql -u username -D dbname -p

Over!

OpenSSH 客户端为不同服务器应用不同配置

有的时候你可能会需要在你的系统上使用 OpenSSH 客户端连接两个不同端口的 SSH 服务器,如 domain1 服务器使用的端口是 2200,而 domain2 服务器使用的端口是 20。这时你还想只使用 ssh domain1 和 ssh domain2 来连接,很高兴的告诉你这是可行的。只需要简单的修改一下配置文件:

~/.ssh/config

Host domain1
        Port 2200
 
Host domain2
        Port 20

TIP: 不仅仅对于 Port ,User 等等都可以,具体参考 man ssh_config。

Over!