文件操作和系统调用
文件操作级别
文件和目录的基本操作
-
创建文件:使用
touch
命令或编程语言中的文件创建函数。这会在文件系统中创建一个新的空文件。 -
创建目录:使用
mkdir
命令或编程语言中的目录创建函数。这会在文件系统中创建一个新的目录。 -
复制文件或目录:使用
cp
命令或编程语言中的复制函数。这可以用来创建文件或目录的副本。 -
移动或重命名文件或目录:使用
mv
命令或编程语言中的移动/重命名函数。这可以用来更改文件或目录的位置或名称。 -
删除文件或目录:使用
rm
命令或编程语言中的删除函数。这可以用来删除文件或目录。 -
列出目录内容:使用
ls
命令或编程语言中的目录列表函数。这可以用来查看目录中的文件和子目录。
文件权限和所有权
-
文件权限:文件可以具有读取、写入和执行权限。这些权限决定了谁可以访问文件以及对文件的操作权限。权限可以通过
chmod
命令来更改。 -
文件所有权:每个文件都有一个所有者和一个用户组。这些属性决定了哪些用户有权访问文件。所有权可以通过
chown
命令来更改。
文件类型
-
普通文件:包含文本、二进制或其他数据的标准文件类型。
-
目录文件:用于存储其他文件和目录的特殊文件类型。
-
符号链接:是指向其他文件或目录的快捷方式,允许创建文件路径的别名。
-
设备文件:表示系统硬件设备,如磁盘驱动器、串口设备等。
-
命名管道:用于进程间通信的特殊文件类型,允许进程以管道方式传输数据。
-
套接字:用于网络通信的特殊文件类型,允许不同进程在网络上进行通信。
文件扩展名
文件扩展名通常用于指示文件的类型或格式。例如,.txt
表示文本文件,.jpg
表示JPEG图像,.cpp
表示C++源代码文件等。这些扩展名有助于用户和程序识别文件类型。
文件路径
-
绝对路径:从根目录开始的完整文件路径,如
/home/user/file.txt
。它指定了文件在文件系统中的确切位置。 -
相对路径:相对于当前工作目录的文件路径,如
./file.txt
或../folder/file.txt
。它指定了文件相对于当前位置的位置。
文件操作操作系统级别
文件操作需要在操作系统级别进行,具体取决于所使用的操作系统,例如UNIX/Linux和Windows。不同的操作系统可能具有不同的文件操作命令和API。
编程中的文件操作
编程语言(如Python、C++、Java)提供了文件操作的API,允许开发者通过编程来执行各种文件操作。这包括打开、读取、写入和处理文件内容等。编程提供了更灵活和自动化的方式来处理文件。
系统调用
什么是系统调用
系统调用(System Call)是操作系统提供给应用程序的编程接口,用于访问底层操作系统功能。它是用户程序与操作系统内核之间的桥梁。
系统调用的作用
-
允许特权操作:系统调用允许应用程序执行特权操作,如文件操作、进程管理、网络通信等,而不会破坏操作系统的稳定性和安全性。
-
提供内核接口:系统调用提供了用户空间和内核空间之间的界面,允许用户程序请求操作系统内核执行某些任务,如创建进程或打开文件。
常见的系统调用
常见的系统调用包括:
-
文件系统调用:用于文件和目录的创建、读取、写入、删除等操作,例如
open()
,read()
,write()
,close()
,unlink()
等。 -
进程管理调用:用于创建、终止、等待进程,以及进程间通信,例如
fork()
,exec()
,wait()
,pipe()
等。 -
内存管理调用:用于分配和释放内存,例如
malloc()
,free()
,mmap()
等。 -
网络通信调用:用于建立和管理网络连接,例如
socket()
,bind()
,connect()
,send()
,recv()
等。 -
时间管理调用:用于获取当前时间、设置定时器等,例如
time()
,sleep()
,gettimeofday()
等。
系统调用的执行过程
-
应用程序通过库函数或系统调用接口发出系统调用请求。
-
操作系统内核接收请求,并根据请求的类型执行相应的内核函数。
-
内核执行完成后,将结果返回给应用程序。
系统调用的权限
系统调用通常需要特权级别较高的权限,因此只能由操作系统内核执行。用户程序通过软中断或陷阱进入内核模式,以便执行系统调用。
系统调用与库函数的关系
库函数通常是对系统调用的封装,提供更高级别的接口,使应用程序更容易使用。库函数内部通常会调用适当的系统调用来完成请求的任务。
跨平台问题
不同操作系统具有不同的系统调用接口和调用号码,因此需要在不同平台上编写不同的系统调用代码。一些跨平台库(如POSIX标准)提供了一致的系统调用接口,以便编写可移植的代码。
最有收获的内容
文件操作和系统调用是操作系统和编程中的核心概念。最有收获的内容包括:
-
了解如何在不同操作系统上执行文件操作,包括创建、复制、移动、删除文件和目录。
-
掌握文件权限和所有权的概念,以便正确管理文件的访问和控制。
-
了解不同类型的文件和文件扩展名,以便识别和处理各种文件。
-
理解系统调用是如何连接用户程序和操作系统内核的,以及它们的作用和执行过程。
-
了解不同的系统调用类型,包括文件系统、进程管理、内存管理、网络通信和时间管理调用。
-
了解库函数与系统调用之间的关系,以及如何使用它们来执行各种操作。
-
认识到跨平台问题,并了解如何编写可移植的代码,以在不同操作系统上工作。
这些知识点对于操作系统、系统编程和应用程序开发都是非常重要的,它们为构建各种类型的应用程序提供了坚实的基础。
实践内容:使用系统调用递归复制文件
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#define BUFFER_SIZE 4096
int copyFile(const char *srcPath, const char *destPath) {
int srcFd, destFd;
ssize_t bytesRead;
char buffer[BUFFER_SIZE];
// 打开源文件
srcFd = open(srcPath, O_RDONLY);
if (srcFd == -1) {
perror("无法打开源文件");
return -1;
}
// 创建或打开目标文件,注意使用O_CREAT和O_WRONLY
destFd = open(destPath, O_CREAT | O_WRONLY | O_TRUNC, 0644);
if (destFd == -1) {
perror("无法创建或打开目标文件");
close(srcFd);
return -1;
}
// 逐块复制文件内容
while ((bytesRead = read(srcFd, buffer, sizeof(buffer))) > 0) {
// 写入目标文件,注意这里是写入到文件的末尾,不是覆盖
if (write(destFd, buffer, bytesRead) != bytesRead) {
perror("写入目标文件时出错");
close(srcFd);
close(destFd);
return -1;
}
}
// 检查读取错误
if (bytesRead == -1) {
perror("读取源文件时出错");
close(srcFd);
close(destFd);
return -1;
}
// 关闭文件描述符
close(srcFd);
close(destFd);
return 0;
}
int main() {
const char *srcFile = "source.txt";
const char *destFile = "destination.txt";
if (copyFile(srcFile, destFile) == 0) {
printf("文件复制成功:%s 到 %s\n", srcFile, destFile);
} else {
fprintf(stderr, "文件复制失败\n");
}
return 0;
}
标签:文件,八章,操作系统,系统,笔记,调用,内核,目录,第七
From: https://www.cnblogs.com/zsy1748774883/p/17746173.html