【操作系统原理】—— 文件系统编程

简介: 【操作系统原理】—— 文件系统编程

实验相关知识

文件系统编程

     文件系统编程是指在编程过程中使用文件系统的相关功能,包括创建、读取、写入、删除文件,以及对目录的操作等。不同的操作系统提供不同的文件系统接口和系统调用,因此文件系统编程的具体实现方式可能会有所不同。以下是在类Unix/Linux环境下进行文件系统编程的一些基本操作和概念:

打开文件:

     使用 open 系统调用打开文件。该调用返回一个文件描述符,之后的读写操作将使用该描述符。

#include <fcntl.h>
int fd = open("filename.txt", O_RDONLY);  // 以只读方式打开文件

读写文件:

     使用 read 和 write 等系统调用进行文件读写操作。

#include <unistd.h>
char buffer[100];
ssize_t bytesRead = read(fd, buffer, sizeof(buffer));  // 从文件中读取数据
ssize_t bytesWritten = write(fd, buffer, bytesRead);   // 写入数据到文件

关闭文件:

     使用 close 系统调用关闭文件。

#include <unistd.h>
close(fd);  // 关闭文件

创建和删除文件:

     使用 creat 或 open 系统调用创建文件。使用 unlink 系统调用删除文件。

#include <fcntl.h>
#include <unistd.h>
int newFile = creat("newfile.txt", 0644);  // 创建文件
unlink("filename.txt");  // 删除文件

文件定位:

     使用 lseek 系统调用移动文件指针,以进行随机访问文件。

#include <unistd.h>
off_t offset = lseek(fd, 0, SEEK_SET);  // 将文件指针移到文件开头

目录操作:

     使用 opendir、readdir、closedir 等系统调用进行目录操作。

#include <dirent.h>
DIR *dir = opendir("/path/to/directory");  // 打开目录 struct dirent
*entry = readdir(dir);       // 读取目录项 closedir(dir);                             // 关闭目录

创建文件,并制定文件访问属性

     在许多编程语言和操作系统中,你可以使用特定的函数或方法来创建文件并指定文件访问属性。以下是一些示例,展示了在不同的编程语言和环境中如何创建文件并设置文件权限或访问属性:

1. C 语言(在 Unix/Linux 环境中)

#include <stdio.h>
#include <fcntl.h>
int main() {
    int fd;
    // 创建文件并设置权限为 0644
    fd = open("example.txt", O_CREAT | O_WRONLY | O_TRUNC, 0644);
    if (fd == -1) {
        perror("Error creating file");
        return 1;
    }
    // 在这里可以写入文件内容,然后关闭文件
    close(fd);
    return 0;
}

2. Python

# 创建文件并设置权限为 0644
with open('example.txt', 'w') as file:
    file.write('Hello, World!\n')
# 可以使用 os 模块来修改文件权限
import os
os.chmod('example.txt', 0o644)

3. Java

import java.io.File;
import java.io.IOException;
public class CreateFile {
    public static void main(String[] args) {
        try {
            // 创建文件并设置权限
            File file = new File("example.txt");
            if (file.createNewFile()) {
                System.out.println("File created: " + file.getName());
                file.setReadable(true);
                file.setWritable(true);
                file.setExecutable(false);
            } else {
                System.out.println("File already exists.");
            }
        } catch (IOException e) {
            System.out.println("An error occurred.");
            e.printStackTrace();
        }
    }
}

4. C# (.NET)

using System;
using System.IO;
class Program
{
    static void Main()
    {
        try
        {
            // 创建文件并设置权限
            using (StreamWriter sw = File.CreateText("example.txt"))
            {
                sw.WriteLine("Hello, World!");
            }
            // 设置文件权限
            File.SetAttributes("example.txt", FileAttributes.Normal);
        }
        catch (Exception e)
        {
            Console.WriteLine("An error occurred: " + e.Message);
        }
    }
}

C库函数和Linux系统调用

C 库函数

定      义: C 库函数是在标准 C 库(如 glibc)中提供的函数,用于执行各种常见的任务。这些函数是用 C 语言编写的,通常被封装在头文件中,可以通过在程序中包含相应的头文件来使用。

特      点: C 库函数提供了高层次的、抽象的接口,使得编程更加方便。这些函数通常涉及到字符串处理、数学计算、文件操作、内存管理等方面的功能。例子包括 printf、scanf、strlen、fopen 等。

调用方式: C 库函数的调用是通过函数调用的方式,直接在程序中调用相应的函数,而不需要进行系统调用。

