linux系统调用和文件操作

合集下载

LinuxC讲解系统调用readdir,readdir_r以及如何遍历目录下的所有文件

LinuxC讲解系统调用readdir,readdir_r以及如何遍历目录下的所有文件

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内核中系统调用详解什么是系统调用?(Linux)内核中设置了一组用于实现各种系统功能的子程序,称为系统调用。

用户可以通过系统调用命令在自己的应用程序中调用它们。

从某种角度来看,系统调用和普通的函数调用非常相似。

区别仅仅在于,系统调用由(操作系统)核心提供,运行于核心态;而普通的函数调用由函数库或用户自己提供,运行于用户态。

随Linux核心还提供了一些(C语言)函数库,这些库对系统调用进行了一些包装和扩展,因为这些库函数与系统调用的关系非常紧密,所以习惯上把这些函数也称为系统调用。

为什么要用系统调用?实际上,很多已经被我们习以为常的C语言标准函数,在Linux 平台上的实现都是靠系统调用完成的,所以如果想对系统底层的原理作深入的了解,掌握各种系统调用是初步的要求。

进一步,若想成为一名Linux下(编程)高手,也就是我们常说的Hacker,其标志之一也是能对各种系统调用有透彻的了解。

即使除去上面的原因,在平常的编程中你也会发现,在很多情况下,系统调用是实现你的想法的简洁有效的途径,所以有可能的话应该尽量多掌握一些系统调用,这会对你的程序设计过程带来意想不到的帮助。

系统调用是怎么工作的?一般的,进程是不能访问内核的。

它不能访问内核所占内存空间也不能调用内核函数。

(CPU)(硬件)决定了这些(这就是为什么它被称作"保护模式")。

系统调用是这些规则的一个例外。

其原理是进程先用适当的值填充(寄存器),然后调用一个特殊的指令,这个指令会跳到一个事先定义的内核中的一个位置(当然,这个位置是用户进程可读但是不可写的)。

在(Intel)CPU中,这个由中断0x80实现。

硬件知道一旦你跳到这个位置,你就不是在限制模式下运行的用户,而是作为操作系统的内核--所以你就可以为所欲为。

进程可以跳转到的内核位置叫做sysem_call。

这个过程检查系统调用号,这个号码告诉内核进程请求哪种服务。

然后,它查看系统调用表(sys_call_table)找到所调用的内核函数入口地址。

linux命令操作手册

linux命令操作手册

linux命令操作手册一、文件操作1.1 创建文件:使用touch命令可以创建一个空文件,语法为“touch 文件名”。

1.2 编辑文件:使用文本编辑器(如vi、nano等)可以编辑文件,语法为“编辑器文件名”。

1.3 复制文件:使用cp命令可以复制文件,语法为“cp 源文件目标文件”。

1.4 移动文件:使用mv命令可以移动文件,语法为“mv 源文件目标目录”。

1.5 删除文件:使用rm命令可以删除文件,语法为“rm 文件名”。

二、目录操作2.1 创建目录:使用mkdir命令可以创建目录,语法为“mkdir 目录名”。

2.2 删除目录:使用rmdir命令可以删除目录,语法为“rmdir 目录名”。

2.3 移动目录:使用mv命令可以移动目录,语法为“mv 目录名目标目录”。

2.4 复制目录:使用cp命令可以复制目录,语法为“cp -r 源目录目标目录”。

三、文本操作3.1 查看文件内容:使用cat命令可以查看文件内容,语法为“cat 文件名”。

3.2 编辑文件内容:使用文本编辑器(如vi、nano等)可以编辑文件内容。

3.3 查找文本:使用grep命令可以查找文本,语法为“grep '查找内容' 文件名”。

3.4 替换文本:使用sed命令可以替换文本,语法为“sed 's/查找内容/替换内容/g' 文件名”。

四、压缩与解压4.1 压缩文件:使用tar命令可以压缩文件,语法为“tar -czvf 压缩文件名.tar.gz 源文件或目录名”。

