归档时间:十二月, 2011

Mini6410的启动过程

十二 27 2011 由 创建在标签 开发

入手Mini6410很久,一直没有用起来,最近项目稍微轻松一点,开始拿起来做点事情、学点东西,后面也会把这款开发板的一些情况发不上来。

Mini6410简介

Mini6410是友善基于三星6410开发的一款ARM11开发板,想了解的人可以到官网看看(6410友善官网),里面有详细的信息。

这里也简要提一下6410一些让人蛋疼的东西,让人用着很不爽,因为还没有用得很熟悉,就说说目前发现的两个让人不爽的地方。第一,它的Superloader不开源,提供的开源的U-boot又不能支持SD卡启动;第二,文件系统压缩使用了自己的压缩方法(在内核配置的地方可以查看到),如果我们想用通用的程序来做的话,压力会比较大。

6410的启动过程介绍

和X86平台的启动过程不同的是6410通过busybox启动,将复杂的启动过程变得简单化,便于初学者学习和使用此块开发板。

开机启动时首先进入Bootloader,它主要完成的工作是初始化硬件设备、建立内存空间映射图,从而将系统的软硬件环境带到一个合适状态,以便为最终调用操作系统内核准备好正确的环境。友善提供了两种Bootloader,基于Samsung的u-boot做了一点修改的和友善自己开发的SuperLoader,SuperLoader功能比较强大,但是不开源,可以免费使用;但是如果我们自己想做一些改变的话,那就有点困难了。

由Bootloader引导后,系统加载内核,内核加载后加载文件系统,之后执行init程序,但是友善直接修改了内核的配置,直接运行linuxrc程序(其实是busybox),然后就开始执行init.d下的rcS脚本。下面将通过内核配置和脚本来介绍它启动的一些细节。

在友善提供的文件系统中的.config中,可以看到启动执行的程序被修改为linuxrc,而且linuxrc只是busybox的一个符号链接,如下:

init.d目录下的启动脚本

rcS启动脚本注解

#! /bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:
runlevel=S
prevlevel=N
umask 022
#导出环境变量和运行级别
export PATH runlevel prevlevel
#
#       Trap CTRL-C &c only in this shell so we can interrupt subprocesses.
#
trap ":" INT QUIT TSTP
#设置主机名称
/bin/hostname friendARM
[ -e /proc/1 ]    || /bin/mount -n -t proc  none /proc
[ -e /sys/class ] || /bin/mount -n -t sysfs none /sys
[ -e /dev/tty ]   || /bin/mount    -t ramfs none /dev
/bin/mount -n -t usbfs none /proc/bus/usb

echo /sbin/mdev > /proc/sys/kernel/hotplug

#udev实现U盘或SD卡的自动挂载,mdev是busybox中的一个udev管理程序的一个精简版,他也可以实现设备节点的自动创建和设备的自动挂载
/sbin/mdev -s
/bin/hotplug

# mounting file system specified in /etc/fstab
mkdir -p /dev/pts
mkdir -p /dev/shm
/bin/mount -n -t devpts none /dev/pts -o mode=0622
/bin/mount -n -t tmpfs tmpfs /dev/shm
/bin/mount -n -t ramfs none /tmp
/bin/mount -n -t ramfs none /var
mkdir -p /var/empty
mkdir -p /var/log
mkdir -p /var/lock
mkdir -p /var/run
mkdir -p /var/tmp

/sbin/hwclock -s
syslogd

#启动网络配置
/etc/rc.d/init.d/netd start
echo "                        " > /dev/tty1
echo "Starting networking..." > /dev/tty1
sleep 1

#启动httpd
/etc/rc.d/init.d/httpd start
echo "                        " > /dev/tty1
echo "Starting web server..." > /dev/tty1
sleep 1

#启动Led模块
/etc/rc.d/init.d/leds start
echo "                        " > /dev/tty1
echo "Starting leds service..." > /dev/tty1
echo "                        "
sleep 1
echo "                        " > /dev/tty1

#alsaconf,看了启动的程序发现是一些默认的配置项
/etc/rc.d/init.d/alsaconf start
echo "Loading sound card config..." > /dev/tty1
echo "                        "

#配置网络相关地址
/sbin/ifconfig lo 127.0.0.1
/etc/init.d/ifconfig-eth0

#启动QT图形界面
/bin/qtopia &
echo "                                  " > /dev/tty1
echo "Starting Qtopia, please waiting..." > /dev/tty1

一条评论

搞笑视频—《甩饼歌》

