Chinaunix首页 | 论坛 | 博客

分类: LINUX

2009-11-09 10:04:10

RTC子系统
内核里面的RTC支持的架构分为两层: 一个独立于硬件的实现了内核RTC API的顶层字符驱动和硬件相关的同下层总线通信的底层驱动. RTC API的详细描叙在Documentation/rtc.txt中,它是一个顺应如hwclock应用程序的对/etc/rtc操作的标准IO控制集. API也指明了在sysfs中(/sys/class/rtc/)和procfs(/proc/driver/rtc)中的属性. RTC API保证了用户空间工具独立于底层平台和RTC芯片. 底层RTC驱动是特定于总线的. 有RTC芯片连向I2C总线并靠I2C客户端驱动运转.

内核有一个专门的RTC子系统提供顶层字符驱动和顶层RTC驱动可以使用的核心设施来配合上层. 这个核心设施的主要组件是rtc_class_ops结构体和注册函数rtc_device_[register|unregister](). 散布在不同特定总线目录上的底层RTC驱动在drivers/rtc/上的子系统上统一起来.

RTC子系统允许一个系统有多个RTC. 它是通过到处多种接口/dev/rtcN和/sys/class/rtc/rtcN做到的, N是系统中RTC的数目. 一些嵌入式系统例如有两个RTC: 一个是构建进了微控制器来支持如周期产生中断的复杂操作, 另外一个是小功率电池供电的外部RTC,用来保持时间. 由于RTC相关的应用程序对/etc/rtc操作, 所以建立一个符号链接让创建的/dev/rtcX结点可以被/etc/rtc访问到.

要使能RTC子系统,在内核配置时打开CONFIG_RTC_CLASS选项.

在PC上你可以选择使用遗留RTC驱动(drivers/char/rtc.c)来忽略RTC子系统. 该驱动对PC兼容机提供了底层和顶层,并导出/dev/rtc和/proc/driver/rtc到用户应用程序中. 要使用这个驱动,在配置内核时打开CONFIG_RTC即可.


伪字符驱动
一些通常使用的内核工具并不和任何物理硬件相连, 而且是通过字符设备优雅实现的. 空洞(null),永久zero源和内核随机数产生器都是作为虚拟设备来看待并且使用伪字符设备驱动来访问.

/dev/null字符设备"淹没"你不愿在屏幕上显示的数据.所以如果你要从CVS中检出源代码文件但不想整屏滚动显示文件名的话, 这样做吧: bash> cvs co kernel > /dev/null
重定向命令输出到/dev/null驱动的写入口点. 驱动的read()和write()函数简单的返回success从而各自忽略了输入和输出缓冲区.

如果你希望用0填充一个图片文件, 运行:
bash> dd if=/dev/zero of=file.img bs=1024 count=1024
/dev/zero驱动的read()函数引出全部为0的数据流到图片文件中.该驱动没有write()函数.

内核哟uyige内置的随机数产生器. 为了那些要使用随机序列的用户着想, 随机数产生器导出了API如get_random_bytes(). 对于用户模式程序它到处了两个字符接口:/dev/random和/dev/urandom. 从这两个文件中读出的随机数的随机性而言/dev/random要高些. 当用户程序从/dev/random中读数据时得到就是真是的随机数,但是从dev/urandom中得到的是伪随机数. /dev/random驱动并不使用公式产生真实随机数而是收集"环境噪音"(中断间隔, 按键点击间隔等等)来维护又一个无序的池称为熵池,作为随机流的种子. 来看下内核的输入子系统当它检测到键盘按下或鼠标移动时贡献给熵池的代码(定义在drivers/input/input.c中的input_event()):

void input_event(struct input_dev *dev, unsigned int type,
            unsigned int code, int value)
{
  /* ... */
  add_input_randomness(type, code, value); /* Contribute to entropy
                                              pool */
  /* ... */
}
要看里面中断处理层贡献中断间期给熵池代码,请看定义在kernel/irq/handle.c的handle_IRQ_event()函数:
irqreturn_t handle_IRQ_event(unsigned int irq,
                             struct irqaction *action)
{
  /* ... */
  if (status & IRQF_SAMPLE_RANDOM)
    add_interrupt_randomness(irq); /* Contribute to entropy pool */
  /* ... */
}
产生的真实随机数取决于熵池大小:
bash> od –x /dev/random
0000000 7331 9028 7c89 4791 7f64 3deb 86b3 7564
0000020 ebb9 e806 221a b8f9 af12 cb30 9a0e cc28
0000040 68d8 0bbf 68a4 0898 528e 1557 d8b3 57ec
0000060 b01d 8714 b1e1 19b9 0a86 9f60 646c c269
在少量行后输出停止,预示着熵池被耗尽.  要补充熵池并重启随机流, 在一个不使用的终端中猛击键盘多次或在屏幕上到处移动鼠标即可.

而/dev/urandom里面是一连串源源不断的伪随机流.

/dev/mem和/dev/kmem是经典的伪字符设备, 可以让你窥探系统内存里面. 这些字符结点分别导出了链接物理内存和内核虚拟内存的原始接口. 要对系统内存操作, mmap()这些结点就可以对返回的内存区域进行操作了.

所有这些伪设备(null,zero,random,mem,kmem)有不同的次设备号但有着静态赋予的相同主设备号1, 看下它们的实现:drivers/char/mem.c和drivers/char/random.c就知道了. 其他两个伪设备属于相同主设备号家族:/dev/null(模拟一个经常满的设备)和/dev/port(可以瞥视到系统I/O端口).

阅读(1161) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~