【Linux后端服务器开发】基础IO与文件系统

目录

一、基础IO

1. C语言文件读写

2. 标志位传参

3. C语言与系统调用关系

二、文件系统

1. 文件描述符

2. 输入输出重定向


一、基础IO

文件调用

  • 库函数接口: fopen、fclose、fwrite、fread、fseek
  • 系统调用接口:open、close、write、read、lseek

1. C语言文件读写

  • r/w/a :读/写/追加
  • 若打开的文件不存在,“r”报错,“w/a”创建
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>

int main() 
{
    //FILE* pf = fopen("test.txt", "w");
    //FILE* pf = fopen("test.txt", "a");
    FILE* pf = fopen("test.txt", "r");
    if (pf == NULL) 
    {
        perror("fopen");
        exit(errno);
    }

    //w
    // int cnt = 5;
    // while (cnt--) 
    //     fprintf(pf, "%s\n", "hello world -- write");


    //a
    // int cnt = 5;
    // while (cnt--) 
    //     fprintf(pf, "%s\n", "append");


    //r
    char buffer[64];
    while (fgets(buffer, sizeof(buffer) - 1, pf)) 
    {
        buffer[strlen(buffer) - 1] = 0;
        printf("%s\n", buffer);
    }

    return 0;       
}

2. 标志位传参

#include <stdio.h>

#define ONE (1 << 1)
#define TWO (1 << 2)
#define THREE (1 << 3)
#define FOUR (1 << 4)

void Show(int flag) 
{
    if (flag & ONE) 
        printf("one\n");
    if (flag & TWO) 
        printf("two\n");
    if (flag & THREE) 
        printf("three\n");
    if (flag & FOUR) 
        printf("four\n");
}

void ShowTest() 
{
    Show(ONE);
    printf("-----------\n");
    Show(TWO);
    printf("-----------\n");
    Show(TWO | THREE);
    printf("-----------\n");
    Show(TWO | THREE | FOUR);
}

int main() 
{
    ShowTest();
    return 0;       
}

 

3. C语言与系统调用关系

  • "w" ----> O_WRONLY | O_CREAT | O_TRUNC
  • "a" ----> O_WRONLY | O_CREAT | O_APPEND
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>

int main() 
{
    umask(0);   //只修改当前进程的umask
    //int fd = open("test.txt", O_WRONLY | O_CREAT | O_TRUNC, 0666);
    //int fd = open("test.txt", O_WRONLY | O_CREAT | O_APPEND, 0666);
    int fd = open("test.txt", O_RDONLY);
    if (fd < 0) 
    {
        perror("open");
        return 1;
    }

    //写/追加
    // int cnt = 5;
    // char outBuffer[64] = {0};
    // while (cnt--) 
    // {
    //     sprintf(outBuffer, "%s: %d\n", "hello --- a", cnt);
    //     write(fd, outBuffer, strlen(outBuffer));
    // }

    //读
    char buffer[1024];
    ssize_t num = read(fd, buffer, sizeof(buffer) -  1);
    if (num > 0) 
    {
        buffer[num] = 0;
    }
    printf("%s", buffer);

    return 0;       
}

二、文件系统

在Linux中,一切皆文件,不仅普通的文件和目录,块设备、管道、socket等等,都是由文件系统管理的。在Linux中的文件系统会给每个文件分配两个数据结构:索引节点(index node)和目录项(directory entry),它们都主要是被用来记录文件的元信息和目录层次结构。

  • 索引节点,inode,用来记录文件的元信息,比如inode编号、文件大小、访问权限、创建时间、修改时间、数据在磁盘的位置等。索引节点是文件的唯一标识,它们之间一一对应,也同样都是被存储在硬盘当中,索引节点也是会占用磁盘的存储空间的。
  • 目录项,dentry,用来记录文件的名字,索引节点指针以及与其他目录项的层级关联关系。多个目录项关联起来,就会形成目录结构,但是它与索引节点不相同的是,目录项是由内核维护的一个数据结构,不是存放咋磁盘中,而是缓存在内存里面。目录项包括文件名和inode节点号。

1. 文件描述符

文件描述符(file descripter)FD:Linux内容默认情况下一个进程只能打开1024个文件,内核为了管理进程,当一个进程打开了哪些文件,内核就会维护一个表,这个表就会记录这个进程打开了哪些文件,然后给每个文件进行编号,这个编号就叫文件描述符(句柄),默认文件描述符的范围为0-1023。
 

三个标准输入输出流:

  • stdin:标准输入,0
  • stdout:标准输出,1
  • stderr:标准错误,2

FILE ----> 结构体

文件描述符表:struct file* fd_array[]

文件分配规则:寻找最小且没被占用的下标

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>

#define TEST_FILE(number) "test"#number

int main() 
{
    umask(0);
    printf("stdin   --->   fd : %d\n", stdin->_fileno);     //0
    printf("stdout  --->   fd : %d\n", stdout->_fileno);    //1
    printf("stderr  --->   fd : %d\n", stderr->_fileno);    //2

    //close(0);
    //close(2);
    close(1);   //关闭文件描述符对应下标的文件
                //关闭文件描述符表的 1 后, fd0 会被分配到 1 的位置,也就是原本stdout的位置
                //而原本输出到stdout的数据,会写入 fd0 中

    int fd0 = open(TEST_FILE(0), O_WRONLY | O_CREAT | O_APPEND, 0666);
    int fd1 = open(TEST_FILE(1), O_WRONLY | O_CREAT | O_APPEND, 0666);
    int fd2 = open(TEST_FILE(2), O_WRONLY | O_CREAT | O_APPEND, 0666);
    int fd3 = open(TEST_FILE(3), O_WRONLY | O_CREAT | O_APPEND, 0666);

    printf("fd : %d\n", fd0);
    printf("fd : %d\n", fd1);
    printf("fd : %d\n", fd2);
    printf("fd : %d\n", fd3);       //fd分配规则,寻找最小的且没被占用的下标
    fprintf(stdout, "fd : %d\n", fd3);  //打印到 f0 对应的文件
    fflush(stdout);

    close(fd0);
    close(fd1);
    close(fd2);
    close(fd3);

    return 0;       
}

2. 输入输出重定向

int dup2(int old_fd, int new_fd)

重定向:将新的文件文件描述符充当老的文件描述符的一份拷贝(old_fd内容 拷贝到 new_fd内容)

上层的fd不变,在内核中更改fd对应的struct file*地址

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>

int main() 
{
    umask(0);
    //int fd = open("test.txt", O_WRONLY | O_CREAT | O_TRUNC, 0666);
    //int fd = open("test.txt", O_WRONLY | O_CREAT | O_APPEND, 0666);
    int fd = open("test.txt", O_RDONLY);
    if (fd < 0) 
    {
        perror("open");
        return 1;
    }

    //输出重定向
    // dup2(fd, 1);
    // printf("open fd: %d\n", fd);
    // fprintf(stdout, "open fd: %d\n", fd);
    // const char* msg = "hello world\n";
    // write(1, msg, strlen(msg));
    // fflush(stdout);

    //输入重定向
    dup2(fd, 0);
    char line[1024];
    while (1) 
    {
        printf("> ");
        if (fgets(line, sizeof(line) - 1, stdin) == NULL) 
            break;
        printf("%s", line);
    }

    close(fd);
    return 0;       
}

  • 9
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 10
    评论
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AllinTome

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值