十二 26 2011 由 创建在标签 娱乐

2011网络热词和事件。

 

一条评论

磁盘——磁盘基础

十二 24 2011 由 创建在标签 开发, 电脑维护

磁盘是广为应用的保存大量数据的存储设备,存储数据的数量级可以达到几百到几千千兆字节,而基于RAM的存储器只能有几百或几千兆字节。不过,从磁盘上读信息的时间为毫秒级,从DRAM读比从磁盘读快10万倍,从SRAM读比从磁盘读快100万倍。

1、磁盘构造

磁盘是由盘片(platter)构成的。每个盘片有两面或者成为表面,表面覆盖着磁性记录材料。盘片中央有一个可以旋转的主轴(spindle),它使得盘片以固定的旋转速率旋转,通常是5400~15000转每分钟(Revolution Per Minute, RPM)。 磁盘通常包含一个或多个这样的盘片,并封装在一个密封的容器内。

磁道(track):当磁盘旋转时,磁头若保持在一个位置上,则每个磁头都会在磁盘表面划出一个圆形轨迹,这些圆形轨迹就叫做磁道;

扇区(sector):每个扇区包含相等数量的数据位(通常是512字节),这些数据编码在扇区上的磁性材料中。扇区之间由一些间隙(gap)分隔开,这些间隙中不存储数据位。间隙存储用来标识扇区的格式化位。

磁盘制造商通常用术语柱面(cylinder)来描述多个盘片驱动器的构造,这里柱面是盘面表面上到主轴中心的距离相等的磁道的集合。例如,如果一个驱动器有三个盘片和六个面,每个表面上的磁道的编号都是一致的,那么柱面k就是六个磁道k的集合。

2、磁盘容量

一个磁盘上可以记录的最大位数称为它的最大容量,或者简称容量。磁盘容量是由以下技术因素决定:

  • 记录密度(recording density 位/英寸):磁道一英寸的段中可以放入的位数;
  • 磁道密度(track density 道/英寸):从盘片中心出发半径上一英寸的段内可以有的磁道数;
  • 面密度(areal densiy 位/平方英寸):记录密度与磁道密度的乘积;

磁盘制造商不懈的努力以提高面密度(从而增加容量),而面密度每隔几年就会翻倍。最初的磁盘,是在面密度很低的时代设计的,将每个磁道分为数目相同的扇区,扇区的数目是由最靠内的磁道能记录的扇区数决定的。为了保持每个磁道有固定的扇区数,越往外的磁道扇区隔得越开。

在面密度相对比较低的时候,这种方法还算合理。不过,随着面密度的提高,扇区之间的间隙(那里没有存储数据位)变得不可接受的大。因此,现代大容器磁盘使用一种称为多区记录(multiple zone recording)的技术,在这种技术中,柱面的集合被分割成不相交的子集合,称为记录区(recording zone)。每个区包含一组连续的柱面。一个区中的每个柱面中的没跳磁道都有相同数量的扇区,这个扇区的数量是由该区域中最里面的磁道所能包含的扇区数确定的。注意,软盘仍然使用的是老式的方法,每条磁道的扇区数是常数。

下面的公式给出了一个磁盘的容量:

3、磁盘操作

磁盘用读/写头来读写存储在磁性表面的位,而读写头连接到一个传动臂(actuator arm)一端,如下图中a所示。

通过沿着半径轴前后移动这个传动臂,驱动器可以将读/写头定位在盘面上的任何磁道上。这样的机械运动称为寻道(seek)。一旦读/写头定位到了期望的磁道上,那么当磁道上的每个位通过它的下面时,读/写头可以感知到这个位的值(读该位),也可以修改这个位的值(写该位)。有多个盘片的磁盘针对每个盘面都有一个独立的读/写头,如上图(b)所示。读写头垂直排列,一致行动。在任何时刻,所有的读写头都位于同一个柱面上。

在传动臂末端的读写头在磁盘表面高度大约0.1微米处的一层薄薄的气垫上飞翔,速度大约为80km/h。这可以比喻成将sears tower(一座位于芝加哥的108层和442米高的摩天大楼)放倒,然后让他在距离地面2.5cm的高度上飞行环绕地球,绕地球一天只需要8秒钟!在这样小的间隙里,盘面上一粒微小的灰尘都像一块巨石。如果读写头碰到了这样的一块巨石,读写头会停下来,撞到盘面——所谓的读写头冲撞(head crash)。为此磁盘总是密封包装的。

