【linux】linux系统调用及文件IO操作

一、系统调用

1、概述 

        系统调用: 就是操作系统内核 提供给用户可以操作内核 一组函数接口。用户 借助 系统调用 操作内核。比如用户可以通过文件系统相关的调用请求系统打开文件、关闭文件或读写文件,可以通过时钟相关的系统调用获得系统时间或设置定时器等。

        进程的空间分为:内核空间 和 用户空间。系统调用是属于操作系统内核的一部分,运行在内核态下,通过软件中断切换到内核态。

2、系统调用和库函数区别

系统调用 是内核提供的一组函数接口。

库函数 是第三方(用户提供)的函数接口。

        如果库函数没有调用系统调用该库函数不能操作内核。比如:字符串操作函数strcpy, bzero

        如果库函数 调用 系统调用该库函数能操作内核。比如:fopen fclose fwrite fget

3、系统调用及IO操作 

        系统调用是需要时间的,程序中频繁的使用系统调用会降低程序的运行效率。 文件IO中缓冲区刷新机制需要内核管理,库函数访问文件的时候根据需要,设置不同类型的缓冲区,从而减少了直接调用IO系统调用的次数,提高了访问效率。

二、文件描述符

1、概述 

        在 Linux的世界里一切设备皆文件,我们可以系统调用I/O 的函 数(I:input,输入;0:output..输出),对文件进行相应的操作 ( open()、close()、write()、read()等。

        打开现存文件或新建文件时,系统(内核)会返回一个文件描述符,文件描述符用来指定已打开的文件。这个文件描述符相当于这个已打开文件的标号,文件描述符是非负整数,是文件的标识,操作这个文件描述符相当于操作这个描述符所指定的文件。

        Linux将系统调用 打开或新建的文件 用非负整数 来表示。而这个非负整数 就是文件描述 符。

        系统会为每一个进程文件 分配一个文件描述符表管理该进程的所有文件描述符

        系统会为 每一个进程文件 打开三个文件描述符:0,1,2

  • 0:标准输入设备(键盘) scanf
  • 1:标准输出设备(终端)printf
  • 2:标准错误输出 (终端)perror

2、文件描述符表对文件描述符的管理

         文件描述符表 是通过 “位图” 来管理文件描述符。使用1024位(0-1023)二进制位管理,位数代表 的就是文件描述符,位上的值1表示打开,值0表示关闭,前三位(0-2)为标准文件描述符。打开文件的时候默认选择最小可用的文件描述符(3)给打开的文件用。

3、查看当前系统文件描述符最大数量ulimit -a

        查看命令:ulimit -a

修改命令:ulimit -n 2048 

 

三、文件IO的操作

        文件常用操作IO:open close read write

1、打开文件 open 

头文件: 

#include<sys/type.h>

#include<sys/stat.h>

#include <funtl.h>

相关函数: 

 函数功能: 打开文件,如果文件不存在则可以选择创建。

//二参数open用于 打开已存在的文件

int open(const char *pathname, int flags);

//三参数open用于 打开不存在的文件 mode是文件在磁盘上的权限 

int open(const char *pathname, int flags, mode_t mode);

//返回值:成功返回最小文件描述符,失败返回-1

参数:

  • pathname:文件的路径及文件名
  • flags:打开文件的行为标志,必选项 O_RDONLY(以只读方式打开, O_WRONLY(以只写方式打开), O_RDWR(以可读可写方式打开) 
  • mode:这个参数,只有在文件不存在时有效,指新建文件时指定文件的磁盘权限

 flags 文件的操作权限可选项,和必选项按位或起来:

取值含义
O_CREAT文件不存在则创建文件,文件存在则先删除再重新创建文件,使用此选项时需使用mode说明文件的权限
O_EXCL如果同时指定了O_CREAT,且文件已经存在,则出错(防止已有文件被删除)
O_TRUNC如果文件存在,则清空文件内容
O_APPEND写文件时,数据添加到文件末尾
O_NONBLOCK对于设备文件, 以O_NONBLOCK方式打开可以做非阻塞I/O

mode文件在磁盘的用户权限:

        磁盘文件的用户权限分类:所有拥有者权限(u)、同组用户权限(g)、其他用户权限(o)

 权限分为:读(4)、写(2)、执行(1),可以相互组合:

7--->可读可写可执行         6--->可读可写         5--->可读可执行

4--->只读        3--->可写可执行         2--->只写         1--->可执行

mode的权限表示0xxx 每一个x都是4、2、1的组合,如:

前第一个0代表其为八进制数:

0777 所有者、同组用户、其他用户都是可读可写可执行

0666 所有者、同组用户、其他用户都是可读可写

查看mode的系统权限掩码umask

        查看掩码命令:umask

 文件的最终权限=给定的权限异或掩码( & ~umask)

umask mode:设置掩码,mode为八进制数

umask -S:查看各组用户的默认操作权限

2、close 关闭文件描述符

        头文件:#include<unistd.h>

        函数:int close(int fd);

功能: 关闭已打开的文件

参数: fd : 文件描述符,open()的返回值

返回值: 成功:0 失败: -1并存放在全局变量errno中

        注意:close工作步骤,先将文件描述符的数量-1,当文件描述符的数量变为0的时候 ,系统回收文件描述符所占的内核空间。

 3、向文件写数据write

头文件:#include<unistd.h>

函数:size_t write(int fd, const void *buf, size_t count);

功能: 把指定数目的数据写到文件fd中

参数:

        fd : 文件描述符

        buf : 数据首地址

        count : 写入数据的长度(字节)

返回值: 成功:实际写入数据的字节个数 失败: - 1 

4、read读取文件数据

        #include<unistd.h>

        size_t read(int fd, void *buf, size_t count);

功能: 把指定数目的数据读到内存(缓冲区)

参数:

        fd : 文件描述符

        buf : 内存首地址

        count : 读取的字节个数

返回值: 成功:实际读取到的字节个数,读完文件数据返回0         失败: - 1 

 5、综合案例:实现cp(copy)命令

        举例:cp b.txt test 将b.txt文件拷贝到test目录中

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/fcntl.h>
int main(int argc,char *argv[])//argc为传参个数,指针数组argv存放每个参数的内容
{//判断参数是否正确(./a.out a.txt test)//若正确,argc=3,argv[0]=./a.out,argv[1]=a.txt,argy[2]=testif(argc!=3){printf("缺少参数");return 0;}//以只读的方式 打开a.txt文件int fp_r=open(argv[1],O_RDONLY);if(fp_r<0){perror("open");return 0;}//以写的方式 在test目录中打开a.txtchar filename[32]="";sprintf(filename,"%s/%s",argv[2],argv[1]);int fp_w=read(filename,O_WRONLY|O_CREAT,0666);if(fp_w<0){perror("open");return 0;}//不同的从fd_r中读取文件数据 写入fd_w文件中while(1){unsigned char buf[128]="";int len=read(fp_r,buf,sizeof(buf));if(len<=0)break;printf("读取的数据大小为%d",len);write(fp_w,buf,sizeof(buf));}//关闭文件close(fp_r);close(fp_w);return 0;
}

四、文件的阻塞特性 

        对于一些设备文件读写操作,如管道,套接字,标准设备文件,默认缓冲区没有数据读会带阻塞,默认缓存区满的状态,写也会阻塞。

        文件描述符决定阻塞和非阻塞,而不是read write函数。文件描述符默认为阻塞的。

1、open打开文件 默认为阻塞特性

        文件描述符 事先不存在用open。如果从终端输入的数据没有换行符,默认调用read读终端设备就会阻塞。

2、 open打开文件 设置为非阻塞特性

3、通过fcntl设置文件的阻塞特性 

        文件描述符事先存在用funtl。 功能:改变已打开的文件性质,fcntl针对描述符提供控制。

头文件:

#include<unistd.h>

#include<fcntl.h>

函数:

int fcntl(int fd, int cmd, ... /* arg */ );

参数:

fd:操作的文件描述符

cmd:操作方式

arg:针对cmd的值,fcntl能够接受第三个参数int arg。

返回值: 成功:返回某个其他值 失败:-1

fcntl函数有5种cmd功能:

  1.  复制一个现有的描述符(cmd=F_DUPFD)
  2. 获得/设置文件描述符标记(cmd=F_GETFD或F_SETFD)
  3. 获得/设置文件状态标记(cmd=F_GETFL或F_SETFL)
  4. 获得/设置异步I/O所有权(cmd=F_GETOWN或F_SETOWN)
  5. 获得/设置记录锁(cmd=F_GETLK, F_SETLK或F_SETLKW) 

设置一个存在的文件描述符的阻塞特性的步骤

  1. fcntl获取文件描述符的状态标记
  2. 修改 获取到的 文件描述符的状态标记
  3. 将修改后的状态标记 使用fcntl设置到文件描述符中 

五、获取文件的状态信息

头文件: 

#include<sys/type.h>

#include<sys/stat.h>

#include<unistd.h>

函数: 

int stat(const char *path, struct stat *buf);

int lstat(const char *pathname, struct stat *buf);  

功能: 获取文件状态信息

        stat和lstat的区别: 当文件是一个符号链接时,lstat返回的是该符号链接本身的信息; 而stat返回的是该链接指向的文件的信息。

参数:

path/pathname:文件名

buf:保存文件信息的结构体

返回值: 成功: 0 失败: -1 

struct stat结构体说明:

struct stat {dev_t st_dev; //文件的设备编号ino_t st_ino; //节点mode_t st_mode; //文件的类型和存取的权限nlink_t st_nlink; //连到该文件的硬连接数目,刚建立的文件值为1uid_t st_uid; //用户IDgid_t st_gid; //组IDdev_t st_rdev; //(设备类型)若此文件为设备文件,则为其设
备编号off_t st_size; //文件字节数(文件大小)blksize_t st_blksize; //块大小(文件系统的I/O 缓冲区大小)blkcnt_t st_blocks; //块数time_t st_atime; //最后一次访问时间time_t st_mtime; //最后一次修改时间time_t st_ctime; //最后一次改变时间(指属性)
};

 st_mode(16位整数)参数说明 :

        由于上述形式的测试是普通的,因此POSIX定义了其他宏,以便更简洁地编写st_mode中的文件类型测试:

S_ISREG(st_mode)

是否是普通文件(regular file)
S_ISDIR(st_mode)是否是目录文件(directory)
S_ISCHR(st_mode)是否是字符设备(character device)
S_ISBLK(st_mode)块设备(block device)
S_ISFIFO(st_mode)管道
S_ISLNK(st_mode)符号链接(软连接)

st_mode控件的文件模式组件定义了下列掩码值:

六、文件目录操作 

        读取一个目录下的所有文件名 

1、打开目录(得到文件目录的句柄)

头文件:

#include<sys/types.h>

#include<dirent.h>

函数:

DIR *opendir(const char *name);

功能:打开一个目录

参数name:目录名

返回值: 成功:返回指向该目录结构体指针 失败:NULL

2、读取目录 

#include<dirent.h>

struct dirent *readdir(DIR *dirp);  

功能:读取目录 调用一次只能读取一个文件

参数 dirp:opendir的返回值

返回值: 成功:目录结构体指针 失败:NULL 

 结构体dirent说明:

struct dirent
{ino_t d_ino; // 此目录进入点的inodeoff_t d_off; // 目录文件开头至此目录进入点的位移signed short int d_reclen; // d_name 的内容长度, 不包含NULL 字符unsigned char d_type; // d_type 所指的文件类型char d_name[256]; // 文件名
};

d_type相关数据:

 3、关闭目录

头文件:

#include<sys/types.h>

#include<dirent.h>

函数:

int closedir(DIR *dirp);

功能:关闭目录

参数dirp:opendir返回的指针

返回值: 成功:0 失败:-1 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/720374.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何创建测试计划?这些要考虑到

以下为作者观点&#xff1a; 创建一个彻底和有效的测试计划对软件测试的成功至关重要。它可以帮助识别过程中可能出现的潜在问题或问题。 什么是测试计划&#xff1f; 测试计划是一份文件&#xff0c;概述了软件测试过程的策略、目标、资源和时间表。测试计划通常包括一些细…

uniapp 项目 浏览器chrome使用vue devtool 识别不了 in not detect

问题 uniapp的项目&#xff0c;vue2&#xff0c; chrome 分析 添加了运行时&#xff0c;指定模板h5.html 指定的h5.html重置了运行根目录&#xff0c;导致了vue dev tool在运行时&#xff0c;chrome上识别不了。 解决&#xff1a; 方法1&#xff1a; 只能调试的时候,不加sati…

java常用应用程序编程接口(API)——Arrays概述

前言&#xff1a; 学到Arrays了&#xff0c;整理下心得。打好基础&#xff0c;daydayup! Arrays 用来操作数组的一个工具类 Arrays的常见方法 方法名说明public static String toString(类型[] arr)返回数组的内容public static int[ ] copyOfRange(类型[ ] arr,启示索引&…

Linux - 安装 maven(详细教程)

目录 一、下载二、安装三、配置环境变量四、镜像资源配置 一、下载 官网&#xff1a;https://maven.apache.org/download.cgi 打开 maven 的官网下载页面&#xff0c;点击 bin.tar.gz 文件链接 即可下载最新版本的 maven 如果想要下载旧版本的 meven&#xff0c;则点击 Maven…

图形系统开发实战课程:进阶篇(上)——9.空间算法(一)

图形开发学院&#xff5c;GraphAnyWhere 课程名称&#xff1a;图形系统开发实战课程&#xff1a;进阶篇(上)课程章节&#xff1a;“图形样式”原文地址&#xff1a;https://www.graphanywhere.com/graph/advanced/2-9.html 第九章 空间算法&#xff08;一&#xff09; \quad 在…

SpringBoot 自定义映射规则resultMap collection一对多

介绍 collection是封装一对多关系的&#xff0c;通常情况下是一个列表&#xff0c;association是一对一&#xff0c;通常情况是一个对象。例如&#xff1a;查询班级下所有的学生&#xff0c;一个班级可以有多个学生&#xff0c;这就是一对多。 案例 有一个学生表&#xff0c…

Go语言中的时间控制:定时器技术详细指南

Go语言中的时间控制&#xff1a;定时器技术详细指南 引言定时器基础创建和使用time.Timer使用time.Ticker实现周期性任务定时器的内部机制小结 使用time.Timer实现简单的定时任务创建和启动定时器停止和重置定时器定时器的实际应用小结 利用time.Ticker处理重复的定时任务创建和…

这里推荐一款unity3d人物动物控制器详细的等学会再写文章

unity3d Animal Controller 1.4.0a 动物NPC行为控制器 动物控制器&#xff08;AC&#xff09;是一个基于脚本架构的动画框架控制器。它适用于任何动物或人形角色的根运动或原地动画。 人和动物的各种动作都有; 小白必选、 我只是运行乐demo就感觉牛 demo路径&#xff1a;Asset…

Python不换行print在终端中不显示

问题描述 当使用不换行 print 即 print(‘test, end) 后立即关闭标准输出 sys.stdout open(os.devnull, w)则 print 的内容不会显示在正常的终端上&#xff08;例外是 PyCharm 中的终端能够正常显示&#xff09;。 复现问题 复现该问题的简易代码&#xff1a; import sys,…

基于pytorch的手写体识别

一、环境搭建 链接: python与深度学习——基础环境搭建 二、数据集准备 本次实验用的是MINIST数据集&#xff0c;利用MINIST数据集进行卷积神经网络的学习&#xff0c;就类似于学习单片机的点灯实验&#xff0c;学习一门机器语言输出hello world。MINIST数据集&#xff0c;可以…

【go从入门到精通】go环境安装和第一个经典程序

go下载和环境变量配置 下载地址 Go官网下载地址&#xff1a;https://golang.org/dl/All releases - The Go Programming Languagehttps://golang.org/dl/ 然后根据自己的系统环境来选择不同的安装包下载&#xff0c;下面我分别针对不同环境进行说明&#xff08;大家可以根据自…

Platformview在iOS与Android上的实现方式对比

Android中早期版本Platformview的实现基于Virtual Display。VirtualDisplay方案的原理是&#xff0c;先将Native View绘制到虚显&#xff0c;然后Flutter通过从虚显输出中获取纹理并将其与自己内部的widget树进行合成&#xff0c;最后作为Flutter在 Android 上更大的纹理输出的…

Unity2023.1.19_ECS_DOTS

Unity2023.1.19_ECS_DOTS 盲学-盲目的学习&#xff1a; 懒着自己整理就看看别人整理的吧&#xff0c;整合一下逻辑通了不少&#xff1a; DOTS/data oriented technology stack-面向数据的技术栈 ECS/Entities-Component-System Unity-Entities包 Entities提供ECS架构面向数…

BUUCTF---[ACTF2020 新生赛]BackupFile1

1.题目描述 2.题目提示backup file &#xff0c;是备份文件的意思。点开链接&#xff0c;页面提示 3.查看源码没有什么有用信息&#xff0c;也没有登录界面&#xff0c;所以也不会用到蚁剑链接来找备份文件&#xff0c;所以大概率就是通过构造playload来查找备份文件。 4.备份…

新手想玩硬件,买单片机还是树莓派好?

新手想玩硬件&#xff0c;买单片机还是树莓派好&#xff1f; 在开始前我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「单片机的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&#x…

Springboot+vue的船舶监造系统(有报告)。Javaee项目,springboot vue前后端分离项目。

演示视频&#xff1a; Springbootvue的船舶监造系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot vue前后端分离项目。 项目介绍&#xff1a; 本文设计了一个基于Springbootvue的船舶监造系统&#xff0c;采用M&#xff08;model&#xff09;V&#xff…

二百二十六、Linux——shell脚本查看今天日期、昨天日期、30天前日期、1月前日期

一、目的 由于磁盘资源有限&#xff0c;因为对原始数据的保存有事件限制&#xff0c;因为对于超过一定期限的数据文件则需要删除&#xff0c;要实现定期删除则第一步就是查看日期时间 二、在Linux中创建shell脚本 #! /bin/bash source /etc/profile nowdatedate --date0 da…

Linux 学习笔记(11)

十一、 资源监控 1 、 free 内存监控 语 法&#xff1a; free [-bkmotV][-s < 间隔秒数 >] 补充说明&#xff1a; free 指令会显示内存的使用情况&#xff0c;包括实体内存&#xff0c;虚拟的交换文件内存&#xff0c;共享内存区段&#xff0c;以 及系统核心使用的…

[计算机网络]:流量控制

一、流量控制简介 一条TCP连接的每一侧主机都为其设置了接收缓存&#xff0c;当TCP成功连接后&#xff0c;它发送的数据会放入接受缓存中。相关联的进程会从缓存中读取数据。但是存在一个问题&#xff0c;当某应用程序读取数据速率太慢&#xff0c;而发送数据一方不停的发送数…

【数据结构】复杂度详解

目录 &#xff08;一&#xff09;算法的复杂度 &#xff08;二&#xff09;时间复杂度 &#xff08;1&#xff09;练笔解释&#xff1a; i&#xff0c;示例1 ii&#xff0c;示例2 iii&#xff0c;二分查找 iv&#xff0c;斐波那契 &#xff08;三&#xff09;空间复杂度…