Linux学习(十六):文件IO

来源:互联网 发布:淘宝团购美食 编辑:程序博客网 时间:2024/06/05 15:48

1、UNIX文件基础

1.1 UNIX输入输出

1 文件描述符

(1)顺序分配的非负整数

(2)内核用以标识一个特定进程正在访问的文件

(3)其他资源(socket、pipe)访问的标识

标准输入stdin、标准输出stdout和标准出错stderr 

这三项是shell默认打开的,对应的文件描述符分别是0/1/2

1.2 UNIX出错处理

1.2.1 错误码errno

   全局的错误码errno,执行函数发生错误时,errno会被置为一个非0的数字,对应一个错误编号。正确时该值不会被清0,但有可能会改变。在使用前,errno首先应被置0;

    1.2.2错误处理函数

     错误处理函数有两个,strerror()和perror();
     函数原型:void perror(const char *s);
功能:在标准出错上打印错误信息
显示效果:s + ‘:’ + ‘空格’ + ‘错误信息’ + ‘\n’

函数原型char *strerror(int errnum);
功能  :将错误码转化成对应的错误信息
#inclu #include<stdio.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <string.h>#include <errno.h>int main(int argc, const char *argv[]){int fd = open(argv[1], O_RDONLY);if(fd == -1){printf("printf\n"); //打印在标准输出上perror("perror"); //打印在标准出错上printf("strerror:%s\n", strerror(errno));return -1;}return 0;}

我们显示一个出错结果

perro是自动打印出了出错的信息,stderr是将特定的错误信息打印出来。

1.2.3 系统调用和库函数


   系统调用    
1、用户空间进程访问内核的接口
2、把用户从底层的硬件编程中解放出来
3、极大提高了系统的安全性
   库函数
1、库函数为了实现某个功能而封装起来的API集合
2、提供统一的编程接口,更加便于应用程序的移植

    我们上一节标准IO的讲到的函数属于是库函数,是标准C库函数,只要有标准C库就都可以使用。本文讲到的文件IO属于系统调用,是用户层向Linux内核层转换的接口。
   系统调用和库函数的区别
(1)所有的操作系统都提供多种服务的入口点,通过这些入口点,程序向内核请求服务
(2)从执行者的角度来看,系统调用和库函数之间有重大的区别,但从用户的角度来看,其区别并不重要
(3)应用程序可以调用系统调用或者库函数,库函数则会调用系统调用来完成其功能
(4)系统调用通常提供一个访问系统的最小界面,而库函数通常提供比较复杂的功能。

2 文件IO

       同标准IO类似,本文主要介绍以下几个函数:

open()/creat()
close()
read()
write()
lseek()

2.1 打开文件

头文件:#include <sys/types.h>
      #include <sys/stat.h>
      #include <fcntl.h>
函数原型:int open(const char *pathname, int flags);
        int open(const char *pathname, int flags, mode_t mode);
功能:打开一个文件,获得文件的文件描述符
参数:pathname:指定打开的文件路径及名字
  mode:与O_CREAT同时存在才生效。指定文件的创建权限
返回值:成功返回描述符,这个描述符是最小的可用描述符;失败返回-1;
open()可以打开设备文件,但是不能创建设备文件,设备文件通常使用命令mknod创建。
文件创建的权限还与权限掩码umask有关,umask默认为002,并且创建文件时默认所有用户都没有执行权限,所以
即使在打开一个文件时设置权限为“777”,实际权限则是“664”。创建一个目录时的默认权限是“775”,也就是有执行
权限

2.2 关闭

函数原型:int close(int fd);
参数:文件描述符
返回值:成功返回0,失败返回-1

2.3 read

函数原型:size_t read(int fd, void *buf, size_t count);
功能:从文件fd中期望读取count字节的数据存储到buf内
参数:count:期望读取的字节数
返回:成功读取的字节数,0文件末尾,-1出错

2.4 write

函数原型:ssize_t write(int fd, const void *buf, size_t count);
功能:将buf里的数据写到文件fd中,大小为count字节 
返回:成功写入的字节数,失败-1