磁盘以扇区大小的块来读写数据。对扇区的访问时间(access time)有三个主要的部分:寻道时间、旋转时间和传送时间:

  • 寻道时间:为了读取某个目标扇区的内容,传动臂首先将读写头定位到包含目标扇区的磁道上。移动传动臂所需的时间成为寻道时间。寻道时间依赖于读写头以前的位置和传动臂在盘面上移动的速度。现代驱动器中平均寻道时间是通过对几千次对随机扇区的寻道求平均值来测量的,通常为3~9ms。一次寻道的最大时间可以高达20ms。
  • 旋转时间:一旦读写头定位到了期望的磁道,驱动器等待目标扇区的第一个位旋转到读写头下。这个步骤的性能依赖于当读写头到达目标扇区时盘面的位置和磁盘的旋转速度。在最坏的情况下,读写头刚刚错过了目标扇区,必须等待磁盘转一整圈。
  • 传送时间:当目标扇区的第一个位位于读写头下时,驱动器就可以开始读或者写该扇区的内容了。一个扇区的传送时间依赖于旋转速度和每条磁道的扇区数目。

关于平均旋转时间和平均传送时间都有公式计算,而平均寻道时间参数一般会给定。

这样可以通过计算得出一些结论:

  • 访问一个磁盘扇区中一定字节的时间主要是寻道时间和旋转延迟。访问扇区中的第一个字节用了很长时间,但是访问剩下的字节几乎不用时间。
  • 因为寻道时间和旋转延迟大致是相等的,所以将寻道时间乘以2是估计磁盘访问时间的简单而合理的方法。
  • 对存储在SRAM中的双字的访问时间大约是4ns,对DRAM的访问时间是60ns。因此,从存储器中读一个512字节扇区大小的块的时间对SRAM 来说大约是256ns,对DRAM来说大约是4000ns。磁盘访问时间,大约10ms,比SRAM大约大40000倍,比DRAM大大约2500倍。如果我们比较访问一个简单字的时间,这些访问时间的差别会更大。

4、逻辑磁盘块

正如我们看到的那样,现代磁盘构造复杂,有多个盘面,这些盘面上有不同的记录区。为了对操作系统隐藏这样的复杂性,现代磁盘将它们的构造呈现为一个简单的视图,一个B个扇区大小的逻辑块的序列,编号为0,1,…,B-1。磁盘中有一个小的硬件/固件设备,称为磁盘控制器,维护着逻辑块号和实际(物理)磁盘扇区之间的映射关系。

当操作系统想要执行一个I/O操作时,例如读一个磁盘扇区的数据到主存,操作系统会发送一个命令到磁盘控制器,让它读某个逻辑块号。控制器上的固件执行一个快速表查找,讲一个逻辑块号翻译成一个(盘面,磁道,扇区)的三元组,这个三元组唯一的标识了对应的物理扇区。控制器上的硬件解释这个三元组,将读写头移动到适当的柱面,等待扇区移动到读写头下,将读写头感知到的位放到控制器上的一个小缓冲区中,然后将他们拷贝到主存中。

5、连接到I/O设备

虽然I/O总线比系统总线和存储器总线慢,但是它可以容纳种类繁多的第三方I/O设备。

通用串行总线(USB)控制器是一个连接到USB总线的设备的中转机构,USB总线是一个广泛使用的标准,连接各种外围I/O设备,包括键盘鼠标、调制解调器、数码相机、游戏操纵杆、打印机、外部磁盘驱动器和固态硬盘。USB 2.0 总线的最大带宽为60MB/s。USB 3.0的最大带宽为600MB/s。

主机总线适配器将一个或多个磁盘连接到I/O总线,使用的是一个特别地主机总线接口定义的通信协议。两个最常用的这样的磁盘接口是SCSI(读作“scuzzy”)和SATA。SCSI磁盘通常比SATA驱动器更快但是更贵。SCSI主机总线适配器(通常称为SCSI控制器)可以支持多个磁盘驱动器,SATA适配器只能支持一个驱动器。

其他设备,如网卡,可以通过插入主板上的扩展槽中,从而连接到I/O总线,这些插槽提供了到总线的直接电路连接。

6、访问磁盘

