收藏 分享(赏)

文件I-O(中嵌教育-嵌入式linux开发课件).ppt

上传人:Facebook 文档编号:2590219 上传时间:2018-09-23 格式:PPT 页数:35 大小:255.50KB
下载 相关 举报
文件I-O(中嵌教育-嵌入式linux开发课件).ppt_第1页
第1页 / 共35页
文件I-O(中嵌教育-嵌入式linux开发课件).ppt_第2页
第2页 / 共35页
文件I-O(中嵌教育-嵌入式linux开发课件).ppt_第3页
第3页 / 共35页
文件I-O(中嵌教育-嵌入式linux开发课件).ppt_第4页
第4页 / 共35页
文件I-O(中嵌教育-嵌入式linux开发课件).ppt_第5页
第5页 / 共35页
点击查看更多>>
资源描述

1、1、Linux系统调用与文件I/O,1.1、 Linux系统调用所谓系统调用是指操作系统提供给用户程序的一组“特殊”接口,用户程序可以通过这组“特殊”接口来获得操作系统内核提供的特殊服务。在linux中用户程序不能直接访问内核提供的服务。为了更好的保护内核空间,将程序的运行空间分为内核空间和用户空间,他们运行在不同的级别上,在逻辑上是相互隔离的。,2.1、用户程序接口(API),在linux中用户编程接口(API)遵循了在UNIX中最流行的应用编程界面标准POSIX标准。这些系统调用编程接口主要通过C库(libc)实现的。,图1 系统调用、API与系统命令之间的关系,2.1文件I/O介绍,可用

2、的文件I / O函数打开文件、读文件、写文件等等。大多数linux文件I / O只需用到5个函数:open、read、write、lseek 以及close。不带缓存指的是每个r e a d和w r i t e都调用内核中的一个系统调用。这些不带缓存的I / O函数不是ANSI C的组成部分,但是P O S I X 组成部分。,2.2 文件描述符,对于内核而言,所有打开文件都由文件描述符引用。文件描述符是一个非负整数。当打开一个现存文件或创建一个新文件时,内核向进程返回一个文件描述符。当读、写一个文件时,用o p e n或c r e a t返回的文件描述符标识该文件,将其作为参数传送给r e

3、a d或w r i t e。,在P O S I X . 1应用程序中,整数0、1、2应被代换成符号常数 STDIN_FILENO、STDOUT_FILENO和STDERR_FILENO。O。这些常数都定义在头文件 中。文件描述符的范围是0 OPEN_MAX 。早期的UNIX版本采用的上限值是1 9 (允许每个进程打开2 0个文件),现在很多系统则将其增加至6 3。,2.3 open函数,#include #include #include int open(const char *pathname, int oflag, /*, mode_t mode * / ) ; 返回:若成功为文件描述符

4、,若出错为- 1,pathname是要打开或创建的文件的名字。oflag参数可用来说明此函数的多个选择项。对于open函数而言,仅当创建新文件时才使用第三个参数。用下列一个或多个常数进行或运算构成oflag参数(这些常数定义在头文件中):O_RDONLY 只读打开。O_WRONLY 只写打开。O_RDWR 读、写打开。,O_APPEND 每次写时都加到文件的尾端。O_CREAT 若此文件不存在则创建它。使用此选择项时,需同时说明第三个参数mode,用其说明该新文件的存取许可权位。O_EXCL 如果同时指定了O_CREAT,而文件已经存在,则出错。这可测试一个文件是否存在,如果不存在则创建此文件

5、成为一个原子操作。O_TRUNC 如果此文件存在,而且为只读或只写成功打开,则将其长度截短为0。O_NOCTTY 如果p a t h n a m e指的是终端设备,则不将此设备分配作为此进程的控制终端。O_NONBLOCK 如果p a t h n a m e指的是一个F I F O、一个块特殊文件或一个字符特殊文件,则此选择项为此文件的本次打开操作和后续的I / O操作设置非阻塞方式。O_SYNC 使每次w r i t e都等到物理I / O操作完成。,2.4 creat函数,可用creat函数创建一个新文件。 #include #include #include int creat(cons

6、t char * pathname, mode_t m o d e) ; 返回:若成功为只写打开的文件描述符,若出错为- 1。 注意,此函数等效于: open (pathname, O_WRONLY | O_CREAT | O_TRUNC, mode) ;c r e a t的一个不足之处是它以只写方式打开所创建的文件。,2.5 close函数,可用close函数关闭一个打开文件: #include int close (int filedes); 返回:若成功为0,若出错为- 1当一个进程终止时,它所有的打开文件都由内核自动关闭。很多程序都使用这一功能而不显式地用c l o s e关闭打开的文