4.2 解压文件:使用tar命令可以解压文件,语法为“tar -xzf 压缩文件名.tar.gz”。

五、文件查找5.1 查找文件:使用find命令可以查找文件,语法为“find 查找路径-name '文件名'”。

5.2 查找目录:使用find命令可以查找目录,语法为“find 查找路径-type d -name '目录名'”。

系统调用知识点总结

系统调用知识点总结

系统调用知识点总结一、系统调用的概念系统调用是操作系统内核提供给用户程序的接口,用于访问操作系统内核提供的服务和资源。

操作系统提供了各种系统调用,包括文件操作、进程管理、网络通信、内存管理、设备管理等。

用户程序通过系统调用可以向操作系统请求服务,比如打开文件、创建进程、发送网络数据等。

系统调用是用户程序和操作系统内核之间的桥梁,它为用户程序提供了访问操作系统内核功能的途径。

二、系统调用的实现原理系统调用的实现原理涉及到用户态和内核态的切换。

当用户程序执行系统调用时,会触发处理器从用户态切换到内核态,然后执行相应的内核代码。

在Linux系统中,系统调用的实现原理一般包括以下几个步骤:1. 用户程序通过系统调用指令(比如int 0x80或syscall指令)发起系统调用请求。

2. 处理器从用户态切换到内核态,执行相应的内核代码。

3. 内核根据系统调用号(syscall number)找到相应的系统调用处理函数。

4. 内核执行系统调用处理函数,完成相应的操作。

5. 内核将处理结果返回给用户程序,然后从内核态切换回用户态。

三、系统调用的调用方式系统调用的调用方式包括直接调用、库函数封装和系统命令等。

用户程序可以通过直接调用系统调用指令来执行系统调用,也可以通过库函数封装的方式来调用系统调用,比如C 标准库中的文件操作函数(如open、read、write等)就是封装了系统调用的库函数,用户程序可以直接调用这些库函数来进行文件操作。

此外,用户程序还可以通过系统命令来触发系统调用,比如在命令行中使用cat命令来读取文件就是通过系统命令来触发系统调用。

四、常用系统调用常用系统调用包括文件操作、进程管理、网络通信、内存管理、设备管理等。

在Linux系统中,常见的系统调用包括:1. 文件操作系统调用:open、read、write、close、lseek等。

2. 进程管理系统调用:fork、exec、wait、exit等。

linux应用程序的编写实验原理

linux应用程序的编写实验原理

Linux应用程序的编写实验原理1. 概述本文档旨在介绍Linux应用程序的编写实验原理。

Linux是一种开源操作系统,拥有强大的稳定性和灵活性,因此在开发应用程序时,使用Linux作为开发平台是很常见的选择。

本文将介绍Linux应用程序的基本概念和原理,并提供一些编写实验的指导。

2. Linux应用程序概念Linux应用程序是为Linux操作系统编写的软件程序。

它们通过使用系统调用和相关的库函数与操作系统进行交互。

Linux应用程序可以包括命令行工具、图形界面程序和服务器端应用程序等。

3. Linux应用程序编写原理要编写一个Linux应用程序,需要掌握以下原理:3.1 系统调用系统调用是Linux应用程序与操作系统之间的接口。

通过系统调用,应用程序可以请求操作系统提供各种服务,如文件操作、进程管理、网络通信等。

常用的系统调用包括open、read、write、fork、exec等。

3.2 进程和线程管理Linux应用程序是以进程或线程的形式运行的。

进程是一个独立的执行实体,拥有自己的地址空间和系统资源。

线程是进程内的一个执行单元,多个线程可以共享同一进程的资源。

编写Linux应用程序时,需要了解进程和线程的创建、销毁和调度等管理操作。

3.3 文件操作Linux应用程序可以通过文件操作来读写文件。

文件可以是文本文件、二进制文件、设备文件等。

