欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Linux----基础I/O

程序员文章站 2022-05-24 20:13:12
...

回顾C文件接口


写文件

#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<string.h>
int main ()
{
    umask(0);
    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;
}

Linux----基础I/O

读文件

#include<stdio.h>
 #include<sys/types.h>
 #include<sys/stat.h>
 #include<fcntl.h>
 #include<unistd.h>
 #include<string.h>
  int main (){
     umask(0);
     int fd = open("myfile",O_WRONLY);
     if(fd < 0){
         perror("open");
         return 1;
     }
     int count = 5;
     const char *msg = "hello world!\n";
    char buf[1024];
     while(1){
         ssize_t s = read(fd,buf,strlen(msg));//类比write
         if(s > 0){
             prin![这里写图片描述](https://img-blog.csdn.net/20180529134822775?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM3OTM0MTAx/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)tf("%s",buf);
         }
         else{
             break;
         }
      }
     close(fd);
     return 0;
 }

open接口

 #include<sys/types.h>
 #include<sys/stat.h>
 #include<fcntl.h>

 int open(const *pathname,int flags);
 int open(const *pathname,int flags,mode_t mode);

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

  • O_RDONLY:只读打开
  • O_WRONLY:只写打开
  • O_RDWR:读,写打开
    这三个常量,必须指定一个且只能指定一个
  • O_CREAT:若文件不存在,则创建它。需要使用mode选项,来指明新文件的访问权限
  • O_APPEND:追加写

返回值:

  • 成功:新打开的文件描述符
  • 失败:-1

open函数返回值


系统函数库函数

  • fopen fclose fread fwrite 都是C标准库中的函数,称之为库函数
  • open close read write都是属于系统提供的接口,称之为系统调用接口

可以认为,f#系列的函数,都是对系统调用的封装,方便二次开发。

文件描述符fd

Linux进程默认情况下会有3个缺省打开的文件描述符,分别是标准输入0标准输出1标准错误2

0,1,2对应的物理设备一般是:键盘,显示器,显示器。
Linux----基础I/O

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

文件描述符分配规则

int main()
{
    int fd = open("myfile", O_RDONLY);//只读方式打开
    if(fd < 0)
       {
              perror("open");
              return 1;
       }
       printf("fd: %d\n",fd);

       close(fd);
       return 0;
}

Linux----基础I/O
在代码的最开始加入代码close(0) 在运行发现结果变换成了Linux----基础I/O
由此可见:在file_struct数组当中,找到当前没有被使用的最小的一个下标,作为新的文件描述符。

FILE


  • 因为IO相关函数与系统调用接口对应,并且库函数封装系统调用,所以本质上,访问文件都是通过fd访问的。
  • 所以C库当中的FILE结构体中,一定封装了fd。

文件系统


通过ls -l可以看到文件元数据
Linux----基础I/O
每行包含7列:

  • 模式
  • 硬链接数
  • 文件所有者
  • 大小
  • 最后修改时间
  • 文件名

ls -l读取存储在磁盘上的文件信息,然后显示出来。还可以使用stat来显示单个文件的信息。
Linux----基础I/O

inod

Linux----基础I/O

  • 超级块:存放文件系统本身的结构信息
  • i节点表:存放文件属性(文件大小,所有者,最新修改时间等)
  • 数据区:存放文件内容

将属性与数据分开存放的想法看起来简单,但是是怎么操作的呢?
Linux----基础I/O

创建一个新文件主要有以下四个操作:
  1. 存储属性:内核先找到一个空闲的i节点(这里是263466)。内核把文件信息记录到其中。
  2. 存储数据:该文件需要在三个磁盘块,内核找到了三个空闲块300,500,800。将内存缓冲区中的内容依次写入。
  3. 记录分配情况:文件内容按300,500,8,,顺序存放。内核在inode上的磁盘分布区记录了上述块列表。
  4. 添加文件名到目录:新的文件名abc。内核将入口(263466,abc)添加到目录文件。文件名和inode之间的对应关系将文件名和文件的内容及属性连接起来。

硬链接

Linux----基础I/O

  • a和b的连接状态完全相同,他们被称为指向文件的硬链接。内核记录了这个连接数,inode 71178543的硬连接数为2。
  • 在删除文件时:1. 在目录中将对应的记录删除 2.将硬连接数-1,如果为零,则将对应的磁盘释放。

软连接

硬链接通过inode引用另一个文件,软连接通过名字引用另一个文件
Linux----基础I/O

相关标签: Linux io