ICS计算机基础教学课件第八章输入输出操作的实现.pptx
《ICS计算机基础教学课件第八章输入输出操作的实现.pptx》由会员分享,可在线阅读,更多相关《ICS计算机基础教学课件第八章输入输出操作的实现.pptx(76页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、I/O操作的实现操作的实现用户空间I/O软件I/O硬件与软件的接口内核空间I/O软件I/O和文件操作和文件操作主要教学目标通过揭示高级语言程序中的I/O及文件操作请求的底层实现机制,使学生深刻理解OS在输入/输出系统中的重要作用;深刻理解计算机中硬件和软件如何协调工作以完成计算机功能。主要教学内容I/O子系统的组成和层次结构用户空间I/O软件I/O硬件与软件的接口内核空间I/O软件I/O操作的实现操作的实现分以下三个部分介绍第一讲:用户空间I/O软件-I/O子系统概述-文件的基本概念-用户空间的I/O函数第二讲:I/O硬件和软件的接口-I/O设备和设备控制器-I/O端口及其编址方式-I/O控制
2、方式第三讲:内核空间I/O软件-与设备无关的I/O软件-设备驱动程序-中断服务程序复习:一个典型程序的转换处理过程复习:一个典型程序的转换处理过程#includeintmain()printf(hello,worldn);经典的“hello.c”源程序#i n c l u d e n n i n t m a i n ()n 104 62 10 10 105 110 116 32 109 97 105 110 40 41 10 123n p r i n t f(h e l10 32 32 32 32 112 114 105 110 116 102 40 34 104 101 108l o ,w
3、o r l d n );n 108 111 44 32 119 111 114 108 100 92 110 34 41 59 10 125hello.c的的ASCII文本表示文本表示复习:复习:Hello程序的数据流动过程程序的数据流动过程“hello”Hello可执行文件Red:shell命令行处理Blue:可执行文件加载Cyan:hello程序执行过程“hello”“hello,world/n”“hello,world/n”问题:hello程序何时被装?谁来装入?被谁启动?每次是否被装到相同的地方?Hello程序是否能直接访问硬件资源?Unix./hellohello,worldunix
4、操作系统在程序执行过程中的作用操作系统在程序执行过程中的作用Shell进程生成子进程,子进程调用execve系统调用启动加载器,以装入Hello程序,最后跳转到第一条指令执行在Hello程序执行过程中,Hello本身不会直接访问键盘、显示器、磁盘和主存储器等硬件资源,而是依靠OS提供的服务来间接访问。操作系统是在应用程序和硬件之间插入的一个中间软件层。操作系统的两个主要的作用:硬件资源管理,以达到以下两个目的:-统筹安排和调度硬件资源,以防止硬件资源被用户程序滥用-对于广泛使用的复杂低级设备,为用户程序提供一个简单一致的使用接口为用户(最终用户、用户程序)使用系统提供一个操作接口例如,利用例如
5、,利用printf()函数最终调出内核服务程序访问硬件。函数最终调出内核服务程序访问硬件。I/O子系统概述子系统概述所有高级语言的运行时(runtime)都提供了执行I/O功能的机制例如,C语言中提供了包含像printf()和scanf()等这样的标准I/O库函数,C+语言中提供了如(输出)这样的重载操作符。从高级语言程序中通过I/O函数或I/O操作符提出I/O请求,到设备响应并完成I/O请求,涉及到多层次I/O软件和I/O硬件的协作。I/O子系统也采用层次结构从用户I/O软件切换到内核I/O软件的唯一办法是“异常”机制:系统调用(自陷)I/O子系统概述子系统概述 各类用户的I/O请求需要通过
6、某种方式传给OS:最终用户:键盘、鼠标通过操作界面传递给OS 用户程序:通过函数(高级语言)转换为系统调用传递给OSI/O软件被组织成从高到低的四个层次,层次越低,则越接近设备而越远离用户程序。这四个层次依次为:(1)用户层I/O软件(I/O函数调用系统调用)(2)与设备无关的操作系统I/O软件(3)设备驱动程序(4)I/O中断处理程序大部分I/O软件都属于操作系统内核态程序,最初的I/O请求在用户程序中提出。OS在I/O系统中极其重要!OS用户用户I/O软件软件用户软件可用以下两种方式提出I/O请求:(1)使用高级语言提供的标准I/O库函数。例如,在C语言程序中可以直接使用像fopen、fr
7、ead、fwrite和fclose等文件操作函数,或printf、putc、scanf和getc等控制台I/O函数。程序移植性很好!但是,使用标准I/O库函数有以下几个方面的不足:(a)标准I/O库函数不能保证文件的安全性(无加/解锁机制)(b)所有I/O都是同步的,程序必须等待I/O操作完成后才能继续执行(c)有时不适合甚至无法使用标准I/O库函数实现I/O功能,如,不提供读取文件元数据的函数(元数据包括文件大小和文件创建时间等)(d)用它进行网络编程会造成易于出现缓冲区溢出等风险(2)使用OS提供的API函数或系统调用。例如,在Windows中直接使用像CreateFile、ReadFil
8、e、WriteFile、CloseHandle等文件操作API函数,或ReadConsole、WriteConsole等控制台I/O的API函数。对于Unix或Linux用户程序,则直接使用像open、read、write、close等系统调用封装函数。用户用户I/O软件软件用户进程请求读磁盘文件操作用户进程使用标准C库函数fread,或WindowsAPI函数ReadFile,或Unix/Linux的系统调用函数read等要求读一个磁盘文件块。用户程序中涉及I/O操作的函数最终会被转换为一组与具体机器架构相关的指令序列,这里我们将其称为I/O请求指令序列。例如,若用户程序在IA-32架构上执
9、行,则I/O函数被转换为IA-32的指令序列。每个指令系统中一定有一类陷阱指令(有些机器也称为软中断指令或系统调用指令),主要功能是为操作系统提供灵活的系统调用机制。在I/O请求指令序列中,具体I/O请求被转换为一条陷阱指令,在陷阱指令前面则是相应的系统调用参数的设置指令。系统系统I/O软件软件OS在I/O子系统中的重要性由I/O系统以下三个特性决定:(1)共享性。I/O系统被多个程序共享,须由OS对I/O资源统一调度管理,以保证用户程序只能访问自己有权访问的那部分I/O设备,并使系统的吞吐率达到最佳。(2)复杂性。I/O设备控制细节复杂,需OS提供专门的驱动程序进行控制,这样可对用户程序屏蔽
10、设备控制的细节。(3)异步性。不同设备之间速度相差较大,因而,I/O设备与主机之间的信息交换使用异步的中断I/O方式,中断导致从用户态向内核态转移,因此必须由OS提供中断服务程序来处理。那么,如何从用户程序对应的用户进程进入到操作系统内核执行呢?系统调用!系统调用和系统调用和APIOS提供一组系统调用为用户进程的I/O请求进行具体的I/O操作。应用编程接口(API)与系统调用两者在概念上不完全相同,它们都是系统提供给用户程序使用的编程接口,但前者指的是功能更广泛、抽象程度更高的函数,后者仅指通过软中断(自陷)指令向内核态发出特定服务请求的函数。系统调用封装函数是API函数中的一种。API函数最
11、终通过调用系统调用实现I/O。一个API可能调用多个系统调用,不同API可能会调用同一个系统调用。但是,并不是所有API都需要调用系统调用。从编程者来看,API和系统调用之间没有什么差别。从内核设计者来看,API和系统调用差别很大。API在用户态执行,系统调用封装函数也在用户态执行,但具体服务例程在内核态执行。系统调用及其参数传递系统调用及其参数传递在用户态,当进程调用一个系统调用时,CPU切换到内核态,并开始执行一个被称为系统调用处理程序的内核函数例如,IA-32中,可以通过两种方式调用Linux的系统调用执行软中断指令int80执行指令sysenter(老的x86不支持该指令)内核实现了许
12、多系统调用,因此,用一个系统调用号(存放在EAX中)来标识不同的系统调用除了调用号以外,系统调用还需要其他参数,不同系统调用所需参数的个数和含义不同,输入参数通过通用寄存器传递,若参数个数超出寄存器个数,则将需传递参数块所在内存区首址放在寄存器中传递(除调用号以外,最多6个参数)传递参数的寄存器顺序:EAX(系统调用号)、EBX、ECX、EDX、ESI、EDI和EBP返回参数为整数值。正数或0表示成功,负数表示出错码用户程序、用户程序、C函数和内核函数和内核用户程序总是通过某种I/O函数或I/O操作符请求I/O操作。例如,读一个磁盘文件记录时,可调用C标准I/O库函数fread(),也可直接调
13、用系统调用封装函数read()来提出I/O请求。不管是C库函数、API函数还是系统调用封装函数,最终都通过操作系统内核提供的系统调用来实现I/O。printf()函数的调用过程如下:Linux系统中系统中printf()函数的执行过程函数的执行过程某函数调用了printf(),执行到调用printf()语句时,便会转到C语言I/O标准库函数printf()去执行;printf()通过一系列函数调用,最终会调用函数write();调用write()时,便会通过一系列步骤在内核空间中找到write对应的系统调用服务例程sys_write来执行。main()printf();用户程序 printf(
14、)xxxx();system_call()xxxx();系统调用封装函数系统调用处理程序用户空间、运行在用户态内核空间、运行在内核态write()int$0 x80I/O标准库函数sys_write()系统调用服务例程在system_call中如何知道要转到sys_write执行呢?根据系统调用号!Linux系统下的系统下的write()封装函数封装函数 1write:2pushl%ebx/将EBX入栈(EBX为被调用者保存寄存器)3movl$4,%eax/将系统调用号4送EAX4movl8(%esp),%ebx/将文件描述符fd送EBX5movl12(%esp),%ecx/将所写字符串首址b
15、uf送ECX6movl16(%esp),%edx/将所写字符个数n送EDX7int$0 x80/进入系统调用处理程序system_call执行8cmpl$-125,%eax/检查返回值9jbe.L1/若无错误,则跳转至.L1(按无符号数比)10negl%eax/将返回值取负送EAX11movl%eax,error/将EAX的值送error12movl$-1,%eax/将write函数返回值置-113.L1:14popl%ebx15ret用法:ssize_twrite(intfd,constvoid*buf,size_tn);size_t和ssize_t分别是unsignedint和int,因为
16、返回值可能是-1。内核执行write的结果在EAX中返回,正确时为所写字符数(最高位为0),出错时为错误码的负数(最高位为1)应用层的应用层的ReadRead函数在函数在LinuxLinux内核中的单向内核中的单向2020次以上的调用!次以上的调用!用户空间中的用户空间中的I/O函数函数用户程序可通过调用特定的I/O函数的方式提出I/O请求。在UNIX/Linux系统中,可以是C标准I/O库函数或系统调用的封装函数,前者如文件I/O函数fopen()、fread()、fwrite()和fclose()或控制台I/O函数printf()、putc()、scanf()和getc()等;后者如ope
17、n()、read()、write()和close()等。标准I/O库函数比系统调用封装函数抽象层次高,后者属于系统级I/O函数。与系统提供的API函数一样,前者是基于后者实现的。用户空间中的用户空间中的I/O函数函数文件的基本概念文件的基本概念所有I/O操作通过读写文件实现,所有外设,包括网络、终端设备,都被看成文件。所有物理设备抽象成逻辑上统一的“文件”使得用户程序访问物理设备与访问真正的磁盘文件完全一致。例如,fprintf/fwrite(主要是磁盘文件)和printf(stdout)都通过统一的write函数陷入内核,差别则由内核处理!UNIX系统中,文件就是一个字节序列。通常,将键盘和
18、显示器构成的设备称为终端(terminal),对应标准输入、和标准(错误)输出文件;像磁盘、光盘等外存上的文件则是普通文件。根据文件的可读性,文件被分成ASCII文件和二进制文件两类。ASCII文件也称文本文件,可由多个正文行组成,每行以换行符n结束,每个字符占一个字节。标准输入和标准(错误)输出文件是ASCII文件。普通文件可能是文本文件或二进制文件。问题:.c、.cpp、.o、.txt、.exe文件各是什么类型文件?哪里遇过“文件”?intfprintf(FILE*fp,char*format,argument)printf在哪显示信息?stdout文件!即终端显示器TTYStream!字
19、节流文件的创建和打开文件的创建和打开读写文件前,用户程序须告知将对文件进行何种操作:读、写、添加还是可读可写,通过打开或创建一个文件来实现。已存在的文件:可直接打开不存在的文件:则先创建1.创建文件:intcreat(char*name,mode_tperms);u创建新文件时,应指定文件名和访问权限,系统返回一个非负整数,它被称为文件描述符fd(filedescriptor)。u文件描述符用于标识被创建的文件,在以后对文件的读写等操作时用文件描述符代表文件。2.打开文件:intopen(char*name,intflags,mode_tperms);u标准输入(fd=0)、标准输出(fd=1
20、)和标准错误(fd=2)三种文件自动打开,其他文件须用creat或open函数显式创建或打开后才能读写u参数perms用于指定文件的访问权限,通常在open函数中该参数总是0,除非以创建方式打开,此时,参数flags中应带有O_CREAT标志。u参数flags:O_RDONLY,O_WRONLY|O_APPEND,O_RDWR等例:fd=open(“test.txt”,O_RDONLY,0);文件的读文件的读/写写3.读文件:size_tread(intfd,void*buf,size_tn);u将fd中当前位置k开始的n个字节读到buf中,读后当前位置为k+n。若文件长度为m,当k+nm时,
21、则读取字节数为m-kbase(fp)-ptr(fp)-cnt未读部分已读部分已读入并出缓冲文件中未缓存文件当前指针输入流缓冲fp文件对应的字节流fp文件在哪里?磁盘上或键盘输入用FILE结构描述相对于fp首的位移输入带缓冲带缓冲I/O的实现的实现向文件fp中写数据时,FILE中定义的缓冲区为输出流缓冲先按需不断地向缓存写1个(如putc)或n个(如fwrite)字节,遇到换行符n或缓存被写满1024(缓冲大小BUFSIZ=1024)个字节,则将缓存内容一次写入文件fp中 未写部分 已写部分输出流缓冲(fp)-base(fp)-ptr(fp)-cnt未写部分已写部分已写入fp并出缓冲文件当前指针
22、输出流缓冲fp文件对应的字节流输出stdout和和stderr的差别的差别猜一下在Linux中以下程序输出什么?#includeintmain()fprintf(stdout,“hello);fprintf(stderr,“world!);return0;输出结果为:world!hello#includeintmain()fprintf(stdout,“hello);fprintf(stderr,“world!n);return0;输出结果为:world!hello#includeintmain()fprintf(stdout,“hellon);fprintf(stderr,“world!);
23、return0;输出结果为:helloworld!stdout和stderr都用于标准输出,但是,stderr为_WRITE|_UNBUFstdout为_WRITE有缓冲:遇到换行符n或缓冲满(BUFSIZE=1024)才写文件!stdout 和和 stderr 的差别的差别例子(可执行文件为hello)#includevoidmain()fprintf(stdout,fromstdoutn);fprintf(stderr,fromstderrn);二者都默认指向标准输出,即显示器;也都可重定位到普通文件中!./helloout.txt:stdout送out.txt,stderr送屏幕./he
24、llo2err.txt:stdout送屏幕,stderr送err.txt./helloout.txt2err.txt:stdout送out.txt,stderr送err.txt./hellocombine.txt2&1:stdout和stderr都送combine.txt./hellocombine.txt2combine.txt:stdout和stderr都送combine.txt执行结果如下:stdio.h中更多的定义中更多的定义在stdio.h中,还定义了feof()、ferror()、fileno()、getc()、putc()、getchar()、putchar()等标准I/O函数。
25、系统级I/O函数对文件的标识是文件描述符,C标准I/O库函数中对文件的标识是指向FILE结构的指针,FILE中定义了1024字节的流缓冲区。使用流缓冲区可使文件内容缓存在用户缓冲区中,而不是每次都直接读/写文件,从而减少执行系统调用次数。int_fillbuf(FILE*);/*第一次调用getc(),需用_fillbuf()填充缓冲区*/int_flushbuf(int,FILE*);/*遇换行或写缓冲区满,调用其将缓冲内容写文件*/#definefeof(p)(p)-flag&_EOF)!=0)#defineferror(p)(p)-flag&_ERR)!=0)#definefileno(
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- ICS 计算机 基础 教学 课件 第八 输入输出 操作 实现
限制150内