在编写应用程序时,需要使用相关的系统调用和库函数,如open、read、write、close等,来进行文件的打开、读写和关闭操作。

3.4 网络通信Linux应用程序可以通过网络进行通信。

常用的网络通信方式包括套接字编程和网络协议。

套接字编程提供了一种通用的网络编程接口,可以实现不同主机之间的数据传输。

网络协议则规定了数据在网络中的传输方式和格式。

编写网络应用程序需要了解套接字编程和网络协议。

3.5 图形界面编程Linux应用程序可以利用图形界面提供用户友好的交互方式。

linux 读取文件的原理

linux 读取文件的原理

linux 读取文件的原理
Linux 读取文件的原理主要涉及到操作系统、文件系统和硬件等多个方面。

下面是一个简要的概述:
1.文件系统:Linux 系统使用的是类Unix 的文件系统,称为Ext4。

文件系统负责管理文件在硬盘上的存储和访问,以及文件的权限和属性等信息。

当一个程序试图读取一个文件时,文件系统会接收到这个请求,并查找文件在硬盘上的位置。

2.打开文件:要读取一个文件,首先需要打开这个文件。

在Linux 中,打开文件是通过系统调用(如open() 或fopen())实现的。

这些系统调用会向操作系统发出请求,请求中包含文件名和打开文件的模式(例如只读、写入等)。

操作系统会查找文件并返回一个文件描述符,这个文件描述符是一个整数,用于标识已经打开的文件。

3.读取文件数据:一旦文件被打开,就可以通过系统调用(如read() 或fread())来读取文件的内容。

这些系统调用会向操作系统发出请求,请求中包含文件描述符、读取的起始位置和要读取的字节数。

操作系统会将读取的请求传递给硬件,硬件会从硬盘中读取相应的数据,并将其存储在内存中。

4.关闭文件:当读取完文件后,需要通过系统调用(如close() 或fclose())来关闭文件。

这个系统调用会将文件描述符释放回操作系统,以便其他程序可以使用它。

linux 系统调用流程

linux 系统调用流程

linux 系统调用流程Linux系统调用流程一、引言Linux是一种自由开源的操作系统,其核心部分是内核。

内核负责管理计算机的硬件资源,并提供各种系统调用供用户程序使用。

本文将介绍Linux系统调用的流程,包括用户程序如何通过系统调用接口向内核发起请求以及内核如何处理这些请求。

二、系统调用的定义系统调用是用户程序与内核之间的接口。

用户程序通过调用特定的系统调用函数来请求内核执行某些操作,例如读写文件、创建进程等。

内核接收到这些请求后,会进行相应的处理并返回结果给用户程序。

三、系统调用的流程1. 用户程序发起系统调用请求用户程序通过调用系统调用函数向内核发起请求。

这些系统调用函数通常由C库提供,并在用户程序中使用。

用户程序需要提供相应的参数,以告知内核所需的操作类型和操作对象。

2. 用户程序转入内核态用户程序发起系统调用请求后,会进入内核态。

在内核态下,用户程序的权限更高,可以执行一些普通用户无法执行的操作,例如访问硬件资源。

3. 内核处理系统调用请求内核接收到系统调用请求后,会根据请求的类型和参数进行相应的处理。

内核会首先检查请求的合法性,验证用户程序的权限和参数的有效性。

如果请求合法,内核会执行相应的操作;如果请求非法,内核会返回错误信息给用户程序。

4. 内核执行系统调用操作内核根据系统调用请求的类型和参数执行相应的操作。

例如,如果用户程序请求打开一个文件,内核会检查文件是否存在,并分配相应的文件描述符。

如果用户程序请求创建一个进程,内核会为进程分配资源并初始化进程上下文。

5. 内核返回结果给用户程序内核在执行完系统调用操作后,会将结果返回给用户程序。

如果操作成功,内核会返回相应的数据或完成状态;如果操作失败,内核会返回错误码,用户程序可以根据错误码进行相应的处理。

