实验相关知识
文件系统编程
文件系统编程是指在编程过程中使用文件系统的相关功能,包括创建、读取、写入、删除文件,以及对目录的操作等。不同的操作系统提供不同的文件系统接口和系统调用,因此文件系统编程的具体实现方式可能会有所不同。以下是在类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操作系统
实验内容
一、文件创建
- 编写实验代码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); }
- 编译以及运行程序file_creat.c
在终端输入:gcc file_creat.c -o file_creat生成课执行文件file_creat,再输入:./file_creat test.txt运行程序。
运行截图:
运行了该程序后,可以发现当前目录下产生了test.txt文件。
二、文件拷贝
- 编写实验代码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); }
- 编译以及运行程序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()函数把写入的内容读取出来并在终端上显示输出。
- 编写实验代码 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; }
- 编译以及运行程序file open.c
在终端输入:gcc file open.c -o file open生成课执行文件file_cp,再输入:./ file open运行程序。
运行截图:
运行了该程序后,可以发现当前目录下产生了file.txt文件,并且程序通过使用read()函数把写入的内容字符串“hello world"读取出来并在终端上显示输出了。