File*其实是一个结构体

  • 文件描述符FD:索引到对应的磁盘文件
  • 文件读写位置指针FP_POS,如果同时读写需要注意文件指针的位置
  • I/O缓冲区BUFFER:保存内存指针,默认大小是8kb,用于减小我们对硬盘操作的次数。因为我们对硬盘的操作是ms级别的,而我们电子设备的操作是ns级别的。
  • 刷新缓冲区到硬盘上:fflush、缓冲区已满、文件正常关闭、return main、exit main
  • Linux系统函数没有缓冲区,C库函数自带缓存

在Linux中,inode保存文件的属性,里面有一个结构体struct stat,其中记录了文件的各种信息,但是没有保存文件名。
文件名保存在denty(目录项)中,每一个文件名对应一个inode编号。每一个硬链接都是一个denty

以Linux32为系统为例:

  • 文件描述符:

    • Linux为每一个运行的程序分配0-4G的内存
    • 0-3G是用户区,3-4G是内核区,内核区不允许用户去访问
    • 文件描述符位于内核区中的PCB进程控制块中,0-1023,每个位置储存一个文件。0\1\2默认是打开的,分别是STDIN_FiLENO 、STDOUT_FILENO 、STDERR_FILENO,每打开一个新文件,会多储存一个文件描述符。是一个栈

查看文件格式:file 文件

虚拟地址

用户区:0-3G

  • 受保护的内存(0-4K)none指针指向这个位置
  • ELF段
    • .text 代码段,二进制机器指令,包含main函数、静态库
    • .rodata段 和.text一样都是ro(只读)权限,在链接的时候完成数据段合并
    • .data段 已经初始化的全局变量
    • .bss未初始化的全局变量,和.data段一样是rw(读写)权限
  • 堆空间:保存全局变量,用malloc或者new在堆上分配内存
  • 共享库: 动态库,对库的调用是相对的地址。
  • 栈空间:从上面开始分配内存,保存局部变量
  • 命令行参数:main函数的参数
  • 环境变量:env查看

CPU使用虚拟地址与物理空间映射的作用:

  • 方便编译器和操作系统安排程序的地址分布:程序可以使用一系列连续的虚拟地址访问内存中不连续的内存缓冲区
  • 方便进程之间的隔离:不同进程之间彼此隔离,一个进程中的代码无法更改正在另一项进程的物理内存
  • 方便OS使用内存:程序可以使用一系列虚拟地址来访问大于可用物理内存的内存缓冲区。当物理内存的供应量变小时,内存管理器会将物理内存页(通常为4KB)保存到此案文件。数据或代码页会根据需要在物理内存和磁盘之间移动

printf函数

printf函数
调用write函数将文件描述符传递
应用层运行write函数
系统调用sys_write()函数,从用户态转化为内核态
内核层设备驱动函数

常用的系统应用函数

man 章节号 需要查找的函数 // 查看Linux手册中的函数

open函数

int open(const char *pathname, int flags);// The argument flags must include one of the following access modes: O_RDONLY, O_WRONLY,  or O_RDWR.  These request opening the file read-only, write-only,or read/write, respectively.int open(const char *pathname, int flags, mode_t mode);
//mode:给创建文件设定访问权限

返回一个文件描述符,-1意思是发生了错误,errno会被赋予错误信息,使用需要包含errno.h

错误宏定义的位置:
第1-34个错误:usr/incclude/asm-generic/errno-base.h
第35-133个错误:/usr/include/asm-generic/errno.h

void perror(const char *s)用来将上一个函数发生错与原因输出到标准设备

编写函数的时候可以使用章节+ shift+k查看函数的man文档

例如:

#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h> //open的头文件
#include<unistd.h>    //close的头文件
#include<stdlib.h>    //exit的头文件
#include<stdio.h> //perror的头文件
int main()
{int fd;    //用于保存文件描述符fd = open("main.c",O_RDWR);if(fd==-1){perror("open file");exit(1);}//创建新文件fd = open("newfile.c",O_RDWR | O_CREAT,777);//实际上文件的属性是775,因为本地有一个掩码,给定的权限将会和掩码有一个取反按位与的操作,实际上相当于减法//nmask获取本地掩码printf("新文件的文件描述符:%d\n",fd);//关闭文件int ret = close(fd);if(ret==-1){perror("close file");exit(1);}elseprintf("ret=%d\n",ret);return 0;
}

获取本地掩码:umask
修改本地掩码:umask xxxx
O_CREAT需要将掩码取反再将权限按位与

