Linux文件系统调用
- 格式:doc
- 大小:34.00 KB
- 文档页数:3
LinuxC讲解系统调⽤readdir,readdir_r以及如何遍历⽬录下的所有⽂件readdir与readdir_r简要说明readdir可以⽤来遍历指定⽬录路径下的所有⽂件。
不过,不包含⼦⽬录的⼦⽂件,如果要递归遍历,可以使⽤深度遍历,或者⼴度遍历算法。
readdir_r 是readdir的可重⼊版本,线程安全。
readdir因为直接返回了⼀个static的struct dirent,因此是⾮线程安全。
readdir如何遍历⽬录⼦⽂件?1. opendir打开⽬录opendir有2个版本:opendir,fopendir。
前者参数为⽬录对应字符串,后者参数为⽬录对应已打开⽂件描述符。
#include <sys/types.h>#include <dirent.h>DIR *opendir(const char *name);DIR *fdopendir(int fd);⽤法模型:DIR *dirp;const char *base_dir = "/home/martin/document";if ((dirp = opendir(base_dir)) != NULL) {perror("opendir error");return -1;}// 调⽤readdir遍历⽬录⼦⽂件...closedir(base_dir);2. readdir遍历⽬录⼦⽂件readdir需要⼀个已打开(调⽤opendir)的DIR对象作为参数。
#include <dirent.h>struct dirent *readdir(DIR *dirp);int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result);dirent 结构定义struct dirent {ino_t d_ino; /* inode number i节点编号 */off_t d_off; /* not an offset; see NOTES 早期⽂件系统中,telldir返回⽂件在⽬录内的偏移 */unsigned short d_reclen; /* length of this record dirent 记录的实际长度 */unsigned char d_type; /* type of file; not supportedby all filesystem types ⽂件类型 */char d_name[256]; /* filename ⽂件名 */};成员介绍:d_ino i节点编号,操作系统⽤来识别⽂件的,每个⽂件都有⼀个inode number(参见)d_off 早期⽂件系统中,⽂件系统使⽤平⾯表格,telldir返回⽂件在⽬录内的偏移,⽽d_off就代表这个偏移的缓存。
Linux内核中系统调用详解什么是系统调用?(Linux)内核中设置了一组用于实现各种系统功能的子程序,称为系统调用。
用户可以通过系统调用命令在自己的应用程序中调用它们。
从某种角度来看,系统调用和普通的函数调用非常相似。
区别仅仅在于,系统调用由(操作系统)核心提供,运行于核心态;而普通的函数调用由函数库或用户自己提供,运行于用户态。
随Linux核心还提供了一些(C语言)函数库,这些库对系统调用进行了一些包装和扩展,因为这些库函数与系统调用的关系非常紧密,所以习惯上把这些函数也称为系统调用。
为什么要用系统调用?实际上,很多已经被我们习以为常的C语言标准函数,在Linux 平台上的实现都是靠系统调用完成的,所以如果想对系统底层的原理作深入的了解,掌握各种系统调用是初步的要求。
进一步,若想成为一名Linux下(编程)高手,也就是我们常说的Hacker,其标志之一也是能对各种系统调用有透彻的了解。
即使除去上面的原因,在平常的编程中你也会发现,在很多情况下,系统调用是实现你的想法的简洁有效的途径,所以有可能的话应该尽量多掌握一些系统调用,这会对你的程序设计过程带来意想不到的帮助。
系统调用是怎么工作的?一般的,进程是不能访问内核的。
它不能访问内核所占内存空间也不能调用内核函数。
(CPU)(硬件)决定了这些(这就是为什么它被称作"保护模式")。
系统调用是这些规则的一个例外。
其原理是进程先用适当的值填充(寄存器),然后调用一个特殊的指令,这个指令会跳到一个事先定义的内核中的一个位置(当然,这个位置是用户进程可读但是不可写的)。
在(Intel)CPU中,这个由中断0x80实现。
硬件知道一旦你跳到这个位置,你就不是在限制模式下运行的用户,而是作为操作系统的内核--所以你就可以为所欲为。
进程可以跳转到的内核位置叫做sysem_call。
这个过程检查系统调用号,这个号码告诉内核进程请求哪种服务。
然后,它查看系统调用表(sys_call_table)找到所调用的内核函数入口地址。
linux中系统调用中open函数读写权限mode具体参数
mode 的具体参数:
S_IRWXU
00700 允许文件的属主读 , 写和执行文件
S_IRUSR (S_IREAD)
00400允许文件的属主读文件
S_IWUSR (S_IWRITE)
00200允许文件的属主写文件
S_IXUSR (S_IEXEC)
00100允许文件的属主执行文件
S_IRWXG
00070允许文件所在的分组读 , 写和执行文件
S_IRGRP
00040允许文件所在的分组读文件
S_IWGRP
00020允许文件所在的分组写文件
S_IXGRP
00010允许文件所在的分组执行文件
S_IRWXO
00007允许其他用户读 , 写和执行文件
S_IROTH
00004允许其他用户读文件
S_IWOTH
00002允许其他用户写文件
S_IXOTH
00001允许其他用户执行文件
mode 只有当在 flags 中使用 O_CREAT 时才有效 , 否则被忽略.
creat 相当于open 的参数flags 等于
O_CREAT|O_WRONLY|O_TRUNC.。
linux 读取文件的原理
Linux 读取文件的原理主要涉及到操作系统、文件系统和硬件等多个方面。
下面是一个简要的概述:
1.文件系统:Linux 系统使用的是类Unix 的文件系统,称为Ext4。
文件系统负责管理文件在硬盘上的存储和访问,以及文件的权限和属性等信息。
当一个程序试图读取一个文件时,文件系统会接收到这个请求,并查找文件在硬盘上的位置。
2.打开文件:要读取一个文件,首先需要打开这个文件。
在Linux 中,打开文件是通过系统调用(如open() 或fopen())实现的。
这些系统调用会向操作系统发出请求,请求中包含文件名和打开文件的模式(例如只读、写入等)。
操作系统会查找文件并返回一个文件描述符,这个文件描述符是一个整数,用于标识已经打开的文件。
3.读取文件数据:一旦文件被打开,就可以通过系统调用(如read() 或fread())来读取文件的内容。
这些系统调用会向操作系统发出请求,请求中包含文件描述符、读取的起始位置和要读取的字节数。
操作系统会将读取的请求传递给硬件,硬件会从硬盘中读取相应的数据,并将其存储在内存中。
4.关闭文件:当读取完文件后,需要通过系统调用(如close() 或fclose())来关闭文件。
这个系统调用会将文件描述符释放回操作系统,以便其他程序可以使用它。
linux 系统调用流程Linux系统调用流程一、引言Linux是一种自由开源的操作系统,其核心部分是内核。
内核负责管理计算机的硬件资源,并提供各种系统调用供用户程序使用。
本文将介绍Linux系统调用的流程,包括用户程序如何通过系统调用接口向内核发起请求以及内核如何处理这些请求。
二、系统调用的定义系统调用是用户程序与内核之间的接口。
用户程序通过调用特定的系统调用函数来请求内核执行某些操作,例如读写文件、创建进程等。
内核接收到这些请求后,会进行相应的处理并返回结果给用户程序。
三、系统调用的流程1. 用户程序发起系统调用请求用户程序通过调用系统调用函数向内核发起请求。
这些系统调用函数通常由C库提供,并在用户程序中使用。
用户程序需要提供相应的参数,以告知内核所需的操作类型和操作对象。
2. 用户程序转入内核态用户程序发起系统调用请求后,会进入内核态。
在内核态下,用户程序的权限更高,可以执行一些普通用户无法执行的操作,例如访问硬件资源。
3. 内核处理系统调用请求内核接收到系统调用请求后,会根据请求的类型和参数进行相应的处理。
内核会首先检查请求的合法性,验证用户程序的权限和参数的有效性。
如果请求合法,内核会执行相应的操作;如果请求非法,内核会返回错误信息给用户程序。
4. 内核执行系统调用操作内核根据系统调用请求的类型和参数执行相应的操作。
例如,如果用户程序请求打开一个文件,内核会检查文件是否存在,并分配相应的文件描述符。
如果用户程序请求创建一个进程,内核会为进程分配资源并初始化进程上下文。
5. 内核返回结果给用户程序内核在执行完系统调用操作后,会将结果返回给用户程序。
如果操作成功,内核会返回相应的数据或完成状态;如果操作失败,内核会返回错误码,用户程序可以根据错误码进行相应的处理。
6. 用户程序继续执行用户程序在接收到内核返回的结果后,会根据结果进行相应的处理。
如果操作成功,用户程序可以继续执行后续的逻辑;如果操作失败,用户程序可以根据错误码采取相应的措施,例如重新尝试或向用户报告错误信息。
网上搜索到一些博客有对这两个函数的解释,看了之后还是犯迷糊。
exit()函数定义在stdlib.h头文件中,_exit()定义在unistd.h头文件中,这是区别之一。
调用_exit()函数时,其会关闭调用进程的所有文件描述符,清理内存和内核数据,但不会刷新流(stdin, stdout, stderr ...)。
exit()函数是在_exit()函数之上的一个封装,其会调用_exit(),并在调用之前先刷新流,并且exit()系统调用之前要检查文件的打开情况,把文件缓冲区的内容写回文件。
所以要保证数据的完整性,得调用exit()函数。
但是也查到一些解释,《Linux环境C程序设计》(第二版 徐诚等编著)一书第205页exit系统调用小节中有这样描述:“由fork()函数创建的子进程分支里,正常情况下使用函数exit()是不正确的,这是因为使用它会导致标准输入输出的缓冲区被清空两次,而且临时文件可能被意外删除。
”这与上面的解释相悖了,究竟谁是对的?基于上面的描述,我还有以下疑问:1、刷新缓冲区是简单的删除其中的数据,还是要进行一些操作,例如保存数据再清空?2、exit()为什么会导致标准输入输出的缓冲区被清空两次?希望有高手不吝赐教,解释exit()和_exit()的区别及使用方法。
谢谢!添加评论 分享匿名用户知乎用户、知乎用户、知乎用户 等人赞同基本来说,_Exit(或 _exit,建议使用大写版本)是为 fork 之后的子进程准备的特殊 API。
功能见 [1],讨论见 [2]。
因为在 fork 之后,exec 之前,很多资源还是共享的(如某些文件描述符),如果使用 exit 会关闭这些资源,导致某些非预期的副作用(如删除临时文件等)。
「刷新」是对应 flush,意思是把内容从内存缓存写出到文件里,而不仅仅是清空(所以常见的对 stdin 调用 flush 的方法是耍流氓而已)。
如果在 fork 的时候父进程内存有缓冲内容,则这个缓冲会带到子进程,并且两个进程会分别 flush (写出)一次,造成数据重复。
linux文件句柄机制Linux文件句柄是操作系统用于管理文件的一种机制。
每个打开的文件都会被分配一个唯一的文件句柄,该句柄用于标识和访问该文件。
在Linux系统中,文件句柄是一种整数类型的标识符,用于表示文件在系统中的位置和状态。
下面是关于Linux文件句柄机制的十个重要知识点:1. 文件句柄是一个整数值,它是内核为每个打开的文件分配的唯一标识符。
Linux内核使用文件句柄来跟踪文件的状态和位置。
2. 文件句柄是通过调用系统调用open()或socket()等来打开文件或套接字时返回的。
这些系统调用返回的整数值就是文件句柄。
3. 文件句柄是进程级别的,每个进程都有自己的文件句柄表。
这意味着不同进程中的文件句柄可能具有相同的值,但它们实际上代表了不同的文件。
4. 文件句柄在进程的文件描述符表中进行管理。
文件描述符是指向文件句柄的指针,它是进程执行I/O操作的主要接口。
5. 文件句柄是顺序递增的整数值,它们从0开始,一般情况下,较小的文件句柄值对应于较早打开的文件。
6. 文件句柄可以被用于读取、写入和关闭文件。
通过调用系统调用read()和write(),可以使用文件句柄进行读取和写入操作。
而通过调用close()可以关闭文件句柄。
7. 文件句柄还可以用于其他文件操作,如定位文件位置、文件锁定和修改文件权限等。
8. 文件句柄在进程终止时会被自动关闭。
当进程结束时,操作系统会自动关闭进程打开的所有文件句柄,以释放系统资源。
9. 在Linux系统中,有一个特殊的文件句柄,即标准输入、标准输出和标准错误输出。
它们分别被分配文件句柄值0、1和2。
10. Linux系统中,文件句柄的最大值是由系统内核参数限制的。
可以通过查看/proc/sys/fs/file-max文件来获取当前系统的最大文件句柄数。
总结:Linux文件句柄机制是操作系统用于管理文件的一种机制,它通过为每个打开的文件分配唯一的文件句柄来标识和访问文件。
linux中获取文件大小的函数在Linux中,要获取文件大小可以使用多种方法和函数。
在本篇文章中,我们将详细介绍三种常用的Linux文件大小获取函数:stat、du和ls。
首先,让我们来了解一下stat函数。
Stat函数是一种用于获取文件信息的系统调用函数。
在Linux中,我们可以使用stat函数来获取文件的各种属性,包括大小。
要使用stat函数,我们需要包含头文件<sys/stat.h>,并调用函数stat("文件路径", &结构体变量)。
具体来说,stat函数将文件的信息存储在一个结构体中,我们可以使用结构体中的成员变量st_size来获取文件的大小。
st_size表示以字节为单位的文件大小。
通过使用stat函数,我们可以简单地获取文件的大小,从而方便地进行后续的操作。
接下来,让我们介绍du命令。
Du命令在Linux系统中用于估算文件和目录的磁盘使用空间。
通过使用du命令,我们可以获取文件以及目录的大小信息。
du命令有多种参数可以使用,其中最常用的是-duh参数。
使用-duh参数,du命令可以以易于理解的方式打印出文件和目录的大小,单位为人类可读的格式(如KB、MB、GB等)。
在使用du命令时,我们只需在终端中输入"du -h 文件路径"即可获取文件的大小信息。
通过使用du命令,我们可以快速了解文件的大小,而不必对文件进行系统调用或查看文件的详细信息。
最后,我们来介绍一下ls命令。
Ls命令是Linux系统中最常用的命令之一,用于列出目录中的文件和子目录。
在使用ls命令时,我们可以通过给ls命令添加特定的参数来获取文件的大小信息。
其中,ls命令最常用的参数是-l,它可以以长格式列出文件的详细信息,包括文件的大小。
通过使用ls -l命令,我们可以获取文件的大小、权限、所有者等信息。
ls命令以易于理解的方式打印出文件的大小,单位为字节,KB或MB。
linux系统调用 api 手册【实用版】目录I.Linux 系统调用 API 手册概述II.Linux 系统调用 API 的功能III.Linux 系统调用 API 的使用方法IV.Linux 系统调用 API 的示例正文I.Linux 系统调用 API 手册概述Linux 系统调用 API 手册是指提供了一系列用于在 Linux 系统中调用系统功能的 API 函数。
这些 API 函数可以让程序员在编写程序时,更加方便、高效地与 Linux 系统进行交互,实现各种系统操作。
II.Linux 系统调用 API 的功能Linux 系统调用 API 的功能主要包括以下几个方面:1.文件操作:包括文件的打开、关闭、读取、写入等操作。
2.进程管理:包括进程的创建、终止、切换等操作。
3.系统管理:包括系统时间的获取、设置,内存的管理等操作。
4.网络操作:包括网络套接字的创建、连接、接收、发送等操作。
III.Linux 系统调用 API 的使用方法要使用 Linux 系统调用 API,首先需要在程序中包含相应的头文件,然后调用相应的函数。
例如,要使用文件操作相关的 API,需要在程序中包含`<unistd.h>`头文件,然后调用如`open()`、`read()`、`write()`等函数。
IV.Linux 系统调用 API 的示例以下是一个简单的使用 Linux 系统调用 API 的示例,该示例展示了如何使用`read()`和`write()`函数实现文件的读写操作:```c#include <stdio.h>#include <unistd.h>int main() {int fd = open("example.txt", O_RDWR);if (fd < 0) {perror("Error opening file");return -1;}char buffer[1024];if (read(fd, buffer, 1024) < 0) {perror("Error reading from file");return -1;}printf("Content of file: %s", buffer);char new_content[1024] = "Hello, world!";if (write(fd, new_content, 1024) < 0) {perror("Error writing to file");return -1;}printf("New content written to file.");close(fd);return 0;}```在这个示例中,我们首先使用`open()`函数打开名为`example.txt`的文件,然后使用`read()`函数从文件中读取内容,使用`write()`函数向文件中写入新内容。
Linux文件系统调用
一、实验目的:
(1)掌握Linux提供的文件系统调用的使用方法。
(2)熟悉文件系统的系统调用用户接口。
(3)了解操作系统文件系统的工作原理和工作方式。
二、实验内容
编写一个文件工具filetools,使其具有以下功能:
0.退出
1.创建新文件
2.写文件
3.读文件
4.修改文件权限
5.查看当前文件权限并退出。
提示用户输入功能号,并根据用户输入的功能选择相应的功能。
三、参考代码
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<syslog.h>
#include<string.h>
#include<stdlib.h>
#define MAX 128
int chmd()
{
int c;
mode_t mode=S_IWUSR;
printf("0.0700\n 1.0400\n 2.0200\n 3.0100\n");//还可以增加其他权限printf("Please input your choice(0-3):");
scanf("%d",&c);
switch(c)
{
case 0:chmod("file1",S_IRWXU);break;
case 1:chmod("file1",S_IRUSR);break;
case 2:chmod("file1",S_IWUSR);break;
case 3:chmod("file1",S_IXUSR);break;
default:printf("You have a wrong choice!\n");
}
return(0);
}
main()
{
int fd;
int num;
int choice;
char buffer[MAX];
struct stat buf;
char*path="bin/ls";
char*argv[4]={"ls","-1","file1",NULL};
while(1)
{
printf("*******************************\n");
printf("0.退出\n");
printf("1.创建新文件\n");
printf("2.写文件\n");
printf("3.读文件\n");
printf("4.修改文件权限\n");
printf("5.查看当前文件的权限并退出\n");
printf("************************************\n");
printf("Please input your choice(0-6):");
scanf("%d",&choice);
switch(choice)
{
case 0:close(fd);//关闭file1文件
exit(0);
case 1:
fd=open("file1",O_RDWR|O_TRUNC|O_CREAT,0750);//创建file1
if(fd==-1)
printf("File Create Failed!\n");
else
printf("fd=%d\n",fd); //显示fileID
case 2:
num=read(0,buffer,MAX);//从键盘里面读取最多128个字符
write(fd,buffer,num); //从读入的信息送到file1里去
break;
case 3:
/*把file1文件的内容在屏幕上输出*/
read(fd,buffer,MAX);
write(1,buffer,num);
break;
case 4:
chmd();
printf("Change mode success!\n");
break;
case 5:
execv(path,argv); //执行ls-l file1
break;
default:
printf("You have a wrong choice!\n");
}
}
}。