2.5 定位

函数原型:off_t lseek(int fd, off_t offset, int whence);
功能:改变文件当前的读写位置
参数:whence:SEEK_SET  SEEK_CUR  SEEK_END(最后一个字符的下一个位>
                offset:偏移量,与whence相加
返回:重新设定位置后当前位置的偏移量(相对起始位置)
每个打开的文件都有一个与其相关的“当前文件位移量”,它是一个非负整数,用以度量从文件开始处计算的字节数。
通常,读/写操作都从当前文件位移量处开始,在读/写调用成功后,使位移量增加所读或者所写的字节数。
lseek()调用成功为新的文件位移量,失败返回-1,并设置errno。
lseek()只对常规文件有效,对socket、管道、FIFO等进行lseek()操作失败。
lseek()仅将当前文件的位移量记录在内核中,它并不引起任何I/O操作。
文件位移量可以大于文件的当前长度,在这种情况下,对该文件的写操作会延长文件,并形成空洞。

复制拷贝文件例程

#include <stdio.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>#define N 32int main(int argc, const char *argv[]){int fd_r = open(argv[1], O_RDONLY);if(fd_r == -1){printf("fd_r open error\n");return -1;}int fd_w = open(argv[2], O_WRONLY|O_CREAT|O_TRUNC, 0664);if(fd_w == -1){printf("fd_w open error\n");return -1;}char buf[N] = {0};int ret = 0;while((ret = read(fd_r, buf, N)) > 0) //ret为0代表读到文件末尾{write(fd_w, buf, ret);}close(fd_r);close(fd_w);return 0;}


2.6 文件锁

函数原型:int fcntl(int fd,  int cmd, …);

参数:fd,文件描述符

   cmd:F_GETLK:检查文件锁

     F_SETLK:设置文件锁

     F_SETLK:设置文件锁(可能引起睡眠)

返回值:成功返回0,失败返回-1

2.7 获取文件信息

文件信息结构体
 struct stat {
   ino_t     st_ino;     // ionde号
   mode_t    st_mode;    // 权限、类型
   nlink_t   st_nlink;   // 硬连接数
   uid_t     st_uid;     // user ID of owner                             
   gid_t     st_gid;     // group ID of owner 
   off_t     st_size;    // 大小
   time_t    st_atime;   // 最后访问时间
   time_t    st_mtime;   // 最后修改时间
};
st_mode指的是文件权限和类型,linux系统定义了以下几种情况(八进制)
S_IFMT     0170000   bitmask for the file type bitfieldsS_IFSOCK   0140000   socketS_IFLNK    0120000   symbolic linkS_IFREG    0100000   regular fileS_IFBLK    0060000   block deviceS_IFDIR    0040000   directoryS_IFCHR    0020000   character deviceS_IFIFO    0010000   fifoS_ISUID    0004000   set UID bitS_ISGID    0002000   set GID bit (see below)S_ISVTX    0001000   sticky bit (see below)S_IRWXU    00700     mask for file owner permissionsS_IRUSR    00400     owner has read permissionS_IWUSR    00200     owner has write permissionS_IXUSR    00100     owner has execute permissionS_IRWXG    00070     mask for group permissionsS_IRGRP    00040     group has read permissionS_IWGRP    00020     group has write permissionS_IXGRP    00010     group has execute permissionS_IRWXO    00007     mask for permissions for others (not in group)S_IROTH    00004     others have read permissionS_IWOTH    00002     others have write permissonS_IXOTH    00001     others have execute permission


1、int stat(const char *path, struct stat *buf);
功能:获取一个文件的属性信息
参数:path:要访问的文件
     buf :存储属性信息
返回:成功返回0,失败返回-1

      2、int fstat(int fd, struct stat *buf);
通过文件描述符获取该文件的属性信息。其余与stat一样。


      3、int lstat(const char *path, struct stat *buf);
当访问软链接文件时,lstat获得的是链接文件的属性信息,stat获得的是原文件的属性信息

3、标准IO与文件比较