CPU使用存储器映射I/O(memory-mapped I/O)的技术来向I/O设备发出命令。在使用存储器映射I/O的系统中,地址空间中有一块地址是为与I/O设备通信保留的。每个这样的地址称为一个I/O端口(I/O port)。当一个设备连接到总显示,它与一个或多个关口相关联(或它被映射到一个或多个端口)。

  1. CPU通过将命令、逻辑块号和目的存储器地址写到与磁盘相关联的存储器映射地址,发起一个碰盘读;
  2. 磁盘控制器读扇区,并执行到主存的DMA传送;
  3. 当DMA传送完成时,磁盘控制器用中断的方式通知CPU

作为一个简单的例子,假设磁盘控制器被映射到端口0xa0。随后,CPU可能通过执行三个对地址0xa0的存储指令,发起磁盘读:第一条指令是发送一个命令字,告诉磁盘发起一个读,同时还发送了其他的参数,例如当读完成时,是否中断CPU。第二条指令知名应该读的逻辑块号。第三条指令指明应该存储磁盘扇区内容的主存地址。

当CPU发起了请求之后,在磁盘执行读的时候,它通常会做些其他的工作。回想一下,一个1GHz的处理器的时钟周期为1ns,在用来读磁盘的16ms时间里,它潜在的可执行1600万条置零。在传输进行时,只是简单地等待,什么都不做,这是种极大的浪费。

在磁盘控制器收到来自CPU的读命令之后,它将逻辑块号翻译成一个扇区地址,读该扇区的内容,然后将这些内容直接传送到主存,不需要CPU的干涉。设备可以自己执行读或者写总线事务,而不需要CPU干涉的过程,这个过程称为DMA(direct memory access)直接存储器访问。这种数据传送称为DMA传送。

在DMA传送完成,磁盘扇区的内容被安全的存储在主存中以后,磁盘控制器通过给CPU发送一个中断信号来通知CPU。基本思想是中断会发信号到CPU芯片的一个外部引脚上。这会导致CPU暂停它当前正在做的工作,跳转到一个操作系统例程。这个程序会记录下I/O已经完成,然后将控制返回到CPU被中断的地方。

注:本文由同实验室的冯建辉整理,我看着不错就拿过来分享了,在这里先感谢一下。

一条评论

Linux 模块

十二 24 2011 由 创建在标签 开发

1、模块简述

模块是内核的一部分(通常是设备驱动程序),但是并没有被编译到内核里面去。它们被分别编译并连接成一组目标文件,这些文件能被插入到正在运行的内核,或者从正在运行的内核中移走,进行这些操作可以使用insmod(插入模块)或rmmod(移走模块)命令。

使用模块有如下几个优点:

  • 模块化编程的需要,降低开发和维护成本。
  • 增强系统的灵活性,使得修改一些内核功能而不必重新编译内核和重启系统。
  • 降低内核编程的复杂性,使入门门槛降低。

同时也列出模块的一些缺点:

  • 对系统性能和内存利用有负面影响;
  • 装入的内核模块和其他内核一样,具有相同的访问权限,因此差的内核模块会导致系统崩溃;
  • 有些模块要求利用其他模块的功能,因此内核要维护模块之间的依赖性;
  • 内核必须能够在卸载模块时通知模块,并且要释放分配给模块的内存和中断等资源;
  • 内核版本和模块版本的不兼容也可能导致系统崩溃(内核版本不同时,部分接口需要替换);

但是对于驱动开发的过程中可以在运行时加载和移除模块显示得尤为重要,这样很容易让模块加载到内核中,而不必在编译的时候将模块编译进去,做过Linux裁剪的都应该知道编译内核是比较烦的一件事情,而且驱动程序开发中很容易出现问题,一旦出现问题就要重新编译。采用模块的方式可以很好地避免内核的重新编译,直到驱动版本稳定后可以将驱动加入至内核。可以大幅提高开发的效率。

2、模块常用的一些命令

3、常用的函数和宏

模块加载函数:  (必须)

模块卸载函数:   (必须)

模块参数:

在模块插入时:

eg:

导出符号

模块声明

4、模块的Makefile

下面是只包含一个文件的模块中所写出的Makefile:

如果一个模块包括多个.c文件(如file1.c, file.c),则应该以如下方式编写Makefile

附录

最简单的Hello模块代码:

/**
 *  Hello.c
 */
#include <linux/init.h>
#include <linux/module.h>

static int hello_init(void)
{
    printk(KERN_INFO " Hello World enter\n");
    return 0;
}

static void hello_exit(void)
{
    printk(KERN_INFO " Hello World exit\n ");
}

module_init(hello_init);
module_exit(hello_exit);

MODULE_AUTHOR("XXX");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("A simple Hello World Module");
MODULE_ALIAS("a simplest module");

无评论