【原创论文栏目提醒】:以下是网学会员为您推荐的原创论文-LINUX实验报告_论文(原创) - 其它资料,希望本篇文章对您学习有所帮助。
实 验 报 告课程名称 Linux 系统与编程实验项目 Linux 系统与编程小
论文实验仪器 系 别___ 计算机学院______ 专 业 班级/学号 学生姓名 _____ ___ 实验日期 成 绩 __ __________ _ 指导教师 _ __ ________ Linux 系统编程小
论文1——VFS 简述如何在 VFS 中管理文件。
并说明相关 shell 命令及系统调用接口。
虚拟文件系统 VFS 作为内核子系统,为用户空间程序提供了文件系统相关的接口。
系统中所有文件系统不但依赖 VFS 共存,而且也依靠 VFS 系统协同工作。
通过虚拟文件系统,程序可以利用标准的 UNIX 文件系统调用对不同介质上的不同文件系统进行读写操作。
它负责完成所有安装文件系统的管理和控制包括文件系统的安装,卸载等等。
它是一种软件机制,也许称它为 Linux 的文件系统管理者更确切点,与它相关的数据结构只存在于物理内存当中。
所以在每次系统初始化期间,Linux 都首先要在内存当中构造一棵 VFS 的目录树,实际上便是在内存中建立相应的数据结构。
VFS 目录树在 Linux 的文件系统模块中是个很重要的概念。
VFS 使得用户可以直接使用 open、read和 write这样的系统调用而无需考虑具体文件系统和实际物理介质。
也许我们现在听起来这并没什么新奇的。
大部分人早就认为这是理所当然的。
但是,使得这些同通用的系统调用可以跨所有介质和文件系统执行,绝非是微不足道的成绩。
更为了不起的是,系统调用可以在这些不同的文件系统和介质之间执行——我们可以用标准的系统调用从一个文件系统拷贝或移动数据到另一个文件系统。
正是由于包括 Linux 在内的现代操作系统引入了抽象层,通过虚拟接口访问文件系统,才使得这种协作性和通用性成为可能。
VFS 即虚拟文件系统是 Linux 文件系统中的一个抽象软件层;因为它的支持,众多不同的实际文件系统才能在 Linux 中共存,跨文件系统操作才能实现。
VFS 借助它四个主要的数据结构即超级块、索引节点、目录项和文件对象以及一些辅助的数据结构,向 Linux 中不管是普通的文件还是目录、设备、套接字等都提供同样的操作界面,如打开、读写、关闭等。
只有当把控制权传给实际的文件系统时,实际的文件系统才会做出区分,对不同的文件类型执行不同的操作。
由此可见,正是有了 VFS 的存在,跨文件系统操作才能执行,Unix/Linux 中的“一切皆是文件”的口号才能够得以实现。
通过对 linux 文件系统的学习我了解了一些关于文件系统的命令的执行这对于刚刚接触这个系统的我来说是一个很大的收获下面是我对他们的阐述.mkfs mkfs 命令用来在 Linux 下建立各种文件系统。
使用权限:超级用户。
格式:mkfs -V -t fstype fs-options device size主要选项:-V:输出帮助信息。
-t fstype: 指定要建立何种文件系统。
如没有任何指定,则使用缺省的文件系统类型fs-options:传递给实际的文件系统制作工具的文件系统相关的选项。
Size:是指该文件系统用的区块数。
device:既可以是设备名,(如: /dev/hda1, /dev/sdb2) 也可以是文件系统的挂载点,(如: /, /usr, /home)。
应用说明: mkfs 命令本身并不执行建立文件系统的工作,它是在 Linux 下各文件系统专用程序(mkfs.fstype)的前端程序。
各文件系统专用程序可以在 /sbin、/sbin/fs、/sbin/fs.d等目录中找到。
主要包括:mkfs.dos 用来创建 DOS 文件系统。
mkfs.reiserfs 用来创建reiserfs 文件系统。
mkfs.jfs 用来创建 jfs 文件系统。
mkfs.vfat 用来创建 vfat 文件系统。
fsck fsck 命令用来检查文件系统并尝试修复错误。
使用权限:所有用户。
格式:fsck 选项 -t fstype device主要选项:-a: 自动修复文件系统,不询问任何问题。
-A: 依照/etc/fstab 配置文件的内容,检查文件内所列的全部文件系统。
-N: 不执行指令,仅列出实际执行会进行的动作。
-P: 当搭配-A参数使用时,则会同时检查所有的文件系统。
-r : 采用互动模式,在执行修复时询问问题,让用户得以确认并决定处理方式。
-R: 当搭配-A参数使用时,则会略过/目录的文件系统不予检查。
-s: 依序执行检查作业,而非同时执行。
-t fstype: 指定要检查的文件系统类型。
-T: 执行 fsck 指令时,不显示标题信息。
-V: 显示指令执行过程。
应用说明:和 mkfs 命令类似,fsck 是在 Linux 各文件系统检查程序(fsck.fstype)的前端程序。
出于对 Linux 各个发行版本的兼容性,检查文件系统的命令可能有不同命令名称,如fsck.ext2、fsck.ext3、e2fsck 都是用来检查 ext2/ext3文件系统。
findfs findfs 命令用来查找指定卷标的文件系统。
使用权限:超级用户。
格式:findfs LABELfindfs UUID主要选项:LABEL :卷标名称。
UUID:分区的 UUID 号。
应用说明:随着 Linux 系统中硬盘容量和数目的增加,Linux 系统中分区数量也越来越多,使用 findfs 命令可以通过卷标名称或 UUID 号快速定位分区位置。
应用实例:查找卷标名称是:/var/ftp 的分区位置,使用命令:findfs LABEL/var/ftp/dev/hda9 通过对 Linux 文件系统的学习我对 VFS 有了很深的了解.它是使 linux 支持多种文件系统的统一的接口通过它实现在 linux 系统下的文件的统一性.它是linux 学习中十分重要的一部分为之后的学习打下了很好的基础. Linux 系统编程小
论文2——字符设备驱动程序 程序部分以 Linux Device Driver3 提供的 scull 程序scull 目录中的 main.c 和 scull.h为主线,以该驱动程序中的各种系统调用和函数调用流程为顺序。
module_init 和module_exit 为相对应的一对系统调用.驱动程序module的工作流程主要分为四个部分:1、 用Linux提供的命令加载驱动module2、 驱动module的初始化(初始化结束后即进入“潜伏”状态,直到有系统调用)3、 当操作设备时,即有系统调用时,调用驱动module提供的各个服务函数4、 卸载驱动 module 以下为操作设备时的代码之后有分析 scull.h ------------------ ifndef __SCULL_H define __SCULL_H define SCULL_MAJOR 252 int scull_majorSCULL_MAJOR endif scull.c ------------------ include include include include scull.h MODULE_LICENSEGPL int scull_openstruct inode inodestruct file filp int scull_releasestruct inode inodestruct file filp int scull_readstruct file filpchar bufsize_t countloff_t f_pos int scull_writestruct file filpconst char bufsize_t countloff_t f_pos struct file_operations scull_fops read: scull_read write: scull_write open: scull_open release: scull_release int init_modulevoid int result printk scull initilized.n resultregister_chrdevscull_majorscullscull_fops ifresultprivate_data里的数据结构open函数的原型如下指的是在file_operations结构体中的定义:int openstruct inode inode struct file filp在驱动开发时要做的,就是为该函数作具体实现,当然对open函数的名称可以自定义,只要在填写file_operations结构体中的open字段时,将自定义的open函数名称填上就可以了。
在scull程序中,用的就是scull_open函数名。
在open函数原型中,有inode和filp两个参数,都是外部应用程序在操作 设备时通过调用系统调用传递给驱动module的。
于是驱动module就可以通过这两个参数来确定要打开的具体设备了。
其实这里所说的具体设备,并不是 说驱动module需要从系统安装的所有设备中确定它所要服务的设备,而是指module需要从某一类拥有相同主设备号的设备中确定它要服务的设备。
之 所以这么说,是因为驱动module是对应于某一个主设备号的所有设备的。
换一句话说,就是Linux内核只管设备的主设备号,而不理会设备的次设备号是 什么,如果有两个,三个或者更多个设备拥有同一个主设备号,那么不管外部应用程序要操作这些设备中的哪一个,Linux内核都只会调用同一个驱动 module。
但是驱动module却不能不管次设备号了,因为它是跟某一个具体的设备打交道的,所以它需要根据open系统调用时传递给它的参数中找到次设备号,从而确定那唯一的一个设备(也许驱动module也可以同时操作几个设备,但一时也想不起来)。
但是上面所说的通过次设备号找到具体的设备, 只是其中一种方法;另外还有一种方法就是通过cdev结构体确定某个具体设备。
设 备所拥有的cdev结构体,或者次设备号,都保存在open函数的inode参数中。
我们可以使用container_of宏通过inode所拥有的 cdev确定具体设备,也可以使用iminor宏从inode所拥有的i_rdev确定次设备号i_rdev是inode结构体中的一个dev_t类型 的变量, 其中保存了真正的设备主次编号。
对于open函数中的file参数,scull程序主要用它来做两件事:其一是将 根据cdev获得的代表设备的scull_dev结构体保存到file-private_data中,这样就可以方便今后对该设备结构体的访问 了,而不用每次都调用container_of宏或者iminor宏来找到设备结构体了;其二是根据file结构体中的f_flags字段来确定,这次的 open调用,是以写方式打开设备,还是以读方式来打开设备。
2、read函数驱动module的file_operations结构体中可以定义很多设备操作服务函数,但是我现在关心的是这些函数怎样与系统调用,或者说是外部应用程序交互,而不管具体的设备操作怎么实现,所以只记录read函数作为代表。
read函数的原型如下:ssize_t readstruct file filp char __user buf s ize_t count lo ff_t f_posread函数原型中有4个参数,分别是filp,buf,count和f_pos。
其中file结构体指针参数可以用来确定我们要操作的设备,因为在open函数中,我们将代表设备的结构体保存到了filp的private_data字段中。
buf 参数是一个指向用户空间的buffer的指针buf前面的__user表示用户空间,对于read来说,就是可以把要传送给外部应用程序的数据放入这 个buffer中。
当然,我们不能简单地将数据copy到这个buffer中,而是要使用Linux内核提供的一些函数,比如copy_to_user函 数。
count是请求传送的数据长度。
f_pos是一个指向“long offset type”对象的指针,指明外部应用程序在文件中进行存取操作的位置。
read函数的返回值是有符号整数类型的指,一般是read操作的实际存取数。
3、release函数release函数的作用正好与open相反, 而 有时候release函数的实现被称为device_close, 不是device_release。
但无论那种形式,这个设备方法都应该完成如下任务:a、释放open分配的,保存在file-private_data中的所有内容。
b、在最后一次关闭操作时关闭设备。
relese函数由close系统调用引起,但并不是每一次close系统调用都 会引起release函数的调用。
只有那些真正释放设备数据结构的close系统调用才会引起release函数的调用。
因为Linux内核为每个 file结构体维护其被引用多少次的计数器, 只有当file结构体的计数器归0时,close系统调用才会引用release函数,这只在删除这个结构时 才会发生,因此每次open驱动程序都只会看到一次对应的一次release调用。
1、上网下载一个基于 linux 操作系统的设备驱动程序源代码,了解其 中包含的系统调用的功能和作用,写好程序分析报告(其中包括 。
以系统调用基本过程为主线)二答:这是一个关于阻塞的问题对 read 调用存在一个问题,就是当设备无数据可读时,解决的方法有两种,一是不阻塞直接读失败跳出。
二就是阻塞读操作,进程进入睡眠,等待有数据时唤醒。
这里探讨一下阻塞型 IO,处理睡眠和唤醒。
睡眠就是当一个进程需要等待一个事件时,应该暂时挂起,让出 CPU,等事件到达后再唤醒执行。
处理睡眠的一种方法是把进程加入等待队列:1首先需要申明和初始化一个等待队列项.includewait_queue_head_t my_queueinit_waitqueue_headmy_queue如果是申明一个静态全局的等待队列,可以不用上面两个定义,直接使用DECLARE_WAIT_QUEUE_HEADmy_queue //静态申明将在编译时自动被初始化2使用已初始化的等待队列项在 需 要 加 入 内 核 等 待 队 列 时 , 调 用 interruptible_sleep_onmy_queue 或 者sleep_onmy_queue在 需 要 唤 醒 时 , 调 用 wake_up_interruptiblemy_queue 或 者wake_upmy_queue3interruptible_sleep_on的缺陷a.引起的竞态:要了解 interruptible_sleep_on等这些 sleep_on 函数可能引起的竞态,就需要多interruptible_sleep_on的实现有个认识。
等 待 队 列 其 实 是 一 个 队 列 链 表 , 链 表 中 的 数 据 是 类 型 wait_queue_t. 简 化 了 的interruptible_sleep_on内部大概是这样:includewait_queue_t wait //定义一个等待队列init_wait_queue_entrywait current //初始化current-state TASK_INTERRUPTILBE //设置为休眠状态,将要进入睡眠add_wait_queuemy_queue wait //把我们定义的等待队列项加入到这个等待队列中schedule //真正进入睡眠remove_wait_queuemy_queue wait //事件到达,schedule返回竞态就发生在 current-state TASK_INTERRUPTIBLE 和 schedule之间,在一些情况下,当驱动准备进入睡眠,即已经设置了 current-state 时,可能刚好有数据到达,这个时候 wake_up 是不会唤醒这个还没有真正进入睡眠的进程, 这样就可能造成该进程因为没有响应唤醒一直处于睡眠,这样就产生这个竞态,这个竞态也是很容易发生的。
解决办法就是不使用 interruptible_sleep_on,而是直接使用它的内部实现。
例如:includewait_queue_t wait //定义一个等待队列init_wait_queue_entrywait current //初始化add_wait_queuemy_queue wait //把我们定义的等待队列项加入到这个等待队列中while1current-state TASK_INTERRUPTILBE //设置为休眠状态,将要进入睡眠if short_head short_tail break //测试是否有数据到达如果有,跳出schedule //真正进入睡眠set_current_stateTASK_RUNNINGremove_wait_queuemy_queue wait //事件到达,schedule返回事实上,可以不用我们做这些复杂的事情,内核定义了一个宏wait_event_interruptiblewq condition 或 者 wait_eventwq conditioncondition 就是测试的条件b.关于排它睡眠:存在这样一种情况,几个进程都在等待同一个事件,当事件到达调用 wake_up 时,等待在这个事件上的所有进程都被唤醒,但是假如该事件只需要被一个进程处理, 其它进程只是被唤醒后接着又进入睡眠,这样很多进程运行,导致上下文切换,造成系统变慢。
解决办法是通过直接对等待队列的链表操作 指定排它睡眠,内核把这个队列放在其它非排它睡眠之前,当事件到达时如果遇到排它睡眠的队列,唤醒它后即结束,其它睡眠下一次被唤醒处理。
事实上 sleep_on 的一系列函数都是对等待队列的链表操作。
链表中数据项是类型为wait_queue_t 的数据。
直接操作链表设置排它睡眠方法大概如下:includewait_queue_t wait //定义一个等待队列init_wait_queue_entrywait current //初始化current-state TASK_INTERRUPTALBE TASK_EXCLUSIVE //设置为排它add_wait_queue_exclusivequeue wait //把我们定义的等待队列项加入到这个等待队列中schedule //进入睡眠remove_wait_queuequeue wait //事件到达,schedule返回c.在多个队列中睡眠interrruptible_sleep_on 等函数只能在一个队列中睡眠, 如果真的需要做到在多个等待队列中睡眠,只能通过直接操作等待队列链表。
这个技巧找到相关资料再看看。
本次实验主要学习了关于 8255 的应用实验是在上两次实验的基础上完成的。
实验一共分为两个小环节。
第一段程序完成的是,把端口 B 直接接到端口 A 上作为输出使输出二极管按照所对应的控制开关亮暗。
第二段程序端口 B 先将程序存在其中,待有中断信号时,将B 口数据输出到 A,即按下 KK1。
这次实验基于 8259 的初始化。
在这个问题上,老师给我们讲了关于它的初始化。
首先8259 要完成对中断向量的设置。
中断向量采用的 ICW2 的方式,以中断基址(08H)的前 5 )位,和中断源的后三位(IRQ7 中的“7”,所组成的中断向量地址经左移两位,得到终端类型号。
这个地址的前两个字节记录了 IP即中断入口地址用 OFFSET 将其给入地址,后两个字节记录了 CS。
之后 ,8259 会进行 ICW1 和 ICW4 进行设置。
在 ICW4 设置过程中,要考虑中断子程序是否要用,因为 ICW4 倒数第二位表示了此程序是否为非自动调整清服务寄存器 ISR中的“1”位为 0。
如果为非自动模式,则需要加入一段中断子程序。
在程序编写过程中,我遇到了很多困难。
比如中断入口设置不正确,编程思路有问题等等。
这些问题都在老师耐心的指导下完成了。
老师的指点使我在编程方面有了很大的自信, 同时也学到了很多课外的知识, 让我对这门课程产生了极大的兴趣。
同时也对我今后的学习有了很大的帮助, 我会在之后的实验中更加努力,达到老师的要求。
上一篇:
【原创】会计学专业毕业论文格式模板
下一篇:
餐饮管理系统