通过O_CREAT 与O_EXCL和起来使用判断文件是否已经存在,例如:

#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h> //open的头文件
#include<unistd.h>    //close的头文件
#include<stdlib.h>    //exit的头文件
#include<stdio.h> //perror的头文件
int main()
{int fd;    //用于保存文件描述符
/*fd = open("main.c",O_RDWR);if(fd==-1){perror("open file");exit(1);}//创建新文件fd = open("newfile.c",O_RDWR | O_CREAT,777);//实际上文件的属性是775,因为本地有一个掩码,给定的权限将会和掩码有一个取反按位与的操作,实际上相当于减法//nmask获取本地掩码printf("新文件的文件描述符:%d\n",fd);
*/fd = open("myhelloc.c",O_RDWR|O_CREAT|O_EXCL , 777);if(fd==-1){perror("open file");exit(1);}
//关闭文件int ret = close(fd);if(ret==-1){perror("close file");exit(1);}elseprintf("ret=%d\n",ret);return 0;
}

文件清空、截断为0O_TRUNC

一定要注意对返回值做一个判断,这样出错的时候就能知道哪里出错。

read()

 #include <unistd.h>ssize_t read(int fd, void *buf, size_t count);

返回值:

  • -1 读文件失败,设置errno
  • 0文件读取了
  • x 读取了x个字符

write()

#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);

lseek()

#include <sys/types.h>#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
whence as follows:SEEK_SETThe file offset is set to offset bytes.SEEK_CURThe file offset is set to its current location plus offset bytes.SEEK_ENDThe file offset is set to the size of the file plus offset bytes.

使用举例:将一个文件的内容拷贝到另一个文件

#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h> //Open
#include<unistd.h>    //Close
#include<stdlib.h>    //exit
#include<stdio.h> //perror
#include<string.h>
#define MAXN 1005
char buffer[MAXN];  //缓冲区
int fd_in,fd_out;   //用于保存文件描述符void Open()
{fd_in=open("file_in",O_RDONLY);if(fd_in == -1){perror("Open fin:");exit(1);}//fd_out=open("file_out",O_WRONLY | O_CREAT | O_EXCL,0777);fd_out=open("file_out",O_WRONLY | O_CREAT,0644);if(fd_out == -1){perror("Open fout:");exit(1);}
}void Close()
{int ret=close(fd_in);if(ret==-1){perror("Close fin");exit(1);}if(ret==-1){perror("Close fout");exit(1);}
}void Work()
{int cnt=read(fd_in,buffer,MAXN);if(-1==cnt){printf("读取文件失败");}while(cnt)  //没有读取到文件末尾{write(fd_out,buffer,cnt);cnt=read(fd_in,buffer,MAXN);}
}
int main()
{Open();Work();Close();
}

经验:

  • open函数如果使用O_CREAT参数,则需要指定使用权限(八进制数字,需要在权限前面加0),如果只使用O_CREATO_RDWR参数配合,如果文件已经存在就会打开之前的文件,不会创建新文件,如果再配合O_EXCL参数,那么如果已经存在文件就会报错。
  • 文件的实际权限是指定权限减去掩码
  • 不要眼高手低,即使看起来比较简单的东西还是需要多动手实践,才能发现自己的问题

lseek

 #include <sys/types.h>#include <unistd.h>off_t lseek(int fd, off_t offset, int whence);
lseek()  repositions the file offset of the open file description associated
with the file descriptor fd to the argument offset according to  the  direc‐
tive whence as follows:SEEK_SETThe file offset is set to offset bytes.SEEK_CURThe file offset is set to its current location plus offset bytes.SEEK_ENDThe file offset is set to the size of the file plus offset bytes.
  • 获取文件长度ret=lseek(fd,0,SEEK_END)
  • 文件拓展:只能向后拓展文件,不能向前
int ret=lseek(fd,2000,SEEK_END);
//文件拓展需要最后做一次写操作,随便写一点东西就可以
//得到一个空洞文件,先得到预定大小的文件然后使用多线程操作
write(fd,"a",1);