Linux 系统调用

定      义: 系统调用是操作系统提供的接口,允许用户程序访问底层的操作系统功能。Linux 系统调用是由内核提供的、底层的、直接与硬件交互的接口。这些调用是由内核中断(或陷阱)触发的。

特      点: 系统调用提供了对操作系统核心功能的直接访问,例如进程控制、文件系统访问、网络通信等。它们是操作系统提供的最底层的接口,通常使用 C 语言的 syscall 函数或汇编语言进行调用。

调用方式: 系统调用的调用是通过特殊的指令(例如 int 0x80 或 syscall 汇编指令)来触发内核处理。在 C 程序中,可以通过在程序中使用 syscall 函数或者直接在汇编中使用系统调用指令来调用。

区别

抽象层次: C 库函数提供了更高层次的抽象,隐藏了底层细节,使得编程更加方便。系统调用则提供了直接的、底层的接口,允许对操作系统的底层功能进行更精细的控制。

性      能: 系统调用通常比 C 库函数更为底层,因此在性能上可能更高效。但由于涉及到更多的底层细节,使用系统调用编程可能更加复杂。

可移植性: C 库函数通常是标准的 C 接口,因此更具有可移植性。系统调用则依赖于底层操作系统,可能在不同的操作系统上具有不同的接口。

实验设备与软件环境

安装环境:分为软件环境和硬件环境

硬件环境:内存ddr3 4G及以上的x86架构主机一部

系统环境:windows 、linux或者mac os x

软件环境:运行vmware或者virtualbox

软件环境:Ubuntu操作系统

实验内容

一、文件创建

  1. 编写实验代码file_creat.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
void  create_file(char *filename)
{
    /*创建的文件具有可读可写的属性*/
    if(creat(filename,0666)<0)
  {
        printf("create file %s failure!\n",filename);
        exit(EXIT_FAILURE);
    }
  else
  {
        printf("create file %s success!\n",filename);
    }
}
int main(int argc,char *argv[])
{
    /*判断入参有没有传入文件名 */
    if(argc<2)
  {
        printf("you haven't input the filename,please try again!\n");
        exit(EXIT_FAILURE);
    }
  create_file(argv[1]);    
  exit(EXIT_SUCCESS);
}
  1. 编译以及运行程序file_creat.c
         在终端输入:gcc file_creat.c -o file_creat生成课执行文件file_creat,再输入:./file_creat test.txt运行程序。

运行截图:

     运行了该程序后,可以发现当前目录下产生了test.txt文件。

二、文件拷贝

  1. 编写实验代码file_cp.c
#include <string.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
 
#define BUFFER_SIZE 1024
 
int main(int argc,char **argv)
{
  FILE *from_fd;
  FILE *to_fd;
  long file_len=0;
  char buffer[BUFFER_SIZE];
  char *ptr;
  /*判断入参*/
  if(argc!=3)
  {
    printf("Usage:%s fromfile tofile\n",argv[0]);
    exit(1);
  }
   
  /* 打开源文件 */
  if((from_fd=fopen(argv[1],"rb"))==NULL)
  {
    printf("Open %s Error\n",argv[1]);
    exit(1);
  }
   
  /* 创建目的文件 */
  if((to_fd=fopen(argv[2],"wb"))==NULL)
  {
    printf("Open %s Error\n",argv[2]);
    exit(1);
  }
   
  /*测得文件大小*/
  fseek(from_fd,0L,SEEK_END);
  file_len=ftell(from_fd);
  fseek(from_fd,0L,SEEK_SET);
  printf("from file size is=%ld\n",file_len);
   
  /*进行文件拷贝*/
  while(!feof(from_fd))
  {
    fread(buffer,BUFFER_SIZE,1,from_fd);
    if(BUFFER_SIZE>=file_len)
    {
      fwrite(buffer,file_len,1,to_fd);
    }
    else
    {
      fwrite(buffer,BUFFER_SIZE,1,to_fd);
      file_len=file_len-BUFFER_SIZE;
    }
    memset(buffer, 0, BUFFER_SIZE);
    //bzero(buffer,BUFFER_SIZE); //清零
  }
  fclose(from_fd);
  fclose(to_fd);
  exit(0);
}
  1. 编译以及运行程序file_cp.c
         在终端输入:gcc file_cp.c -o file_cp生成课执行文件file_cp,再输入:./file_cp file_cp.c test.c运行程序。

运行截图:

