Liunx系统编程:系统层面上的文件IO接口

这篇具有很好参考价值的文章主要介绍了Liunx系统编程:系统层面上的文件IO接口。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

一. 如何在系统层面上理解文件

二. 语言层面上的文件IO函数

三. Linux操作系统提供的IO接口

3.1 open接口 -- 打开文件

3.2 close接口 -- 关闭文件

3.3 write接口 -- 向文件中写内容

3.4 read接口 -- 从文件中读取内容

四. 总结


一. 如何在系统层面上理解文件

在Linux操作系统层面,可以认为,只要能进行input写入或output读取的任何的任何设备,都可以被理解为文件,我们可以从狭义和广义两个方面认识文件的概念:

  • 狭义上的文件:磁盘文件
  • 广义上的文件:任何可以进行IO操作的设备,包括显示器、键盘、声卡、网卡、磁盘、光盘、音响、磁带、光盘等。

换句话说就是:Linux下一切皆文件

文件 = 内容 + 属性,对文件的操作无外乎就是对内容的操作和对属性的操作。因此,就算一个文件的内容为空,那么它的属性信息也要存储在磁盘中,也要占用存储空间

通过Linux操作系统的ls -l (可简写为ll) 指令,可以查看文件的属性信息,包括文件的类型、权限信息、链接数、拥有者、所属组、文件内容占用空间大小、最近一次修改的时间、文件名。

Liunx系统编程:系统层面上的文件IO接口,Linux系统和网络,linux,运维,服务器
图1.1 ls -l指令查看文件信息

本质上,只有操作系统有权利对文件进行读写操作。用户对于文件的任何操作,其本质是都是调用操作系统的相关IO接口来完成的,只不过为了方便不同用户的使用,操作系统及各种编程语言,会通过图形化界面、库函数等方式,封装文件的IO接口。

如果我们希望通过代码来访问文件,那么操作流程依次为:写代码 -> 编译源代码 -> 载入内存运行,创建进程 -> 访问文件。因此,我们还可以认为,访问文件的操作本质是由进程来完成的

二. 语言层面上的文件IO函数

C/C++均提供了相应的库函数/类,来实现的文件得IO操作

  • C语言读文件函数:fgets、fgetc、fread、fscanf等。
  • C语言写文件函数:fputs、fputc、fwrite、fprintf等。
  • C++写文件类:std::ofstream,通过流插入运算符 << 来写文件。
  • C++读文件类:std::ifstream,通过流提取运算符 >> 来读文件。

这些语言层面的IO函数,在底层都封装了操作系统提供的IO接口。那么,既然操作系统已经提供了IO接口,为什么各种语言语言还要提供自己的IO函数呢?这可以从以下两个方面来理解:

  1. 语言层面的IO函数相对于系统接口使用难度较低。
  2. 语言具有跨平台的性能,而如果直接使用系统接口,那么代码就不具有跨平台性。

提问:库函数怎样针对不同的OS平台,实现不同版本的IO函数呢?答:一般采用条件编译#ifdef/#endif的方法来实现,在库函数中将全部平台下的IO接口都进行封装,实现不同底层原理的IO函数,再根据运行的平台,来对库函数代码选取一部分进行编译。

不同的语言,会提供不同的IO接口函数,但是,在同一操作系统平台下,系统IO的接口都是一样的,无论语言层面的IO接口再怎么变化,在底层都需要封装系统IO接口。

三. Linux操作系统提供的IO接口

3.1 open接口 -- 打开文件

用于打开文件的系统接口(可能创建文件),有下面两种格式: 

  • int open(const char* file, int flag)
  • int open(const char* file, int flag, int mode) 

使用open函数,要包含三个头文件:<sys/types.h>、<sys/stat.h>和<sys/fcntl.h> 

其中,file的意义为文件打开的路径,flag为打开方式的标识方法,mode为如果要创建文件的话文件的起始权限。

