【Linux系统】从 C 语言文件操作到系统调用的核心原理

06-02 908阅读

【Linux系统】从 C 语言文件操作到系统调用的核心原理

文章目录

  • 前言
  • lesson 15_基础IO
    • 一、共识原理
    • 二、回顾C语言接口
      • 2.1 文件的打开操作
      • 2.2 文件的读取与写入操作
      • 2.3 三个标准输入输出流
      • 三、过渡到系统,认识文件系统调用
        • 3.1 `open` 系统调用
          • 1. 比特位标志位示例
          • 3.2 `write` 系统调用
            • 1. 模拟实现 `w` 选项
            • 2. 模拟实现 `a` 选项
            • 3.3 `read` 系统调用
            • 四、访问文件的本质
            • 结语

              前言

              本文将从文件的基本概念出发,先回顾 C 语言中文件操作的常用接口,再逐步过渡到 Linux 系统调用,解析文件描述符、文件打开对象、进程与文件的关系等关键概念。通过代码示例和原理分析,带你揭开 Linux 基础 IO 的神秘面纱,理解操作系统如何管理文件、进程如何与文件交互的底层逻辑。


              lesson 15_基础IO

              一、共识原理

              • 文件 = 内容 + 属性。

              • 文件分为 打开的文件 和 没打开的文件。

              • 打开的文件:谁打开的?进程!—— 本质是研究进程和文件的关系。

              • 没打开的文件:在哪里放着呢?在磁盘上。我们最关注的问题?没有被打开的文件非常多,文件如何被分门别类的放置好(如何存储) —— 我们要快速的进行增删查改 —— 快速找到文件。

              • 文件被打开,必须先被加载到内存!

              • 进程:打开的文件 = 1:n。

                小结:操作系统内部,一定存在大量的别打开的文件!—— OS 要不要管理这些被打开的文件呢? —— 怎么管理???—— 先描述,在组织。—— 在内核中,一个被打开的文件都必须有自己的文件打开对象,包含文件的很多属性。struct XXX{文件属性;struct XXX *next};

                二、回顾C语言接口

                2.1 文件的打开操作

                • fopen 函数用于打开文件,格式为

                  • FILE *fopen(const char *path, const char *mode);
                    
                  • path: 文件路径或文件名。如果只有文件名,操作系统会在当前工作目录(cwd)下查找该文件。

                  • mode: 文件打开模式。常见模式有:

                    • w: 如果文件已存在,先清空文件再写入。如果文件不存在,创建新文件。
                    • a: 以追加模式打开文件,在文件末尾添加内容。
                    • 当前路径 (cwd): 每个进程维护一个当前工作目录,操作系统会根据该目录来查找文件。如果路径没有指定,fopen 会使用进程的当前工作路径。

                    • 2.2 文件的读取与写入操作

                      • fwrite 用于向文件写入数据。其函数声明为:

                        size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
                        
                        • ptr: 指向要写入数据的指针。
                        • size: 每个写入对象的大小。
                        • nmemb: 要写入的对象个数。
                        • stream:文件流指针
                        • 举例使用:

                          int main()
                          {
                              FILE *fp = fopen("log.txt", "w");
                              if (fp == NULL)
                              {
                                  perror("fopen");
                                  return errno;
                              }
                              char* str = "Hello Linux!";
                              fwrite(str, strlen(str), 1, fp);
                              fclose(fp);
                              return 0;
                          }
                          
                          • fwrite的第二个参数是指每个写入对象的大小,strlen函数返回的值是不包含字符串结束标识符,那么我们传参是加一还是不加一呢?加一就代表把\0写入到文件中,那么我们是应该怎么选择呢?这里不妨试一试加一的结果:

                            注意 log.txt 文件中,字符串的末尾有一个^@,是什么意思呢?实际上这个字符组合是表示\0的ASCII码,所以写入字符串时,使用 strlen 计算字符串长度时,不包括结束符 \0。通常不需要将 \0 写入文件,因为它是 C 语言中的结束标志,而在其它语言中读取文件时,可能不希望看到这些无关的字符。

                            2.3 三个标准输入输出流

                            C 程序启动时,会自动打开以下三个标准流:

                            • stdin: 标准输入流(通常与键盘连接)。
                            • stdout: 标准输出流(通常与显示器连接)。
                            • stderr: 标准错误流(通常与显示器连接)。

                              这三个流都由操作系统和 C 标准库提供,并用于处理程序与外部交互的基本输入输出。

                              三、过渡到系统,认识文件系统调用

                              文件其实是在磁盘上的,磁盘是外部设备,访问磁盘文件其实是访问硬件!几乎所有的库只要是访问硬件设备,必定要封装系统调用。

                              3.1 open 系统调用

                              open 是一个用于打开文件或创建文件的系统调用,其原型为:

                              #include 
                              #include 
                              #include 
                              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_CREAT:文件不存在时创建文件。
                                  • O_TRUNC:打开文件时清空文件内容。
                                  • O_APPEND:以追加模式打开文件。
                                  • mode: 在使用 O_CREAT 时,需要指定新文件的访问权限。
                                  • 返回值:成功返回文件描述符,失败返回 -1。
                                    1. 比特位标志位示例

                                    通过按位或(|)传递多个标志位,可以在同一次调用中同时指定多个选项。

                                    代码示例:

                                    #define ONE (1
                                        if(flags & ONE) printf("function1\n");
                                        if(flags & TWO) printf("function2\n");
                                        if(flags & FOUR) printf("function3\n");
                                        if(flags & EIGHT) printf("function4\n");
                                        return;
                                    }
                                    int main()
                                    {
                                        printf("--------------------------------------\n");
                                        show(ONE);
                                        printf("--------------------------------------\n");
                                        show(ONE | TWO);
                                        printf("--------------------------------------\n");
                                        show(ONE | TWO | FOUR );
                                        printf("--------------------------------------\n");
                                        show(ONE | TWO | FOUR | EIGHT);
                                        printf("--------------------------------------\n");
                                        return 0;
                                    }
                                    
                                        umask(0); // 将权限掩码设置成0000
                                        int fd = open("log.txt", O_WRONLY | O_CREAT | O_TRUNC, 0666); 
                                        if(fd 
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。

相关阅读

目录[+]

取消
微信二维码
微信二维码
支付宝二维码