Linux应用程序之文件

     文件是具有永久性存储、按照特定字节顺序组成的一个有序的数据的集合。根据数据的存储方式,可将文件分为二进制文件和文本文件,计算机的存储在物理上是二进制的,所以文本文件与二进制文件的区别并不是物理上的,而是逻辑上的。这两者只是在编码层次上有差异。简单来说,文本文件是基于字符编码的文件,常见的编码有ASCII编码,UNICODE编码等。二进制文件是基于值编码的文件,你可以根据具体应用,指定某个值是什么意思,这样一个过程,可以看作是自定义编码。Linux中的七种文件:

                                                                   

    Linux系统中任何进程在运行时,都默认打开三个文件:(1)标准输入stdio (2)标准输出stdout (3)标准出错stderr。Linux中用open打开文件时会建立下面三个数据结构:

(1) 文件描述符数组(每个元素有两项:前一项为文件描述符(fd),后一项为struct file结构体指针)中,Linux中文件描述符数组长度为1024(每个可同时打开1024个文件),每次打开文件时系统分配目前未被使用的最小的文件描述符给打开的文件;
(2) struct files记录一个打开的文件的相关信息,包括:文件状态标志(open第二个参数),文件当前偏移量(下一次读写的位置),文件读写权限等。
(3) struct node记录一个物理上存在的文件的相关信息,包括文件创建者,大小,创建时间,属性等等。

内核为使当前进程与进程打开的文件建立联系,在进程的PCB(进程控制块task_struct)中使用一个成员来指向管理进程打开文件列表的结构体struct files_struct,而结构体中的struct file *fd_array[]是一个指针数组,指向进程所打开的文件的struct file。内核将这个数组中每个成员的下标值(int型)传递给用户空间来标识该打开的文件,该值即是文件描述符值。每个被打开的文件都对应于一个struct file,而每个文件只有一个struct node。

 



(1) open函数:打开和创建文件。

#include <fcntl.h>
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
返回值:成功则返回文件描述符,否则返回 -1
对于open函数而言,只有创建新文件(文件不存在时打开)是才需要使用到第三个参数。
添加O_CREAT标志时 若文件不存在则自动创建文件,此时第三个参数为操作文件权限。

(2) close函数:关闭文件。

#include <unistd.h>
int close(int fd);

返回值:成功返回0,出错返回-1并设置errno
参数fd是要关闭的文件描述符。需要说明的是,当一个进程终止时,内核对该进程所有尚未
关闭的文件描述符调用close关闭。

(3) read函数:读文件

#include <unistd.h>
ssize_t read(int fd, void *buf, int nbyte);

函数说明:read()会把参数fd所指的文件传送nbyte个字节到buf指针所指的内存中。
若参数nbyte为0,则read()不会有作用并返回0。返回值为实际读取到的字节数,如果返回0,
表示已到达文件尾或无可读取的数据。

(4) write函数:
文件

#include <unistd.h>
ssize_t write(int fd, void *buf, int nbyte);
函数说明:write函数把buf中nbyte写入文件描述符fd所指的文档,成功时返回写的字节数,错误时返回-1.

(5) lseek函数:文件读写位置定位(修改struct file结构体中文件当前偏移量的值)

#include <sys/types.h> 
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);

whence的值:
SEEK_SET: 文件开头
SEEK_CUR: 文件当前位置
SEEK_END: 文件末尾
返回值:若成功返回为文件指针相对于文件头的位置,若出错为-1;
lssek(fd,10L,SEEK_END);//允许操作;
//此时添加的10个字节空间存放空洞字符("\0"),空洞字符其实就是二进制的0;
lssek(fd,-10L,SEEK_SET);//不允许操作。

(6) fcntl函数:
更改文件属性

#include <sys/types.h> 
#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd ,int cmd,...);

返回值:若成功返回cmd,失败返回-1;
fcntl函数的五种功能: 

<span style="font-size:14px;">A.cmd = F_DUPFD	    复制一个现存的文件描述符,新文件描述符作为函数返回值; eg:fcntl(fd ,F_DUPFD);  /  fcntl(fd ,F_DUPFD,5);		
B.cmd = F_GETFD/F_GETFD	  获得/设置文件描述符标记(fd),新的文件描述符fd为返回值; 	
C.cmd = F_GETFL/F_SETFL	  获得/设置文件状态标志,对应于fd的文件状态标志作为返回值;
 	eg:int val=fcntl(3,F_GETFL);
 	    val |=O_APPEND;//添加文件状态标志
 	    val &=~O_APPEND;
 	    fcntl(3,F_SETFL,val|);	
D.cmd = F_FETOWN/F_SETOWN		获得/设置文件异步I/O所以权
 	
E.cmd = F_SETLK/F_SETLKW		获得/设置记录锁</span>
 
(7) stat,fstat,lstat函数
该函数可以获取文件的属性,文件属性存储在结构对象buf中,lstat返回符号链接的属性
#include <sys/types.h> 
int stat(const char *path, struct stat *buf); 
int fstat(int filedes, struct stat *buf); 
int lstat(const char *path, struct stat *buf);

struct stat结构体用于存放从内核空间struct node结构体中返回的文件属性,struct stat结构体中的成员变量对应与struct node每个成员变量。


(8) 文件描述符复制         

#include <unistd.h>
int dup(int fd);  //将fd拷贝给当前未被使用的最小的文件描述符,并返回该文件描述符
int dup2(int fd,int fd2);

返回值:成功则返回新文件描述符,出错返回-1.
函数说明:1)两个函数可用来复制文件描述符;
                  2)复制文件描述符时即是复制

(9) 文件映射

#include<sys/mman.h>
void *mmap(void *start,size_t length,int prot,int flags,int fd,off_t offset);     //将文件映射到内存区域
int munmap(void *start,size_t length);   //取消映射

      start:映射区的开始地址,设置为0时表示由系统决定映射区的起始地址。
      length:映射区的长度。//长度单位是 以字节为单位,不足一内存页按一内存页处理
      prot:期望的内存保护标志,不能与文件的打开模式冲突。是以下的某个值,可以通过or运算合理地组合在一起
                 ----PROT_EXEC         //页内容可以被执行
                 ----PROT_READ        //页内容可以被读取
                 ----PROT_WRITE       //页可以被写入
                 ----PROT_NONE        //页不可访问
      flags:指定映射对象的类型,映射选项和映射页是否可以共享。它的值可以是一个或者多个标志位的组合体
      fd:有效的文件描述词。一般是由open()函数返回,其值也可以设置为-1,此时需要指定flags参数MAP_ANON,表              明进行的是匿名映射。
      off_t offset:被映射对象内容的起点。

      mmap()必须以PAGE_SIZE()为单位进行映射,而内存也只能以页为单位进行映射,若要映射非PAGE_SIZE整数倍的地址范围,要先进行内存对齐,强行以PAGE_SIZE的倍数大小进行映射。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值