Linux命令【四】文件+虚拟内存+常用系统函数相关推荐

  1. linux常用命令(2)常用系统工作命令

    linux常用命令(2)常用系统工作命令 echo命令 作用:在终端输出字符串或变量提取后的值 格式:echo[字符串|$变量] 示例: [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直 ...

  2. linux系统编程笔记02——Linux命令:修改文件权限命令chmod、chgrp、chown详解

    Linux命令:修改文件权限命令chmod.chgrp.chown详解 Linux系统中的每个文件和目录都有访问许可权限,用它来确定谁可以通过何种方式对文件和目录进行访问和操作. 文件或目录的访问权限 ...

  3. python123测试3平方根格式化_Python3常用系统函数帅哥定制版

    Python3常用系统函数JSON帅哥定制版 没错,这里的帅哥指的就是我自己 安装 安装pip3 wget --no-check-certificate https://pypi.python.org ...

  4. Python3常用系统函数帅哥定制版

    Python3常用系统函数JSON帅哥定制版 没错,这里的帅哥指的就是我自己 安装 安装pip3 wget --no-check-certificate https://pypi.python.org ...

  5. PHP常用系统函数帅哥特供版

    [TOC] PHP常用系统函数帅哥特供版 常用操作 定界符 <<<EOF内容EOF; 1.PHP定界符的作用就是按照原样,包括换行格式什么的,输出在其内部的东西: 2.在PHP定界符 ...

  6. C语言字符串、文件操作常用操作函数,

    C语言字符串常用操作函数 C语言字符串.文件操作常用操作函数 字符串输出 - puts() 字符串输入 - gets() 字符串比较 - strcmp() 字符串复制 - strcpy() 字符串连接 ...

  7. Linux命令:文件和目录操作

    Linux命令:文件和目录操作 >文件是Linux用来存储信息的基本结构, 它是被命名(称为文件名)的存储在某种介质(如磁盘.光盘.磁带等)上的一组信息的集合. >Linux系统文件以文件 ...

  8. c语言有哪些系统函数,C语言常用系统函数.doc

    C语言常用系统函数.doc 下载提示(请认真阅读)1.请仔细阅读文档,确保文档完整性,对于不预览.不比对内容而直接下载带来的问题本站不予受理. 2.下载的文档,不会出现我们的网址水印. 3.该文档所得 ...

  9. Linux删掉一级目录,linux命令删除文件夹

    本文收集整理关于linux命令删除文件夹的相关议题,使用内容导航快速到达. 内容导航: Q1:linux shell 删除文件夹命令 iftestx"$1"=x"-f&q ...

最新文章

  1. 干货 | 如何使用 CNN 推理机在 IoT 设备上实现深度学习
  2. 从3D人脸到自动驾驶,CVPR2020十个顶级开源数据集
  3. 怎么看调用的接口_Hadoop RPC调用实例分析
  4. 跟老齐学python Django实战第一章错误解决
  5. Disconf 学习系列之全网最详细的最新稳定Disconf 搭建部署(基于Windows7 / 8 / 10)(图文详解)...
  6. android基础入门思考题答案,《Android移动应用基础教程》中国铁道出版社课后习题(附答案)...
  7. infomixdb mysql_不同数据库oracle mysql SQL Server DB2 infomix sybase分页查询语句
  8. 常用方法 保证数据长度相同
  9. Uncaught ReferenceError: jie is not defined
  10. MySQL学习笔记( 整理中)
  11. php shuffle有种子吗6,6个BT种子网站,没有它找不到的资源!太少人知道了怪可惜的...
  12. Matlab 线性拟合 非线性拟合
  13. SQL server 数据库查询语句的基本实现
  14. 【PowerDesigner】【5】数据模型 CDM
  15. 【华为OD机试真题 C++】数字涂色 【2022 Q4 | 100分】
  16. 仿微信朋友圈,文字展开全文,全文收起功能
  17. C语言编程题:输入多个字符串,输出其中最短的字符串。
  18. 走进如心小镇,数智化变革连接“未来社区”
  19. SparkSql MAPJOIN优化之小表left join大表
  20. 小猫写给DOTA英雄们的情之赞歌

热门文章

  1. ORM框架greenDao 2 (用于了解旧版本的使用方法,目前最新版本为3.2.2,使用注释的方式来生成)...
  2. MySQL的复制:MySQL系列之十三
  3. 关于源码,反码,补码(正数--负数)---------(-128)自己的理解
  4. Mathematica图片局部变色
  5. MyEclipse 6.5安装maven插件
  6. 解决SimpleButton被移除后保持OVER状态
  7. Bdsyn百度手机助手是何物,它是怎样神不知鬼不觉地安装到你的电脑里的?
  8. 手机调用系统的拍照和裁剪功能,假设界面有输入框EditText,在一些手机会出现点击EditText会弹出输入法,却不能输入的情况。...
  9. jquery ajax.then,jQuery动态AJAX Promise链
  10. 亚信联创java面试题_亚信联创面试题及答案