6. 用户程序继续执行用户程序在接收到内核返回的结果后,会根据结果进行相应的处理。

如果操作成功,用户程序可以继续执行后续的逻辑;如果操作失败,用户程序可以根据错误码采取相应的措施,例如重新尝试或向用户报告错误信息。

Linux(CC++)下的文件操作open、fopen与freopen

Linux(CC++)下的文件操作open、fopen与freopen

Linux(CC++)下的⽂件操作open、fopen与freopenopen是下的底层系统调⽤函数,fopen与freopen c/c++下的标准I/O库函数,带输⼊/输出缓冲。

linxu下的fopen是open的封装函数,fopen最终还是要调⽤底层的系统调⽤open。

所以在linux下如果需要对设备进⾏明确的控制,那最好使⽤底层系统调⽤(open),open对应的⽂件操作有:close, read, write,ioctl 等。

fopen 对应的⽂件操作有:fclose, fread, fwrite, freopen, fseek, ftell, rewind等。

freopen⽤于重定向输⼊输出流的函数,该函数可以在不改变代码原貌的情况下改变输⼊输出环境,但使⽤时应当保证流是可靠的。

详细见第3部分。

-------------------------------------------------------------------------------------------------------------------open和fopen的区别:1,fread是带缓冲的,read不带缓冲.2,fopen是标准c⾥定义的,open是POSIX中定义的.3,fread可以读⼀个结构.read在linux/unix中读⼆进制与普通⽂件没有区别.4,fopen不能指定要创建⽂件的权限.open可以指定权限.5,fopen返回⽂件指针,open返回⽂件描述符(整数).6,linux/unix中任何设备都是⽂件,都可以⽤open,read.-------------------------------------------------------------------------------------------------------------------1、open系统调⽤(linux)需要包含头⽂件:#include<sys/types.h>#include<sys/stat.h>#include<fcntl.h>函数原型:int open( const char * pathname, int oflags);int open( const char * pathname,int oflags, mode_t mode);mode仅当创建新⽂件时才使⽤,⽤于指定⽂件的访问权限。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

零、本课程能学到的内容
1、文件系统及文件的IO操作。

2、linux的多进程编程。

3、linux的多线程编程。

4、进程及线程之间的同步和异步通信
5、linux的网络编程(编写服务器、客户端、TCP、UDP程序)。

一、linux的系统调用
用户程序通过软中断的方式,让cpu切换到内核态运行,数据就借此传输。

对于CPU来说,它不知道现在运行是用户程序还是内核程序。

软中断后,cpu根据拿到的数据,进行特定的任务,然后退出中断,将任务的结果交回给用户程序。

这个任务如何描述?是通过数字来编号的。

例子:写一个打印字符串的程序,通过系统调用来完成。

需要传递的参数有:指向字符串的指针(字符串的首地址),字符串的长度。

汇编写法
用int$0x80产生软中断
C的写法
直接使用syscall函数(它的本质就是用软中断来产生系统调用)
系统调用编号见:/usr/include/asm/unistd_32.h里
一共有358个。

其中,4号对应的write调用。

二、linux文件系统基础
扇区(sector):磁头读取的最小单位数据,在磁盘上类似一个扇子的形状。

一般是512个字节。

块(block):软件读取磁盘的最小单位数据,一般来说是扇区的2的n次幂大小,常用的有4096个字节。

块就是文件存放的最小单位。

如果有一个文件是15045个字节,那么就分成4个块存储,最后那个块的数据是不满的。

可以用数组的方式将一个文件的所有数据块的编号保存起来。

这个数组多大合适?
前提是数组大小要固定,才好管理。

用一个15元素的数组来保存数据块的编号。

其中0-11元素,保存数据块的前面12个,第12个元素是一个一级指针,指向另一个表格,那个表格是4096字节,可以保存1024个块的编号。

如果还不够,第13个元素是一个二级指针,指向的那个表格是一级指针表格。

14个元素是三级指针,指向的表格是二级指针表格。

