Linux——系统文件I/O

本文主要介绍一下用系统接口进行文件的访问:

首先来看代码:

hello.c写文件:

    #include <stdio.h>
    #include <unistd.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    
    int main()
    {
        int fd=open("myfile",O_WRONLY|O_CREAT,0644);
        if(fd<0)
        {
            perror("open");
            return 1;
        }
    
        int count=5;
        const char *msg="hello world!\n";
        int len=strlen(msg);
        while(count--){
            write(fd,msg,len);
        }
        close(fd);
        return 0;
    }


hello.c读文件:

    #include <stdio.h>
    #include <unistd.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    
    int main()
    {
        int fd= open("myfile",O_RDONLY);
        if(fd<0){
            perror("open");
            return 1;
        }
    
        const char *msg="hello world!\n";
        char buf[1024];
        while(1){
            ssize_t s=read(fd,buf,strlen(msg));
            if(s>0)
                printf("%s\n",buf);
            else
                break;
        }
        close(fd);
        return 0;
    }
                             

依次运行写文件和读文件,测试结果:

下面介绍下上述代码中用到的接口:open (man open)

参数介绍:

pathname:要打开或创建的目标文件

flags:打开文件时,可以传入多个参数选项,用下面的一个或多个常量进行“或”运算,构成flags:

  • O_RDONLY:只读打开
  • O_WDONLY:只写打开
  • O_RDWR:读、写打开

以上三个常量必须指定一个,且只能指定一个

  • O_CREAT:若文件不存在,则创建它。需要使用mode选项,来指明新文件的访问权限
  • O_APPEND:追加写

mode_t理解:直接man手册,很清楚

open函数具体使用哪个,和具体应用场景有关,若目标文件不存在,需要open创建,则第三个参数表示创建文件的默认权限,说到创建文件的默认权限,我们具体来看下:

  • 新建文件夹默认权限=0666-权限掩码
  • 新建目录默认权限=0777-权限掩码
  • 超级用户默认掩码值为0022,普通用户默认掩码值为0002

说到这里,上述代码中open的各参数就很容易理解了。

然后就是write和read的参数了,也很简单:

    write各参数:

        fd:文件描述符(后面讲)

        msg:缓冲区首地址(从哪开始写)

        len:期望写入多少字节

    read各参数:

        fd:

        buf:接收区首地址(往哪里读)

        len:同上

学过C文件操作的,可以自己类比C文件相关接口。

下面介绍之前提到的文件描述符fd:

    通过对open函数的学习,我们发现文件描述符实际上就是一个小整数

    0&1&2

  • Linux进程默认情况下会有3个缺省打开的文件描述符,分别是:标准输入0、标准输出1、标准错误2
  • 0、1、2对应的物理设备一般是:键盘,显示器,显示器

所以输入输出还可以采用如下方式:

    #include <stdio.h>
    #include <unistd.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    
    int main()
    {
        char buf[1024];
        ssize_t s=read(0,buf,sizeof(buf));
        if(s>0){
            buf[s]=0;
            write(1,buf,strlen(buf));
            write(2,buf,strlen(buf));
        }
        return 0;
    }

运行上面的程序,输入内容,回车,即可输出结果:

    我们已经知道,文件描述符就是从0开始的小整数,当我们打开文件时,操作系统在内存中要创建相应的数据结构来描述目标文件。于是就有了file结构体表示一个已经打开的文件对象,而进程执行open系统调用,所以必须让进程和文件关联起来。每个进程都有一个指针*file指向一张表files_struct,该表最重要的部分就是包含一个指针数组,每个元素都是一个指向打开文件的指针。所以,本质上,文件描述符就是该数组的下标。因此,只要拿到文件描述符,就可以找到对应的文件。来张图感受一下:

文件描述符的分配规则

先来看代码:

    #include <stdio.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <stdlib.h>
    
    int main()
    {
        //close(0);
        //close(2);
        int fd=open("myfile1",O_WRONLY|O_CREAT,0644);
        if(fd<0){
            perror("open");
            return 1;
        }
    
        printf("fd:%d\n",fd);
        fflush(stdout);
    
        close(fd);
        exit(0);
    }

运行结果:

关闭0或者2,再运行,发现结果是fd:0或fd:2,由此我们可以知道文件描述符的分配规则:在file_struct数组当中,找到当前没有被使用的最小的一个下标,作为新的文件描述符。

重定向

    #include <stdio.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <stdlib.h>
    
    int main()
    {
        close(1);
        int fd=open("myfile1",O_WRONLY|O_CREAT,0644);
        if(fd<0){
            perror("open");
            return 1;
        }
    
        printf("fd:%d\n",fd);
        fflush(stdout);
    
        close(fd);
        exit(0);
    }
  

关闭1,再看结果,发现屏幕并未输出结果,而是将结果输出到了myfile1中:

上述这种现象叫做输出重定向,常见的重定向有:>,>>,<

直接看图体会:

printf是C库当中的IO函数,一般往stdout中输出,但是stdout底层访问文件的时候,找的还是fd:1,但此时fd:1下标所表示的内容已经变成了myfile1的地址,不再是显示器的地址,所以,输出的任何消息都会往文件中写入,进而完成输出重定向。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值