关于file,就是带有路径的文件的文件名。flag类似于C语言的open函数中"w"、"a"、"r"等打开方式控制的标识,主要的flag和对应的功能以下几种:

  • O_RDONLY -- 以只读方式打开文件。
  • O_WRONLY -- 以只写的方式打开文件。
  • O_RDWR -- 读写方式打开文件。
  • O_CREAT -- 如果指定的文件不存在,那就创建它。注意O_WRONLY与C语言的"w"不同的是,在open中只声明O_WRONLY并不会在文件不存在的时候创建文件。
  • O_APPEND -- 追加写入文件的内容,而不覆盖文件原有内容。
  • O_TRUNC -- 清空文件的内容后写文件。如果仅仅声明O_WRONLY,那么仅仅是在文件起始位置开始写数据,写多少内容覆盖文件原来的多少内容,不会情况原有内容。

如果我们同时需要两种flag的功能,那么应该使用按位或操作符,来同时对两个位置进行标记。如:我们希望open以只写的方式打开某个文件的同时在文件不存在的时候创建它,那么flag的传参方式为O_WRONLY|O_CREAT。

mode为文件创建的起始权限,以8进制的方式传参,如果我们希望创建文件的起始权限为拥有者、所属组和其它人都是rw-,那么在调用open时就应该给mode传0666。

但是,实际创建文件的起始权限,要经过系统的文件权限掩码过滤相应权限。Linux系统默认的文件掩码一般为0002,即:其它人不能拥有写文件的权限。那么,我们就可以在创建的进程的文件中,使用umask(0000),将该进程中的文件掩码暂时改为0000,不对任何权限进行过滤,这样就可以按照希望的方式给定文件的起始权限。

open接口的返回值:a.如果文件打开成功,就返回被打开的文件的文件描述符。b.如果文件打开失败,那么就返回-1。

再使用open之后,应当通过if判断open函数的返回值,再确保文件打开成功之后,再使用文件。

代码3.1:文件打开

#include<stdio.h>    
#include<unistd.h>    
#include<sys/types.h>    
#include<sys/stat.h>    
#include<sys/fcntl.h>    
    
int main()    
{    
    int fd1 = open("log1.txt", O_WRONLY|O_CREAT);   //以只写的方式打开log1.txt文件,如果文件不存在就创建    
    if(fd1 < 0)  //判断打开是否成功    
    {    
        perror("open fd1");    
        return 1;    
    }    
    
    //下面省略打开文件是否成功的判断    
    int fd2 = open("log2.txt", O_RDONLY);   //以只读方式打开log2.txt文件    
    int fd3 = open("log3.txt", O_WRONLY|O_APPEND);   //以追加写的方式打开log3.txt文件    
    int fd4 = open("log4.txt", O_WRONLY|O_TRUNC);    //清空文件原有内容再写入    
    
    umask(0000);   //在此之后,权限掩码为0000    
    int fd5 = open("log5.txt", O_WRONLY|O_CREAT, 0666);   //给定权限0666创建文件    
    
    close(fd1);    
    close(fd2);    
    close(fd3);    
    close(fd4);    
    close(fd5);                                                                                                                                                                                                                               
    
    return 0;    
} 

3.2 close接口 -- 关闭文件

close用于关闭某个被open接口打开的文件,其函数原型为:

  • int close(int fd) -- 其中fd为文件描述符,关闭文件成功返回0,失败返回-1。

使用close函数需要包含的头文件:<unistd.h> 

close一般配合open的返回值使用,如果传入错误的文件描述符,那么close就会失败。

3.3 write接口 -- 向文件中写内容

  • 函数原型:ssize_t wirte(int fd, const void* ptr, size_t count)
  • 函数功能:将从ptr位置处开始的count个字节的内容,写入到fd所对应的文件中去。
  • 函数返回值:返回实际写入到文件中的bytes数。

使用write函数需要包含的头文件:<unistd.h>

代码3.2:写文件