运行了该程序后,我将file_cp.c拷贝为test.c,可以看到运行程序后文件夹出现了file_cp.c和test.c大小和内容都一样。

三、编写一应用程序实现如下功能:使用open()函数创建一个名为 file. txt,权限为666的文件;并向其中写入字符串“hello world",然后使用read()函数把写入的内容读取出来并在终端上显示输出。

  1. 编写实验代码 file open.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char const *argv[]) {
  int fd,ret;
  char buf[32] = "hello world!",buf2[11] = {0};
  fd = open("file.txt",O_RDWR|O_APPEND|O_CREAT,0666);
  if(fd < 0) {
    printf("open file err\n");
    return -1;
  }
  printf("open success\n");
  ret = write(fd,buf,strlen(buf));
  if(ret < 0) {
    perror("write:");
    return -1;
  }
  printf("write bif = %s\n",buf);
  printf("write count=%d\n",ret);
  close(fd);
  fd = open("file.txt",O_RDWR|O_APPEND|O_CREAT,0666);
  ret = read(fd,buf2,11);
  if(ret < 0) {
    perror("read:");
    return -1;
  }
  printf("read bif2= %s\n",buf2);
  printf("read count=%d\n",ret);
  close(fd);
  return 0;
}
  1. 编译以及运行程序file open.c
         在终端输入:gcc file open.c -o file open生成课执行文件file_cp,再输入:./ file open运行程序。

运行截图:

     运行了该程序后,可以发现当前目录下产生了file.txt文件,并且程序通过使用read()函数把写入的内容字符串“hello world"读取出来并在终端上显示输出了。


相关文章
|
8天前
|
存储 Unix Linux
手写操作系统(4)——计算机是如何启动的?BIOS、GRUB、文件系统......
手写操作系统(4)——计算机是如何启动的?BIOS、GRUB、文件系统......
18 1
|
5天前
|
算法 程序员 内存技术
深入理解操作系统内存管理:原理与实践
【5月更文挑战第18天】 在现代计算机系统中,操作系统扮演着关键角色,其中内存管理作为其核心功能之一,保障了系统资源的高效利用和程序的顺利运行。本文旨在探讨操作系统内存管理的基本原理及其在实际中的应用,涉及物理内存的组织、虚拟内存技术的实现以及内存分配策略等关键技术点。通过分析不同内存管理机制的优势与局限,我们将对操作系统如何协调多任务环境下的内存使用有更深刻的认识。
|
6天前
|
存储 缓存 算法
深入理解操作系统内存管理:原理与实践
【5月更文挑战第17天】 本文旨在探讨操作系统中的内存管理机制,通过分析其核心原理及提供实际应用场景,帮助读者深化对操作系统内存管理的认识。文章首先介绍内存管理的基础知识,然后详细阐述连续分配与非连续分配策略,接着讨论分页和分段机制,并探索虚拟内存技术如何使得内存管理更加高效。此外,文中还将涉及内存优化技巧以及现代操作系统中内存管理面临的挑战。
|
7天前
|
存储 缓存 安全
操作系统(14)----文件系统的结构
操作系统(14)----文件系统的结构
11 1
|
8天前
|
存储 算法 Linux
深入理解操作系统内存管理:原理与实践
【5月更文挑战第14天】 在现代计算机系统中,操作系统的内存管理是确保系统高效稳定运行的关键组成部分。本文将详细探讨操作系统内存管理的基本原理,包括虚拟内存的概念、物理内存与进程地址空间的映射机制、以及分页和分段技术的具体实现。此外,文章还将介绍内存分配策略、内存碎片问题及其解决方案,以及现代操作系统中采用的高级内存管理特性,如Linux内核的内存管理子系统。通过理论分析与实际案例相结合的方式,旨在帮助读者深入理解并掌握操作系统内存管理的核心知识。
|
8天前
【操作系统】实验八 proc文件系统
【操作系统】实验八 proc文件系统
9 1
|
8天前
|
存储 Linux 网络安全
【操作系统】实验二 Proc文件系统
【操作系统】实验二 Proc文件系统
9 1
|
8天前
|
存储 Linux 程序员
【操作系统原理】—— Linux内存管理
【操作系统原理】—— Linux内存管理
|
8天前
|
Ubuntu Linux C语言
【操作系统原理】—— 信号量与PV操作实现
【操作系统原理】—— 信号量与PV操作实现
|
8天前
|
消息中间件 安全 Ubuntu
【操作系统原理】—— 线程同步
【操作系统原理】—— 线程同步