美文网首页unix
Unix的文件管理(上)

Unix的文件管理(上)

作者: 卢融霜 | 来源:发表于2019-10-27 22:17 被阅读0次

    目录

    • 概念
    • 文件分类
    • 什么是文件描述符
    • Unix的文件操作相关函数讲解及使用
    • 编写程序实现 cat命令、cp命令

    概念

    在Unix/linux系统中,几乎所有的一切都可以看作文件,因此,对于文件的操作适用于各种输入输出设备等等,当然目录也可以看作文件。一切皆文件。
    开发者仅需要使用一套 API 和开发工具即可调取 Linux 系统中绝大部分的资源

    文件的分类

    1.普通文件 <--------------> "-"

    Linux中最多的一种文件类型, 包括纯文本文件、二进制文件(binary)、数据格式的文件(data)、各种压缩文件。

    2.目录文件 <--------------> "d"

    目录文件就是目录, 能用 # cd 命令进入的。

    3.块设备文件 <--------------> "b"

    是存储数据以供系统存取的接口设备,简单而言就是硬盘。
    3.块设备文件 <--------------> "b"

    4.字符设备文件 <--------------> "c"

    即串行端口的接口设备,例如键盘、鼠标等等。

    5.套接字文件 <--------------> "s"

    这类文件通常用在网络数据连接。可以启动一个程序来监听客户端的要求,客户端就可以通过套接字来进行数据通信。

    6.管道文件 <--------------> "p"

    是一种特殊的文件类型,它主要的目的是,解决多个程序同时存取一个文件所造成的错误。(FIFO:是first-in-first-out(先进先出)的缩写。)

    7.链接文件<--------------> "l"

    链接文件类似Windows下面的快捷方式。

    文件描述符

    文件描述符是内核为了高效管理已被打开的文件所创建的索引,用于指-向被打开的文件,所有执行I/O操作的系统调用都通过文件描述符;文件描述符是一个简单的非负整数,用以表明每个被进程打开的文件。
    一个进程可以同时打开的文件描述符个数, 受limits.h中定义的OPEN_MAX宏的限制, POSIX要求不低于16,传统Unix是63,现代Linux是256。
    内核缺省为每个进程打开三个文件描述符:
    stdin,标准输入,默认设备是键盘,文件编号为0
    stdout,标准输出,默认设备是显示器,文件编号为1,也可以重定向到文件
    stderr,标准错误,默认设备是显示器,文件编号为2,也可以重定向到文件

    查看所有文件打开的文件描述符

    ll /proc/进程ID/fd
    

    文件操作函数

    open

    //需要引用的头文件
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>  
    //API函数 如下
    int open(const char *pathname, int flags);   
    int open(const char *pathname, int flags, mode_t mode);   
    

    函数功能:

    主要用于打开/创建 一个 文件/设备返回值。

    参数详解
    第一个参数 pathname :字符串形式的文件路径和文件名。
    第二个参数 flags:操作标志 必须包含以下访问模式中的一种:
    O_RDONLY - 只读
    O_WRONLY - 只写
    O_RDWR - 可读可写
    三选一的同时可以 | 上如下权限:
    O_APPEND - 追加,写入到文件的尾部
    O_CREAT - 文件不存在则创建,存在则打开
    O_EXCL - 与O_CREAT搭配使用,存在则open失败
    O_TRUNC - 文件存在且允许写,则清空文件
    第三个参数 mode: 权限 当创建新文件时,需要指定的文件权限, 如: 0644 => rw-r--r--

    返回值

    • 成功:
      返回新的文件描述符。
    • 失败返回-1。

    creat

    //需要引用的头文件
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    //API 如下
    int creat(const char *pathname, mode_t mode);
    

    函数功能

    用于创建文件,存在则更新,不存在则创建

    参数详解
    第一个参数 pathname :字符串形式的文件路径和文件名。
    第二个参数 mode:权限 当创建新文件时,需要指定的文件权限, 如: 0644 => rw-r--r-- (open函数也可实现 creat函数)

    返回值

    • 成功:
      返回文件描述符
    • 失败
      返回-1

    close

    //需要引入头文件
    #include <unistd.h>   
    //API如下:
    int close(int fd);
    

    函数功能

    主要用于关闭参数fd指定的文件描述符,也就是让描述符fd不再关联任何一个文件,以便于下次使用 。

    参数详解
    第一个参数 fd :准备关闭的文件描述符。

    返回值

    • 成功:0
    • 失败:-1

    read

    //需要引入头文件
    #include <unistd.h>   
    //API如下:
    ssize_t read(int fd, void *buf, size_t count);
    

    函数功能

    表示从指定的文件中读取指定大小的数据

    参数详解
    第一个参数: fd :文件描述符(从哪里读)
    第二个参数: buf:缓冲区的首地址(存到哪里去)
    第三个参数: count:读取的数据大小

    返回值

    • 成功:
      返回读取到的字节数,返回0表示读到文件尾。
    • 失败:
      返回-1

    write

    //需要引入头文件
    #include <unistd.h>  
    //API 如下:
     ssize_t write(int fd,const void *buf,size_t count);
    

    函数功能

    表示将指定的数据写入到指定的文件中
    注意:read和write函数一般默认以二进制形式进行读写操作

    参数详解
    第一个参数:fd:文件描述符(写入到哪里去)
    第二个参数:buf:缓冲区的首地址(数据从哪里来)
    第三个参数:count:写入的数据大小

    返回值

    • 成功:
      返回写入的数据大小,0表示没有写入。
    • 失败:
      返回-1

    文件位置

    每个打开的文件都有一个与其相关的“文件位置”。
    文件位置通常是一个非负整数,用以度量从文件头开始计算的字节数。
    读写操作都从当前文件位置开始,并根据所读写的字节数,增加文件位置。
    打开一个文件时,除非指定了O_APPEND, 否则文件位置一律被设为0。在超越文件尾的文件位置写入数据,将在文件中形成空洞。文件空洞不占用磁盘空间,但被算在文件大小内

    lseek

    //需要引入头文件
    #include <sys/types.h>
    #include <unistd.h> 
    API 如下:
    off_t lseek(int fd,off_t offset,int whence);
    

    函数功能

    主要用于调整文件的读写位置

    参数详解
    第一个参数:fd:文件描述符(表示在哪个文件中操作)
    第二个参数:offset:偏移量(正数表示向后,负数向前)
    第三个参数:whence:起始位置(从什么地方开始偏移)

    • SEEK_SET - 文件开头位置
    • SEEK_CUR - 文件当前位置
    • SEEK_END - 文件结尾位置

    返回值

    • 成功:
      返回距离文件开头位置的偏移量。
    • 失败:
      返回-1

    函数结合练习

    编写程序实现 cat命令

    #include <stdio.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <sys/stat.h>
    #include <sys/types.h>
    #include <string.h>
    int main(int argc,char* argv[]){
        if(argc!=2){
            printf("cat:参数不对\n");
            return -1;
        }   
        int fd=open(argv[1],O_RDONLY);
        if(fd==-1){
            perror("open");
            return -1;
        }
        char c = 0;
        while(1){
            int res = read(fd,&c,1);
            if(res<=0){
                break;
            }
            printf("%c",c);
            memset(buf,0,1024);
        }
        close(fd);
        return 0;
    }
    

    编写程序实现 cp命令

    #include <stdio.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <string.h>
    int main(int argc,char* argv[]){
        if(argc!=3){
            printf("cp:命令错误\n");
            return -1;
        }
        int fd1 = open(argv[1],O_RDONLY);
        if(fd1==-1){
            printf("cp:源文件不存在\n");
            return -1;
        }
        int fd2 = open(argv[2],O_WRONLY|O_TRUNC|O_CREAT,0664);
        if(fd2==-1){
            printf("cp:目标文件创建失败\n");
            close(fd1);
            return -1;
        }
        char buf[4096]={0};
        while(1){
            int res = read(fd1,buf,4096);
            if(res<=0){
                break;
            }
            write(fd2,buf,res);
            memset(buf,0,4096);
        }
        close(fd1);
        close(fd2);
        return 0;
    }
    

    相关文章

      网友评论

        本文标题:Unix的文件管理(上)

        本文链接:https://www.haomeiwen.com/subject/itimvctx.html