#include<stdio.h>    
#include<string.h>    
#include<unistd.h>    
#include<sys/types.h>    
#include<sys/stat.h>    
#include<sys/fcntl.h>    
    
int main()    
{    
    int fd1 = open("log1.txt", O_WRONLY|O_CREAT|O_TRUNC);    
    if(fd1 < 0)    
    {    
        perror("open fd1");    
        return 1;    
    }    
    
    const char* s1 = "hello world\n";    
    //这里不需要strlen(s) + 1
    //字符串末尾以\0结尾是语言层面的规则,与文件无关
    write(fd1, s1, strlen(s1));
    write(fd1, s1, strlen(s1));
    write(fd1, s1, strlen(s1));

   int fd2 = open("log2.txt", O_WRONLY|O_CREAT|O_APPEND|O_TRUNC); 
   if(fd2 < 0)
   {
       perror("open fd2");
       return 2;
   }

   const char* s2 = "hello Linux\n";
   write(fd2, s2, strlen(s2));
   write(fd2, s2, strlen(s2));
   write(fd2, s2, strlen(s2));

   close(fd1);
   close(fd2);                                                                                                                                                                                                                                
                                                                                                                              
   return 0;                                                                                                                  
}

3.4 read接口 -- 从文件中读取内容

  • ssize_t read(int fd, void *buff, size_t count)
  • 从fd确定的文件后缀读取count个字符,到buff所指向的内存空间中去。
  • 函数返回值:a.如果成功从文件中读取到内容,就返回实际读取到的内容的bytes数  b.如果读到了文件的末尾,就返回0。

代码3.3:read读取文件内容文章来源地址https://www.toymoban.com/news/detail-525528.html

  #include<stdio.h>    
  #include<string.h>    
  #include<unistd.h>    
  #include<sys/types.h>    
  #include<sys/stat.h>    
  #include<sys/fcntl.h>    
      
  int main()    
  {    
      int fd = open("log1.txt", O_RDONLY);   //只读方式打开文件    
      if(fd < 0)  //检查文件是否打开成功    
      {    
          perror("open");    
          return 1;    
      }    
      
      char buff[100];   //记录存储从文件中读取到的内容    
      memset(buff, '\0', 100);  //空间内容初始化                                                                                                                                                                                              
      
      ssize_t ret = read(fd, buff, 100);   //读取100字节的内容到buff中        
      printf("ret = %d\n", ret);    
      printf("buff:%s\n", buff);    
      
      close(fd);    
      return 0;    
  }  

四. 总结

  • 在操作系统层面,一切可以进行IO操作的设备都被视为文件。从狭义上讲文件就是磁盘文件,从广义上讲文件包含磁盘、显示器、键盘、鼠标、网卡、声卡等诸多设备。
  • 每一种编程语言都会提高特定的IO接口,对系统IO接口进行封装,从而方便用户的使用、实现语言的跨平台性能。
  • Linux操作系统提供了open、write、read、close等系统调用接口,用于文件IO操作。