7、件。 如:例open.c,2.6 lseek函数,每个打开文件都有一个与其相关联的“当前文件偏移量”。它是一个非负整数,用以度量从文件开始处计算的字节数。通常,读、写操作都从当前文件偏移量处开始,并使偏移量增加所读或写的字节数。按系统默认,当打开一个文件时,除非指定O_APPEND选择项,否则该位移量被设置为0。可以调用l s e e k显式地定位一个打开文件。,#include #include off_t lseek(int filesdes, off_t offset, int whence) ; 返回:若成功为新的文件位移,若出错为- 1。对参数offset 的解释与参数w h e n

8、 c e的值有关。 若whence是SEEK_SET,则将该文件的位移量设置为距文件开始处offset 个字节。 若whence是SEEK_CUR ,则将该文件的位移量设置为其当前值加offset,offset可为正或负。 若whence是SEEK_END ,则将该文件的位移量设置为文件长度加offset,offset可为正或负。,若l s e e k成功执行,则返回新的文件位移量,为此可以用下列方式确定一个打开文件的当前位移量: off_t curr_pos; Curr_pos = lseek(fd, 0, SEEK_CUR);,2.7 read函数,用r e a d函数从打开文件中读数据

9、#include ssize_t read(int feledes, void *buff, size_t nbytes) ; 返回:读到的字节数,若已到文件尾为0,若出错为- 1。如r e a d成功,则返回读到的字节数。如已到达文件的尾端,则返回0。,有多种情况可使实际读到的字节数少于要求读字节数:读普通文件时,在读到要求字节数之前已到达了文件尾端。例如,若在到达文件尾端之前还有3 0个字节,而要求读1 0 0个字节,则r e a d返回3 0,下一次再调用r e a d时,它将返回0 (文件尾端)。当从终端设备读时,通常一次最多读一行(第11章将介绍如何改变这一点)。当从网络读时,网络中

10、的缓冲机构可能造成返回值小于所要求读的字节数。某些面向记录的设备,例如磁带,一次最多返回一个记录。读操作从文件的当前位移量处开始,在成功返回之前,该位移量增加实际读得的字节数。,2.8 write函数,用w r i t e函数向打开文件写数据。 #include ssize_t write(int filedes, const void * buff, size_t nbytes) ; 返回:若成功为已写的字节数,若出错为- 1。其返回值通常与参数nbytes的值不同,否则表示出错。w r i t e出错的一个常见原因是:磁盘已写满,或者超过了对一个给定进程的文件长度限制。,对于普通文件,写操

11、作从文件的当前位移量处开始。如果在打开该文件时,指定了O _ A P P E N D选择项,则在每次写操作之前,将文件位移量设置在文件的当前结尾处。在一次成功写之后,该文件位移量增加实际写的字节数。 见例:write.c,2.9 fcntl函数,fcntl函数可以改变已经打开文件的性质。 #include #include #include int fcntl(int filedes, int cmd, . ) ; 返回:若成功则依赖于cmd(见下),若出错为- 1。,f c n t l函数有五种功能:复制一个现存的描述符, 新文件描述符作为函数值返(c m dF_DUPFD)。获得/设置文件

12、描述符标记,对应于filedes 的文件描述符标志作为函数值返回(c m d = F_GETFD或F_SETFD)。获得/设置文件状态标志,对应于filedes 的文件状态标志作为函数值返回。(c m d = F_GETFL或F_SETFL)。获得/设置异步I / O有权(c m d = F_GETOWN或F_SETOWN)。获得/设置记录锁(c m d = F_SETLK , F_SETLKW)。,文件状态,标志说明,F_SETFL 将文件状态标志设置为第三个参数的值(取为整型值)。可以更改的几个标志是:O _ A P P E N D,O _ N O N B L O C K,O _ S Y

13、N C和O _ A S Y N C。F_GETOWN 取当前接收S I G I O和S I G U R G信号的进程I D或进程组I D。F_SETOWN 设置接收S I G I O和S I G U R G信号的进程I D或进程组I D。正的a rg指定一个进 程I D,负的a rg表示等于a rg绝对值的一个进程组I D。,2.9.2 用fcntl给文件加锁,当多个用户共同使用、操作一个文件的时候,linux通常采用的方法是给文件上锁,来避免共享资源产生竞争的状态。 文件锁包括建议锁和强制性锁。建议性锁要求上锁文件的进程都要检测是否有锁存在,并尊重已有的锁。强制性锁由内核和系统执行的锁。 F

