linux学习中
分类: LINUX
2010-05-04 11:36:37
刚学会 ARM 不久,就遇到很多工程师在学习和使用 Linux,当时很是好奇和羡慕!注意到几乎所有工 程师都拥有《GNU/Linux 编程指南》,故也买来收藏着,看了些介绍性的篇幅,也有了在 PC 机上装个 Linux 系统的念头。由于对 RedHat 还不了解,包括基本的操作,于是买了本《Redhat9.0 入门》,在电脑城找了 张 Readhat9.0 光盘(现在肯定找不到了,去网上下吧),还担心在原来硬盘上安装会破坏原来的数据(担 心是多佘的,后来都用 PartitionMagic 在原盘符下直接分区),于是花了 75 元买了 8.4G 的旧硬盘,就这 样回家瞎玩起来。后来又买了本《Redhat9.0 系统管理》,应付 RedHat9.0 的基本操作已经足够。熟悉一两 个星期的 Redhat9.0 基本操作与环境后,是该玩点深入的东东了,觉得自己将来应该是先以嵌入式 Linux 驱动为主,而不是应用编程,所以在还没有进一步学习《GNU/Linux 编程指南》的情况下,就买《Linux 设 备驱动程序》钻研(后来证明这是错误的,有些急功近利)。《Linux 设备驱动程序》看的比较费劲,通读 了一遍后,在 PC 机做的第二个实验就遇到了困难,编译总是出错。去书店参考其它驱动的书,上网查找等 试了很多方法都没有解决,困惑了很久。后来又开始研读《GNU/Linux 编程指南》,读了这本书,再翻《Linux 设备驱动程序》就轻松多了。问题没有解决总会有个结,会时常有针对性的去书店翻些相关的书,上网查 些资料等。在了解到了内核源码树结构,编译等之后,才知道驱动和应用程序是有区别的,是属于内核级, 在编译时要指定 Linux 内核源代码树下的头文件(–I/usr/src/linux-2.4/include),问题就这样解决, 以后的学习、实验都变得顺利了,出现问题基本都能很快排除。总结这阶段的学习顺序,我觉得应该是: 首先,在 PC 机上安装 Linux 系统,再买本相应的入门书籍,主要是熟悉 Linux 环境,学习常用的命令和操
作(不一定多,基本、常用的就可以,以后在使用过程中慢慢积累),理解各目录结构与作用等。其次,学 习在 Linux 环境下编程,《GNU/Linux 编程指南》就可,它会介绍文件描述符的概念,打开、读、写等操作 的系列基础知识,没有这些基础而直接看《Linux 设备驱动程序》会觉得累。后来研读了《UNIX 环境高级 编程》,觉得也很好,它讲了很多前者没有的细节。再次,拿本内核的书翻翻,了解一下 linux 内核源代码 树的目录结构,编译等。最后学习《Linux 设备驱动程序》,理解驱动程序的结构框架等。注:我觉得学习 不需要都直接记住,有点不现实(但应该理解,不要留下疑问,如果有,应及时的用实验去证实再记录), 在以后的应用中再查阅巩固,这阶段也不例外。
1. 如何修改在开机引导装载程序中,等待自动登录默认操作系统的时间? 答:如果引导装载程序是 GRUB,则修改/etc/grub.conf 文件中的 timeout=秒数。 如果引导装载程序是 LILO, 则修改的是/etc/lilo.conf 文件。可用 vi 等编辑器修改,下同。
2. 在字符(Text)模式下,如何关机、重启、注销?
答:关机:poweroff 或 shutdown –h now;重启:reboot 或 shutdown –r now;注销(即重新登入):logout; 其中在 shutdown 指令中的now 是指现在就执行,也可以指定多少时间后再执行此命令。
3. U 盘的使用
答:先创建/mnt/usb 目录,再执行 mount /dev/sda1 /mnt/usb 挂载,此时/mnt/usb 就是 U 盘的目录,在 拔出 U 盘时要执行umount /mnt/usb 进行卸载。
4. 在字符模式(Text)下,如何进入 X Window 模式(Graphic)?在 X Window 模式下,如何返回字符模式? 答:执行 startx 命令 启动 X Window 模式;鼠标点击“Main Menu(主菜单)->Log out(注销)”打开对话框 中,选择“注销”进入字符模式;或CRTL+ALT+F1~F6 来进入不同的虚拟控制台(即文本模式下)。
5. 如何重新指定开机默认进入的执行模式(字符或 X Window 模式)? 答:修改/etc/inittab 文件中的内容(id:5:initdefault:)。
其中,5 表示以 X Window 模式(Graphic)登入,3 为字符模式(Text)登入
6. 在字符模式下,如何使用户登入时,系统不要求输入密码?如何恢复或更改用户密码? 答:取消输入密码:passwd –d 用户帐号。如要取消root登入时的密码,则执行passwd –d root。也可 以用vi打开/etc/shadow文件,删除密码的方法取消。恢复或更改密码则执行passwd 用户帐号(如果是取消 自己则不用)命令后会提示输入New password和Retype new password。
7. 字符模式下,如何新增用户帐号?
答:使用“useradd 用户帐号” 命令来增加,但在新增后还不能登入使用,还需要用 passwd 命令来设置 密码后才行。
8. 在 X Window 下,如何选择系统默认使用的语言? 答:鼠标点击“主菜单->系统设置->语言”打开选择语言对话框中选择。
9. 用 ls 等命令查看的内容太多,超过一页时,如何分页显示?
答:可用 ls | more 或 ls | less 进行分页查看。其中,在用 more 浏览时,按空格键(Space)则会显示 下一页的内容;按回车(Enter)键则会向下多显示一行;按 q 键则离开浏览模式。
在用 less 浏览时,按 h 键会出现在线使用说明;按 q 键离开浏览模式。
10.如何获得命令的使用方法?
答:可利用在线手册—man(Manual),用法是输入 man 和待查的命令名称。如要查询 ls 命令的使用方法, 则输入以下命令:man ls。也可以 ls --help
11.搜索文件及目录和搜索包含特定字符串的文件?
答:搜索文件及目录可以用 find 命令,如要在根目录(/)上搜索 apache 文件则输入命令:find / -name apache –print,注意:如果没有指定目录,则系统会以当前的目录为搜索的范围;搜索包含特定字符串的 文件可以用 grep 命令,如要在/etc 目录下搜索包含字符串“password”
的文件则输入:grep –n ‘password’ /etc/*.*,其中加入-n 参数会标出符合指定的字符串的列数,另 外不可指定在目录中搜索,否则会出现错误信息,如上述不能写成:grep –n ‘password’ /etc/ 另外如果想停止搜索可以直接按“Ctrl + C”键结束该命令就可以。现在我常用:grep –ir password /etc
12.控制台间的切换
答:在文本模式下,用 ALT+F1~F6 来分别在 6 个虚拟控制台间切换,它们可分别用不同的用户名登入和执 行不同的命令与程序,如果已经启动了 X Window(如:在文本模式下用”startx”命令启动),则按 ALT+F7 切换到 X Window 图形模式。
在 X Window 图形模式下,用 CRTL+ALT+F1~F6 分别切换到文本模式下的 6 个虚拟控制台。CRTL + ALT + BackSpace 结束图形模式。
因为 linux 是多任务的系统,所以可以在不同的控制台下用不同(或同一)的用户登陆来运行不同的程序。 我觉得这个功能很方便,因为有时在文本模式下,需要打开多个终端来处理显示多个的任务,如:一个终 端运行 minicom 作为目标板的控制,一个终端作为宿主机编译目标板要运行的文件,还有多个终端打开多 个源文件在浏览等等。如果习惯在 X Window 模式下就例外,因为用鼠标右键就可以打开多个终端。
13.查看 PDF 文档和浏览网页?
答:在 X Window 下打开 shell 终端,输入”xpdf filename.pdf”和“mizzo filename.html” 命令分 别查看。注:必须在 X Window 下才能运行这两个程序,文本模式不能运行。
14.查看磁盘使用情况 答:#df –h
15./proc 目录下,几个关于系统资源非常有用的文件
/proc/modules、/proc/ioports、/proc/iomen、/proc/devices、/proc/interrupts、/proc/filesystems
16.关于内核代码调试时输出打印信息的 printk 语句
如:printk(KERN_DEBUG “Here I am : %s :%i\n”, FILE , LINE_&_) ;
printk(KERN_INFO “ Driver Initional \n”) ;等同于 printk(“<6>” “ Driver Initional
\n”) ;
printk( “<1> Hello, World!\n”) ;
没有指定优先级的 printk 语句采用默认日志级别(DEFAULT_MESSAGE_LOGLEVEL)在 kernel/printk.c 中被指 定,根据日志级别,内核可能会把消息输出到当前控制台上。当优先级小于 console_loglevel 整数值时, 消息才会被显示出来。如果系统同时运行了 klogd 和syslogd,则无论 console_loglevel 为何值,都将把 内核消息追加到/val/log/messages 中。console_loglevel 的初始值是DEFAULT_CONSOLE_LOGLEVEL,可以 通过文本文件/proc/sys/kernel/printk 来读取和修改它及控制台的当前日志级别等。也可以简单的输入 下面命令使所有的内核消息得到显示:
#echo 8 > /porc/sys/kernel/printk
17.查看当前正在运行的进程 答:#ps
18.解压缩到指定目录
答:#tar xvzf linutte.tgz –C /linuette
19.当/etc/grub.conf 文件中的内容被修改或破坏时不能正常启动时,如何在 GRUB 引导时修改设置使其 正常启动
答:以修改了/etc/grub.conf 文件中的 vga 项使启动时显示器不能显示为例,在 GRUB 启动引导菜单中 windows XP 和 Red Hat Linux(2.4.20-8)两项中使用键头键选中 linux 系统,不按[Enter],而按[E]键进 入菜单项目编辑器,再使用键头键选中 kernel 项,也按[E]键进行编辑,在行的后面输入 vga=791 fb=on 后按[Enter],最后按[b]键执行命令,并引导操作系统。
20.包管理器 RPM 使用,以 tmake 为例
安装:#rpm –ivh tmake-1.7-3mz.noarch.rpm
升级:#rpm –Uvh tmake-1.7-3mz.noarch.rpm
查询:#rpm –q tmake
删除:#rpm –e tmake
输入minicom启动,或输入minicom –s直接进入设置模式。
2. 设置
1> 选择串口:在选择菜单中的“Serial port setup”,按回车,再按“A”以设置“Serial Device”
(如果使用串口1,则输入/dev/ttyS0,如果您使用串口2,则输入/dev/ttyS1,注意其中的S是大写),按 回车返回。
2> 设置波特率:按“E”键进入设置“bps/par/Bits”(波特率)界面,如果按“I”以设置波特率为
115200,按回车返回。
3> 数据流控制:按“F”键设置“Hardware Flow Control”为“NO”。
其它为缺省设置 ,然后按回车到串口设置主菜单,,选择“Save setup as dfl”,按回车键保存刚 才的设置(保存到“/etc/minirc.dfl),再选择“Exit”退出设置模式,回到minicom操作模式。
此时可像Windows下的超级终端一样使用了。
3. 退出 minicom
按下“Ctrl+A”键,松开后紧接着再按下“Q”键,在跳出的窗口中,选择“Yes”。
4. 其它有用的功能
命令帮助 -- “Ctrl+A”后按 “ Z ” 清屏 -- “Ctrl+A”后按 “ C” 设置 -- “Ctrl+A”后按 “ O ” 发送文件 -- “Ctrl+A”后按 “ S ” 退出 -- “Ctrl+A”后按 “ Q ”
从 NFS 服务器中共享文件又称导出目录,/etc/exports 文件控制 NFS 服务器要导出哪些目录。格式如 下:
共享的目录 可以连接的主机 (读写权限,其它参数) 如果允许目标板(IP:192.168.0.*)挂载主机的/home目录,则/etc/exports 文件的内容如下:
/home 192.168.*.*(rw,sync)
注:如果出现 mount 不成功,可将 sync 去掉试试 更改后要使用如下命令重新载入配置文件:
#/sbin/services nfs reload 或 #/etc/init.d/nfs reload
然后启动 NFS 服务器,命令如下:
/sbin/services nfs start
上面两个命令也可以用下面的一条指令完成,如下:
/sbin/service nfs restart
设置好后也可以通过 mount 自己来测试 NFS 服务设置是否成功。如果本机 IP 为 192.168.0.1,则可以 用 mount 192.168.0.1:/home/mnt,如果 mount 成功,则在/mnt 的目录就可以看到/home 目录下面的东西 了。
下面将宿主机(IP:192.168.0.1)配置的/home 目录挂载到(IP:192.168.0.7)目标板上的/mnt 目 录。
在宿主机启动 minicom 作为目标板的显示终端,启动目标板的 linux 系统,再使用下面命令:
mount –o nolock 192.168.0.1:/home /mnt
注意:如果没有“-o nolock”选项,而直接使用命令:mount 192.168.0.1:/home /mnt 时将出现如 下错误:portmap:server localhost not responding,timed out
目前我都用:mount –t nfs 192.168.0.1:/home /mnt
《GNU/Linux 编程指南》一书的例程是非常全面的,下载它的源代码后,可以直接编译运行,基本上 不会有什么问题。
参考《Linux 设备驱动程序》P25 页,hello.c 源程序如下:
#define MODULE
#include
int init_module(void){
printk (“<1>Hello,world\n”);
return 0;
}
void cleanup_module(void){
printk(“<1>Goodbye cruel world\n”);
} 用以下命令进行编译:
#gcc –c hello.c
#insmod ./hello.o hello,world
#rmmod hello //注:不是#rmmod hell.o
Goodbye cruel world
出现 的问题 :在执行#insmod ./hello.o 时并没出打印出“hello,world”而是出现了下述错 误:./hello:kernel–module version mismatch
hello.o was compiled for kernel version 2.4.20 while this kernel is version 2.4.20-8
原因:模块和内核版本不匹配,即编译内核的编译器与现在编译模块的编译器版本不一致。 解决方法:1>将/usr/include/linux/version.h 文件中的#define… “2.4.20”修改成#define…
“2.4.20-8”(),再重新编译!
2> 用 insmod 的-f(force,强制)选项强行装入模块,如下:insmod –f ./hello.o
3> 因用 vi /usr/include/linux/version.h 查看到定义的内核版本是 2.4.20,而在内核原代码树下
/usr/src/linux-2.4/include/linux/version.h 中定义为 2.4.20-8 版本,所以用如下命令进行编译:gcc –c –I/usr/src/linux-2.4/include hello.c,再装载就 OK! 注:可查看/proc/modules 文件。
驱动程序源代码如下:
/*CharDriver.c*/
#define _NO_VERSION
#include
#include
char kernel_version[] = UTS_RELEASE;
#define KERNEL
#include
#include
#include
#include
#include
#define SUCCESS 0
static int device_read(struct file *file, char *buf, size_t count, loff_t *f_pos);
static int device_open(struct inode *inode, struct file *file);
static void device_release(struct inode *inode, struct file *file);
struct file_operations tdd_fops = {
read: device_read, open: device_open, release: device_release,
};
#define DEVICE_NAME "char_dev" static int Device_Open = 0; unsigned int test_major = 0;
//static char Messaege[1024];
static int device_open(struct inode *inode, struct file *file){
#ifdef DEBUG
printk ("device_open(%p)\n", file);
#endif
if (Device_Open)
return -EBUSY; Device_Open++; MOD_INC_USE_COUNT; return SUCCESS;
}
static void device_release(struct inode *inode, struct file *file){
#ifdef DEBUG
printk ("device_release(%p,%p)\n", inode, file);
#endif
Device_Open--; MOD_DEC_USE_COUNT;
}
static int device_read(struct file *file, char *buf, size_t count, loff_t *f_pos){
int left;
if (verify_area(VERIFY_WRITE, buf, count) == -EFAULT)
return -EFAULT;
for (left = count; left > 0; left--){
put_user(1, buf);
buf++;
}
return count;
}
int init_module(void){
int result;
result = register_chrdev(0, "char_dev", &tdd_fops);
if (result < 0){
printk("char_dev:can't get major number\n");
return result;
}
if (test_major == 0)
test_major = result;
printk ("Hello,I'm in kenel mode\n");
return 0;
}
void cleanup_module(void){
printk("Hello,I'm goint to out\n");
unregister_chrdev(test_major,"char_dev");
} 用下述命令进行编译:
#gcc –O2 -DMODULE –D KERNEL -c CharDriver.c
出现下述错误:
CharDriver.c 18:Tvariable ‘fops’ has initializer but incomplete type CharDriver.c 19:unknown field ‘read’ specified in initializer CharDriver.c 20:unknown field ‘open’ specified in initializer CharDriver.c 20:unknown field ‘release’ specified in initializer CharDriver.c 53:storage size of ‘fops’ isn’t known
原因:在用 gcc 进行编译时,默认搜索的 include 文件路径为/usr/include,但/usr/include/linux/fs.h
中没有定义 file_operations 结构体(可以打开该文件看一下),file_operations 是在原代码树目录
/usr/src/linux-2.4/include 下的 linux/fs.h 中定义,而且用了#ifdef KERNEL 条件编译。因此在编 译时必须指定该目录和定义 KERNEL 。编译命令如下:
#gcc –O2 -DMODULE –D KERNEL__ –I/usr/src/linux-2.4/include -c CharDriver.c
经过编译得到的文件 CharDriver.o 就是设备驱动程序,执行以下命令把它安装到系统中:
#insmod CharDriver.o
如果安装成功,用#vi /proc/devices 打开文件将看到设备 char_dev 和主设备号。如果需要卸载,可运行
#rmmod char_dev
然后就需要创建设备文件了,执行以下命令:mknod /dev/char_dev c 254 0,其中“/dev/char_dev”是 要生成的设备名及目录,选项c 是指字符设备,254 是生成的主设备号,可用上面方法查看到,也可能是
253 或其它,从设备号设成 0 就可以。另外可以用 rm –f /dev/char_dev 将删除 mknod 命令创建的设备文 件。可用下述测试程序源代码进行测试。
驱动的测试程序如下:
/*DriverTest.c*/
#include
#include
#include
#include
int main(int argc, char *argv[]){
int testdev;
int i;
char buf[10];
testdev = open("/dev/char_dev", O_RDWR);
if (testdev == -1){
printf("Cann't open file \n");
exit(0);
}
read(testdev, buf, 10);
for (i = 0; i < 10; i++){
printf("%d\n", buf[i]);
}
close(testdev);
}
需要注意的是将驱动程序数据传给用户程序时是 put_user(1,buf),而不是 put_user(1,buf,1);否则会 出现错误。还有copy_to_user(buf,Buffer++,1)函数的 Buffer 是指针变量,而不是具体的数据,如果写 成 copy_to_user(buf,1,1),也会出错。
公司虽然用 ARM 已经多年,但都是裸奔,产品在功能和性能上的提升都出现了瓶颈,急需软件平台的 突破,这也增大了我的学习动力。过年假期没有回家(尽管妈妈生病刚动完手术,但还是含着泪在电话里 告诉爸爸我的决定),而是抓紧时间专心研究基于 s3c2410 的嵌入式 Linux 平台。硬件是一块普普通通的 s3c2410 开发板,软件选择 MIZI Linux SDK (Software Development Kit) for S3C2410,因为我觉得它是 s3c2410 最原始的平台,国内大部分的开发板都是在它的基础上发展过来,选择它比较可靠,心里也比较
踏实,以后应用于产品也是如此。从 mizi ftp 站点下载的 SDK 光盘,包含了开发板原理图、BOM 表、linux 开发平台所需的所有软件、工具及使用手册等,资料是比较齐全的,完全可以参考它设计出自己的开发板。 下面的软件安装、工具使用等内容摘自和总结于它的操作手册,LED、按键驱动实验的源代码摘自广州友善 之臂科技有限公司的 SBC-2410X-UM.pdf。