全部用完可以存储2G大小的文件的数据块编号。

在文件系统内部,如何来表示一个文件呢?
用一个inode结构体来表示一个文件。

inode是index node的意思。

也叫索引节点。

一个索引节点对应一个文件,有多少个文件就有多少个索引节点。

inode结构体里面有文件的大小、文件的修改时间、文件的权限、文件的数据块的编号数组。

inode结构体数组保存了所有文件的inode,这个数组的下标就是inode编号。

文件名或者目录名保存目录文件的数据块里面。

在linux里面,一个目录也是一个文件,叫做目录文件,其它的叫做普通文件。

目录文件里就有,inode编号和文件名的对应关系。

那么,给出文件路径时,如何找到这个文件的数据块?
/usr/include/stdio.h
首先,找到根目录的数据块,从里面找到文件和inode编号关系表,
例如usr这个文件名和inode编号为10002是对应的,那么就到inode结构体数组里找出下标为10002的元素,得到对应文件usr的数据块,因为usr也是一个文件夹,既然是文件夹,它的数据块里面也会有关系表,就可以找到include这个文件的数据块,最后找到stdio.h的数据块,这个是一个普通文件,就把它的数据块全部取出来。

这里搜索的起点是根目录的数据块,那么这个文件的数据块到哪里找?
在一个磁盘里面,最开始的几个块,存储了本磁盘的很多重要数据,例如块的大小,有哪些inode下标空闲,哪些已经用了,最重要的是根目录的数据块。

所有的参数存放在其中的一个块,这个块叫做超级块(super block)。

在磁盘格式化,实际就是生成一个超级块。

这个块的重要性毋庸置疑,如果数据被损坏,则磁盘没办法使用。

三、打开文件
在linux里面,用open函数就可以打开一个文件。

函数原型:int open(const char*path,int flag)
函数如果打开成功,则返回一个文件描述符f ile d escribtor,这个描述符fd是一个非负整数。

1、文件描述符
在文件被打开后,需要用一个结构体来描述这个被打开的文件。

这个结构体是struct file。

它包含了文件的读写指针、文件的长度、文件的属主等等重要属性。

另外,对于任意一个程序(进程),还有一个结构体,描述当前程序打开的所有文件。

struct files_struct
fd就是fd_array数组的下标。

打开一个文件后,生成一个struct file来保管文件的属性,然后将该结构体的首地址放到fd_array数组里面的一个空闲的位置,然后将该元素的下标返回。

下次如果要访问这个文件,直接拿着下标去找就行了。

需要说明的是,对于任意一个程序来说,一般都会默认打开三个文件,键盘输入端、屏幕输出端、错误输出端。

它们的编号分别为0,1,2。

在我们用open打开一个文件的时候,一般会在描述符里面找出一个最小的空闲描述符作为文件的描述符。

利用这个技术,可以人为的关闭屏幕输出端1,然后再打开另外一个文件,这个时候,printf就会自动将文字输出那个文件里。

2、错误代码
在系统调用失败的时候,系统会自动往一个全局变量写一个数据,就是错误代码。

这个全局变量是int errno。

单单看这个变量是没意义的,必须要解读。

可以用strerror(errno)来将这个数据解读成一个字符串。

errno需要包含errno.h头文件,strerror需要包含string.h。

另外还可以使用perror来打印错误信息。

小结:
1、用户程序通过系统调用的方式让内核执行特定的任务,系统调用是通过软中
断实现的。

2、系统内部用inode来唯一确定一个文件。

3、文件打开后,用struct file结构体来描述这个文件的属性,对于程序(进程而
言),有一个struct files_struct结构体描述程序打开的所有文件,里面的fd_array数组保存着指向各个struct file的指针,open的返回值就是fd_array 数组的最小可用下标。

4、默认的文件描述符0-输入,1-输出,2-错误输出。

5、出错后,errno这个全局变量会保存错误的代码,用strerror可用解读出信息。

相关文档
最新文档