14、cntl不仅可以实施建议性锁而且可以实施强制性锁。,2.9.3 fcntl函数格式,#include #include #include int fcnt1(int filedes, int cmd,. struct flock flockptr ) ; struct flock 结构,2.9.4 f l o c k结构说明:,所希望的锁类型:F_RDLCK(共享读锁)、F_WRLCK(独占性写锁)或F_UNLCK(解锁一个区域)要加锁或解锁的区域的起始地址,由l_start和l_whence两者决定。l_stat是相对位移量(字节),l_whence则决定了相对位移量的起点。区域的长度,由l

15、_len表示。,关于加锁和解锁区域的说明还要注意下列各点:该区域可以在当前文件尾端处开始或越过其尾端处开始,但是不能在文件起始位置之前开始或越过该起始位置。如若l_len为0,则表示锁的区域从其起点(由l_start和l_whence决定)开始直至最大可能位置为止。也就是不管添写到该文件中多少数据,它都处于锁的范围。为了锁整个文件,通常的方法是将l_start说明为0,l_whence说明为SEEK_SET,l_len说明为0。,2.10 ioctl函数,ioctl 函数是I / O操作的杂物箱。不能用本章中其他函数表示的I / O操作通常都能用i o c t l表示。终端I / O是ioct

16、l 的最大使用方面,主要用于设备的I / O控制。 #include /* SVR4 */ #include /* 4.3+BSD * / int ioctl(int filedes, int request, . . . ) ; 返回:若出错则为- 1,若成功则为其他值。,3、select 实现I/O复用,3.1 I/O处理的五种模型 阻塞I/O模型:若所调用的I/O函数没有完成相关的功能就会使进程挂起,直到相关数据到达才会返回。如:终端、网络设备的访问。 非阻塞模型:当请求的I/O操作不能完成时,则不让进程休眠,而且返回一个错误。如:open、read、write访问。 I/O多路转接模型

17、:如果请求的I/O 操作阻塞,且他不是真正阻塞I/O,而且让其中的一个函数等待,在这期间, I/O还能进行其他操作。如:select函数。,信号驱动I/O模型:在这种模型下,通过安装一个信号处理程序,系统可以自动捕获特定信号的到来,从而启动I/O。 异步I/O模型:在这种模型下,当一个描述符已准备好,可以启动I/O时,进程会通知内核。由内核进行后续处理,这种用法现在较少。,3.2 select函数,传向select的参数告诉内核: (1) 我们所关心的描述符。 (2) 对于每个描述符我们所关心的条件(是否读一个给定的描述符?是否想写一个给定的描述符?是否关心一个描述符的异常条件?)。 (3)

18、希望等待多长时间(可以永远等待,等待一个固定量时间,或完全不等待)。从s e l e c t返回时,内核告诉我们: (1) 已准备好的描述符的数量。 (2) 哪一个描述符已准备好读、写或异常条件。,#include /* fd_set data type */ #include /* struct timeval */ #include /* function prototype might be here */ int select (int numfds, fd_set *readfds,fd_set *writefds, fd_set *exceptfds, struct timeval

19、 * timeout) ; 返回:准备就绪的描述符数,若超时则为0,若出错则为- 1。,timeout值:NULL:永远等待,直到捕捉到信号或文件描述符已准备好为止;具体值: struct timeval 类型的指针,若等待为timeout时间还没有文件描述符准备好,就立即返回;0:从不等待,测试所有指定 的描述符并立即返回;,先说明最后一个参数,它指定愿意等待的时间。 struct timeval long tv_sec; /* seconds */long tv_usec; /* and microseconds */ ;,select函数根据希望进行的文件操作对文件描述符进行分类处理,这

20、里,对文件描述符的处理主要设计4个宏函数: FD_ZERO(fd_set *set) 清除一个文件描述符集; FD_SET(int fd, fd_set *set) 将一个文件描述符加入文件描述符集中; FD_CLR(int fd, fd_set *set) 将一个文件描述符从文件描述符集中清除; FD_ISSET(int fd, fd_set *set) 测试该集中的一个给定位是否有变化;,在使用select函数之前,首先使用FD_ZERO和FD_SET来初始化文件描述符集,并使用select函数时,可循环使用FD_ISSET测试描述符集, 在执行完成对相关的文件描述符后, 使用FD_CLR来清除描述符集。 例,见:select.c,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 中等教育 > 小学课件

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报