到了这里,关于Liunx系统编程:系统层面上的文件IO接口的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Linux 文件:IO接口详解及实操

    在c语言文件中,创建、打开、读、写操作可以通过如下的代码进行: 通过\\\'w\\\'指令对文件进行写入操作时,编译器会先将文件内容清空然后重新写入。 C默认会打开三个输入输出流,分别是stdin, stdout, stderr。 仔细观察发现,这三个流的类型都是FILE*, fopen返回值类型,文件指针

    2024年01月24日
    浏览(36)
  • Liunx 套接字编程(2)TCP接口通信程序

    面向连接、可靠传输、提供字节流传输服务 客户端向服务器发送一个连接建立的请求流程,上图中服务端第三步详细流程 socket--创建套接字 bind---绑定 sockfd : socket返回的套接字描述符 addr: 要绑定的地址信息(不同地址域类型,有不同的地址结构) listen--监听 注意:listen第二

    2024年02月08日
    浏览(72)
  • 【创作赢红包】| 【Linux】 基础IO——自己实现文件接口FILE

    模仿C库,自己封装一个最简单的文件接口 FILE 创建makefile 创建MY_FILE结构体 内部包含文件描述符fd,输出缓冲区ou’tputbuffer 、flags刷新方法 分别通过C库中fopen 、fwrite、fclose 接口的实现,设计属于自己的接口 1. MY_fopen的实现 1.识别标志位 分别实现了读、写追加方式 2. 尝试打开

    2024年02月02日
    浏览(44)
  • Unix/Linux系统编程:信号驱动IO

    详细信息参考unix/linux系统编程手册第63章  在I/O多路复用中,进程是通过系统调用(select()或poll())来检查文件描述符上是否可以执行I/O操作。而在信号驱动I/O中,当文件描述符上可执行I/O操作时,进程请求内核为自己发送一个信号。之后进程就可以执行任何其他的任务直到

    2024年02月11日
    浏览(37)
  • 【Liunx系统编程】命令模式3

    目录 一,zip/unzip压缩指令 二,tar打包/压缩/解包指令 三,uname获取系统信息指令 四,Liunx下常用且重要的按键和关机指令 五,文件之间的互传  1,Windows与Linux之间的互传 2,Linux系统之间的远程拷贝 六,Liunx系统的分析 zip功能: 将目录或文件压缩成zip格式 zip语法: zip [选项

    2024年02月05日
    浏览(49)
  • 【Linux】基础IO----系统文件IO & 文件描述符fd & 重定向

    作者:დ旧言~ 座右铭:松树千年终是朽,槿花一日自为荣。 目标:了解在Linux下的系统文件IO,知道什么是文件描述符,什么是重定向 毒鸡汤:白日莫闲过,青春不再来。 专栏选自:Linux初阶 望小伙伴们点赞👍收藏✨加关注哟💕💕 最早我们在C语言中学习关于如何用代码

    2024年04月14日
    浏览(54)
  • 【Linux】基础IO——文件系统

    磁盘计算机上唯一的一个机械设备,同时它还是外设 机械磁盘很便宜,虽然效率会慢一些,所以企业一般使用机械磁盘,因为便宜 磁盘不仅仅外设,还是一个机械设备(盘片、磁头),所以磁盘一定非常慢 盘片:一片两面,有一摞盘片 磁头:一面一个磁头 一个磁头负责一面的

    2023年04月09日
    浏览(46)
  • 【Linux】文件周边001之系统文件IO

    👀 樊梓慕: 个人主页  🎥 个人专栏: 《C语言》 《数据结构》 《蓝桥杯试题》 《LeetCode刷题笔记》 《实训项目》 《C++》 《Linux》《算法》 🌝 每一个不曾起舞的日子,都是对生命的辜负 目录 前言 1.C语言文件IO 1.1C语言文件IO接口汇总  1.2当前路径指的是什么?  1.3stdi

    2024年01月24日
    浏览(52)
  • 【Linux】基础IO——系统文件IO&&fd&&重定向

    大家好我是沐曦希💕 空文件,也要在磁盘占据空间,因为文件也有属性,属性也属于数据,需要空间进行存储。所以 文件包括内容和属性 所以 对文件操作就是对内容或者对属性进行操作,或者对内容和属性进行操作。 文件具有唯一性,所以在 标定一个文件时候,必须使用

    2024年02月02日
    浏览(46)
  • 【Linux】基础IO_文件系统

     环境:centos7.6,腾讯云服务器 Linux文章都放在了专栏:【 Linux 】欢迎支持订阅 相关文章推荐: 【Linux】冯.诺依曼体系结构与操作系统 【C/进阶】如何对文件进行读写(含二进制)操作? 【Linux】基础IO_文件操作 【Linux】基础IO_文件描述符与重定向 在前文我们所讲的都是

    2024年02月05日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包