linux系统和网络(一):文件IO

        本文主要探讨linux系统编程的文件IO相关知识。

文件IO
        文件存在块设备中为静态文件,open打开文件,内核在进程中建立打开文件的数据结构在内存中用于记录文件的文件参数,开辟一段内存用于存放内容,将静态文件转为动态文件
        打开文件后对文件的读写操作都为对动态文件操作,close关闭文件时内核将内存中的动态文件同步到块设备中的静态文件

文件描述符
        文件描述符是数字,打开文件时,系统在内存中构建数据结构来表示动态文件并返回数字作为文件描述符,该数字和动态文件数据结构挂钩绑定,API对描述符操作可实现对文件操作
        文件描述符用于区分程序打开多个文件

open的flag
        同时使用O_TRUNC和O_APPEND,O_TRUNC的优先级高
        O_CREAT创建不存在文件,文件存在,创建这个文件,原来内容清除
        O_EXCL和O_CREAT结合使用,文件不存在创建文件,文件存在报错
        O_NONBLOCK非阻塞模式,文件打开默认是阻塞
        O_SYNC:write阻塞等待底层完成写入才返回到应用层,无O_SYNC时write将内容写入底层缓冲区即可返回,底层适时将buf中内容同步硬盘,使用O_SYNC,内容直接写入硬盘

errno和perror
        linux系统对错误做了编号,函数执行错误时,函数返回errno编号
        errno是由OS的全局变量,用于给上层调用反馈错误
        perror函数读取errno并将errno数字转为对应的错误信息打印

标准IO和系统IO
        API的read和write的count参数表示想要写或读入字节数,返回值表示实际写或读取字节数
        标准IO函数是由文件IO封装而来,标准IO加了应用层缓冲机制,写入内容不直接写入内核buf,先写入应用层标准IObuf中,标准IO库根据操作系统单次最佳count写入内核buf,内核将内核buf数据写入硬盘
        ffulsh(int fflush(FILE *stream);)将IO buf中的数据同步到内核buf,无需等待
        API在不同操作系统间不能通用,C库函数函数可以,可移植性强
        文件IO不带缓存,标准IO带缓存的,标准IO性能高

linux系统管理文件
        硬盘分为两区域:内容管理表项(文件名,扇区号,块号...(inode节点,结构体))和内容
        快速格式化是删除硬盘内容管理表(inode),内容还在

        vnode:程序运行后是进程,程序中打开的文件就该进程,进都有数据结构记录进程所有信息(进程信息表),进程信息表包含文件管理表(文件管理结构体vnode)包含fd和其他文件相关信息

        空洞文件:文件有一段是空的,write时lseek跳过一段,再write会构成空洞文件
多线程通过文件指针的不同位置,同时对同一文件写入

文件描述符解析
        重复打开同一文件,多个fd数值不同且有各自的文件指针,但表示同一文件,用这些fd同时对文件写入,后一个写入会覆盖前一个,加O_APPEND可解决覆盖
        文件描述符是数字,是进程表中文件描述符表的一个表项,描述符作为index去索引查表得到文件表指针,再间接访问文件对应的文件表
        文件描述符是open系统调用时由操作系统自动分配,fd从0开始依次增加,分配最小的未被占用的描述符,文件描述符表是数组,fd是index,文件表指针是value
        linux内核占用0、1、2(stdin、stdout、stderr)描述符


文件描述符复制(dup,dup2,fcntl)

int dup(int oldfd);
int dup2(int oldfd, int newfd);
int fcntl(int fd, int cmd, ... /* arg */ );

        dup复制后得到的fd由操作系统内部分配,dup2可指定描述符
        close(1)关闭标准输出,该程序不显示输出内容,使用dup重新分配1为fd(open一个文件)就把fd和1绑定,则该程序的输出重定位到该文件
        dup和dup2通过复制fd同时写入同一文件是接续写入内容,不会覆盖
        cmd为F_DUPFD作用是复制文件描述符(dup和dup2),从fd列表中找(>=arg的最小数)

文件类型
        -:普通文件:文件内容本质上是数字(1,0),不同的解析方式将文件解析为文本文件,二进制文件等,使用不对应的解析器解析文件会乱码
        d:目录文件是特殊文件,内容:文件的路径,文件列表和其他(vim查看)
        c:字符设备文件,b:块设备文件,设备文件对应硬件设备,存在文于件系统中,不存在于硬盘上(/dev,/sys,/proc等)
        p:管道文件,s套接字文件,l:符号链接文件

文件属性

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


        stat(linux)命令查看文件属性,调用stat API实现的,内核将文件属性信息结构体值存放在stat函数buf中并打印
        stat从文件名得到文件属性信息结构体,fstat是文件fd得到文件属性信息,文件已打则fstat效率高,stat从磁盘读取文件,fstat从内存读取动态文件
        lstat和stat/fstat:stat和fstat获得符号链接文件指向的文件属性,lstat获得符号链接文件本身的属性
        struct stat是内核定义的结构体,在<sys/stat.h>中声明

struct stat  
{   dev_t       st_dev;     /* ID of device containing file -文件所在设备的ID*/  ino_t       st_ino;     /* inode number -inode节点号*/    mode_t      st_mode;    /* protection -保护模式?*/    nlink_t     st_nlink;   /* number of hard links -链向此文件的连接数(硬连接)*/    uid_t       st_uid;     /* user ID of owner -user id*/    gid_t       st_gid;     /* group ID of owner - group id*/    dev_t       st_rdev;    /* device ID (if special file) -设备号,针对设备文件*/    off_t       st_size;    /* total size, in bytes -文件大小,字节为单位*/    blksize_t   st_blksize; /* blocksize for filesystem I/O -系统块的大小*/    blkcnt_t    st_blocks;  /* number of blocks allocated -文件所占块数*/    time_t      st_atime;   /* time of last access -最近存取时间*/    time_t      st_mtime;   /* time of last modification -最近修改时间*/    time_t      st_ctime;   /* time of last status change - */    
};  

        st_mode按位标志文件权限,S_ISREG宏返回1表示普通文件,不是普通文件返回是0

S_ISREG(m)  is it a regular file?
S_ISDIR(m)  directory?
S_ISCHR(m)  character device?
S_ISBLK(m)  block device?
S_ISFIFO(m) FIFO (named pipe)?
S_ISLNK(m)  symbolic link?  (Not in POSIX.1-1996.)
S_ISSOCK(m) socket?  (Not in POSIX.1-1996.)

        位掩码来判断文件类型,st_mode & S_IFMT 等于文件类型的hex,通过文件类型的hex判断文件类型
        位掩码来判断文件权限,st_mode & name   等于文件权限的hex,通过文件类型的hex判断文件权限
        位掩码来判断文件id,st_mode & S_ISUID(S_ISGID) 获得文件的id

hex    name       ls   octal    description
f000   S_IFMT          170000   文件类型掩码
1000   S_IFIFO    p    010000   字符设备文件
2000   S_IFCHR    c    020000   字符设备文件
4000   S_IFDIR    d    040000   文件目录
6000   S_IFBLK    b    060000   块设备文件
8000   S_IFREG    -    100000   普通文件
a000   S_IFLNK    l    120000   链接文件
c000   S_IFSOCK   s    140000   套接字文件S_ISUID         0004000   用户idS_ISGID         0002000   用户组id
1c0    S_IRWXU         00700     用户权限掩码
100    S_IRUSR         00400     用户读权限
80     S_IWUSR         00200     用户写权限
40     S_IXUSR         00100     用户执行权限
38     S_IRWXG         00070     用户组权限掩码
20     S_IRGRP         00040     用户组读权限
10     S_IWGRP         00020     用户组写权限
08     S_IXGRP         00010     用户组执行限
07     S_IRWXO         00007     其他用户掩码
04     S_IROTH         00004     其他用户读权限
02     S_IWOTH         00002     其他用户写权限
01     S_IXOTH         00001     其他用户执行权限

        access判断文件权限,文件主组其他都不存在该权限时,返回-1,有一个存在则返回0

int access(const char *pathname, int mode);#define R_OK 4 /* 读权限*/
#define W_OK 2 /* 写权限*/
#define X_OK 1 /* 执行权限*/
#define F_OK 0 /* 文件存在*/

        修改文件权限chmod/fchmod

int chmod(const char *path, mode_t mode);
int fchmod(int fd, mode_t mode);
同linux(1,2,4.如0777)
S_ISUID  (04000)  set-user-ID 
S_ISGID  (02000)  set-group-ID 
S_ISVTX  (01000)  sticky bit 
S_IRUSR  (00400)  read by owner
S_IWUSR  (00200)  write by owner
S_IXUSR  (00100)  execute/search  by  owner  
S_IRGRP  (00040)  read by group
S_IWGRP  (00020)  write by group
S_IXGRP  (00010)  execute/search by group
S_IROTH  (00004)  read by others
S_IWOTH  (00002)  write by others
S_IXOTH  (00001)  execute/search by others

        修改文件属主chown/fchown/lchown

int chown(const char *path, uid_t owner, gid_t group);
int fchown(int fd, uid_t owner, gid_t group);
int lchown(const char *path, uid_t owner, gid_t group);

        umask
        设置创建的文件掩码,即设置创建的文件权限的补码,不论权限大小,都无执行权限

mode_t umask(mode_t mask);

        目录文件
        opendir打开目录得到DIR类型指针,readdir函数调用DIR类型指针返回struct dirent类型指针

DIR *opendir(const char *name);
DIR *fdopendir(int fd);
struct dirent * readdir(DIR * dir);
struct dirent {ino_t          d_ino;       /* inode number 文件inode节点号*/off_t          d_off;       /* not an offset; 文件相对首文件偏移量*/unsigned short d_reclen;    /* length of this record 文件长度(大小)*/unsigned char  d_type;      /* type of file; 文件类型*/                              char           d_name[256]; /* filename 文件名*/};

demo1:

        文件续写和覆盖(fd,dup,dup2,fcntl)

覆盖:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>int main()
{int num = 0;int fd_1 = open("test_1",O_RDWR);if(fd_1 < 0){perror("open");exit(-1);}int fd_2 = open("test_1",O_RDWR);if(fd_2 < 0){perror("open");exit(-1);}while(1){if(num >=6){break;}write(fd_1,"ab",2);write(fd_2,"cd",2);num++;}close(fd_1);close(fd_2);return 0;
}

结果显示:

 续写: 

        fd/dup/dup2/fcntl 

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>int main()
{int num = 0;int fd_1 = open("test_1",O_RDWR|O_APPEND);if(fd_1 < 0){perror("open");exit(-1);}int fd_2 = open("test_1",O_RDWR|O_APPEND);if(fd_2 < 0){perror("open");exit(-1);}//int fd_2 = dup(fd_1);//int fd_2 = dup2(fd_1,10);//int fd_2 = fcntl(fd_1,F_DUPFD,10);while(1){if(num >=6){break;}write(fd_1,"ab",2);write(fd_2,"cd",2);num++;}close(fd_1);close(fd_2);return 0;
}

结果显示:

 demo2:

         stat函数获取stat命令的结果

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>char buf[32] = {0};void get_time(unsigned long file_time)
{memset(buf,0,32);time_t time_f = file_time;time(&time_f);struct tm* timeinfo = localtime(&time_f);strcpy(buf,asctime(timeinfo));
}int main()
{int ret = -1;struct stat file;memset(&file, 0, sizeof(struct stat));stat("test_1",&file);printf("dev : %d\n",file.st_dev);printf("inode : %d\n",file.st_ino);printf("nlink : %ld\n",file.st_nlink);printf("uid : %ld\n",file.st_uid);printf("gid : %ld\n",file.st_gid);printf("rdev : %ld\n",file.st_rdev);printf("blksize : %ld\n",file.st_blksize);printf("size : %ld\n",file.st_size);printf("blocks : %ld\n",file.st_blocks);get_time(file.st_atime);printf("atime :%s",buf);get_time(file.st_mtime);printf("mtime :%s",buf);get_time(file.st_ctime);printf("ctime :%s",buf);ret = file.st_mode & S_IFREG;if (ret == 0x8000)printf("type : -\n");ret = file.st_mode & S_IRWXU;if(ret == 0x1c0)printf("u:rwx\n");ret = file.st_mode & S_IRWXG;if(ret == 0x38)printf("g:rwx\n");ret = file.st_mode & S_IRWXO;if(ret == 0x07)printf("o:rwx\n");return 0;}

demo3: 

        获取文件权限,修改文件权限,修改文件属主属组,修改文件掩码

        注意:

                文件的执行权限不能通过文件掩码来设置,需要用chmod,掩码能设置的最大权限为0666

                 umask函数设置的权限,仅仅只在程序运行中成立,程序结束以当前操作系统设置的掩码为准

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>int main()
{int ret = -1;if(access("test_1",F_OK) == 0)printf("test exited\n");if(access("test_1",R_OK)  == 0)printf("read premisson\n");if(access("test_1",W_OK) == 0)printf("write premisson\n");if(access("test_1",X_OK)  == 0)printf("operaton premisson\n");chmod("test_1",0777);chown("test_1",1000,1000);umask(0222);system("touch file");return 0;}

结果示例:

demo4:

         显示文件夹中文件的名称,大小,类型,inode,offsset

#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <stdlib.h>int main()
{DIR * dir;struct dirent * ptr;char type;dir = opendir("tmp");if(dir == NULL){perror("opendir");exit(-1);}printf("type\tinode\toffset\t\t\tname_len\tname\n");while((ptr = readdir(dir)) != NULL){if(ptr->d_type == 8){type = '-';}else if(ptr->d_type == 4){type = 'd';}else{printf("have no type file\n");}printf("%c\t%ld\t%ld\t%d\t\t%s\n",type,ptr->d_ino,ptr->d_off,ptr->d_reclen,ptr->d_name);}closedir(dir);return 0;
}

结果示例:

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

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

相关文章

【最新版】在WSL上运行 Linux GUI (图形用户界面)应用(Gnome 文本编辑器、GIMP、Nautilus、VLC、X11 应用)

文章目录 一、 安装WSL0. 先决条件1. 全新安装2. 现有 WSL 安装3. 注意事项 二、运行 Linux GUI 应用1. 更新发行版中的包2. 安装 Gnome 文本编辑器启动 3. 安装 GIMP启动 4. 安装 Nautilus启动 5. 安装 VLC启动 6. 安装 X11 应用 适用于 Linux 的 Windows 子系统 (WSL) 现在支…

MATLAB求解微积分(代码+详细解读)

大多数实际工程问题常常简化为微分方程&#xff0c;其求解显地至关重要。 符号微积分 极限 % matlab提供的求极限函数limit(),其调用格式为 % y limit(fun,x,x0) % fun为要求解的函数&#xff0c;x为函数自变量&#xff0c;x0为函数自变量的取值&#xff0c;x趋近于x0 clc;…

windows环境下cmd找不到pip

报错信息&#xff1a;pip : 无法将“pip”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写&#xff0c;如果包括路径&#xff0c;请确保路径正确&#xff0c;然后再试一次。 所在位置 行:1 字符: 1 pip ~~~ CategoryInfo : ObjectNotFou…

Linux-----13、用户、组

# 用户、组 # 一、用户管理 # ㈠ 用户概念及作用(了解) **用户&#xff1a;**指的是Linux操作系统中用于管理系统或者服务的人 一问&#xff1a;管理系统到底在管理什么&#xff1f; 答&#xff1a;Linux下一切皆文件&#xff0c;所以用户管理的是相应的文件 二问&#x…

【UML】第6篇 用例图

目录 一、什么是用例图 二、参与者 2.1 什么是参与者 2.2 如何识别参与者 2.3 参与者之间的关系 从今天开始&#xff0c;就到了最干的各种的图的梳理和学习了&#xff0c;未来AI就能编码了&#xff0c;把业务建模和设计的基本功打好&#xff0c;也许能和AI和平相处呢。 一…

UART协议——FPGA代码篇

一.串口&#xff08;UART&#xff09;协议简介 UART 串口通信有几个重要的参数&#xff0c;分别是波特率、起始位、数据位、停止位和奇偶检验位&#xff0c;对于两个使用UART 串口通信的端口&#xff0c;这些参数必须匹配&#xff0c;否则通 起始位&#xff1a;表示数据传输的开…

科技云报道:至简至强,新一代服务器的算力美学

科技云报道原创。 在这个时代&#xff0c;数据和计算的边界正在迅速扩张。 随着云计算、物联网和人工智能的日益成熟&#xff0c;对算力的需求已经突破了传统的限制&#xff0c;进入了一个全新的阶段。在这个阶段&#xff0c;不仅是算力的量级发生了变化&#xff0c;其性质和…

2-以太坊虚拟机

以太坊虚拟机&#xff0c;简称EVM&#xff0c;是用来执行以太坊上的交易的。业务流程如下图&#xff1a; 输入一笔交易&#xff0c;内部会转换成一个Message对象&#xff0c;传入EVM执行。 如果是一笔普通转账交易&#xff0c;那么直接修改StateDB中对应的账户余额即可。如果…

数据结构:树(Tree)

树型结构 树的概念 树是一种非线性结构&#xff0c;他是由n&#xff08;n>0&#xff09;个有限结点组成的一个具有层次关系的集合。 当n0时&#xff0c;该树为空树。 在任意一个非空树中都满足以下条件&#xff1a; 1、有一个特殊的结点&#xff0c;称为根结点&#xff0c…

GaussDB数据库表创建行访问控制策略

目录 一、前言 二、GaussDB中的行访问控制 1、CREATE ROW LEVEL SECURITY POLICY语法 2、ALTER ROW LEVEL SECURITY POLICY语法 3、ROW LEVEL SECURITY策略与适配SQL语法关系 三、GaussDB中的行访问控制策略示例 1、实现GaussDB行访问控制的一般步骤 2、行访问控制策略…

关于#c语言#的问题:分析递归调用的过程◇画出调用过程各语句执行过程

关于#c语言#的问题&#xff1a;分析递归调用的过程◇画出调用过程各语句执行过程 当涉及到递归调用的过程时&#xff0c;可以通过绘制函数调用栈来分析和理解递归的执行过程。下面是一个示例的C语言递归函数和相应的调用过程&#xff1a; #include <stdio.h>void recurs…

详解 Jeecg-boot 框架如何配置 elasticsearch

目录 一、下载安装 Elasticsearch 1、 地址&#xff1a;https://www.elastic.co/cn/downloads/elasticsearch 2、下载完成后&#xff0c;解压缩&#xff0c;进入config目录更改配置文件 3、 修改配置完成后&#xff0c;前往bin目录启动el 4、访问&#xff1a;localhost:92…

【Stm32-F407】全速DAP仿真器下载程序

文章内容如下: 1) 全速DAP仿真器简介2) 全速DAP仿真器下载程序流程 1) 全速DAP仿真器简介 1&#xff09;全速DAP仿真器简介 DAP全称 Data Acquisition Processor&#xff0c;是一种用于数据采集和实时控制的设备。本文使用的全速DAP仿真器遵循ARM公司的CMSIS-DAP标准&#xff…

采购oled屏幕,应注意什么

在采购OLED屏幕时&#xff0c;应注意以下几点&#xff1a; 规格和参数&#xff1a;了解OLED屏幕的规格和参数&#xff0c;包括尺寸、分辨率、亮度、对比度、响应时间等。确保所采购的屏幕符合项目的需求和预期效果。 品质和可靠性&#xff1a;选择具有可靠品质和稳定性的OLED屏…

Docker单点部署[8.11.3] Elasticsearch + Kibana + ik分词器

文章目录 一、Elasticsearch二、Kibana三、访问四、其他五、ik分词器第一种&#xff1a;在线安装第二种&#xff1a;离线安装 Elasticsearch 和 Kibana 版本一般需要保持一致才能一起使用&#xff0c;但是从 8.x.x开始&#xff0c;安全验证不断加强&#xff0c;甚至8.x.x之间…

geemap学习笔记029:使用Earth Engine数据--几何(Geometry)数据

前言 从本节开始将会分类别的进行学习&#xff0c;例如使用Earth Engine数据、使用本地地理数据、可视化地理数据、分析地理数据等&#xff0c;当然前面介绍过的&#xff0c;就不再赘述。 1 导入库并显示地图 import ee import geemapee.Initialize()2 创建几何对象-1 Map …

电子商务网站知识|搭建自己的电子商务网站需要注意什么|搭建电商独立站的注意事项

电子商务网站建设步骤包括什么呢? 电子商务网站建设第一步&#xff0c;网站的规划与设计 电子商务网站算是一个比较复杂的系统&#xff0c;电商网站建设前就要想好需要有的功能。电子商务网站的规划也是建所有网站都需要做的事情&#xff0c;在规划设计中需要对网站进行整体…

【计算机网络】TCP协议——1.报文格式详解

前言 上篇讲解了UDP报文格式。TCP和UDP是同层协议&#xff0c;都属于传输层&#xff0c;数据来源于上层——应用层 目录 一. TCP协议概述 二. TCP报文格式 1. 两个问题 2. 确认号和序列号 3. 标志位字段 4. 窗口大小 5. 校验和字段 6. 紧急指针与紧急数据 7. 选项字…

【uniapp小程序-上拉加载】

在需要上拉加载的页面的page.json上添加红框框里面的 onReachBottom() {if(this.commentCurrent<this.commentTotal){this.commentCurrent 1; this.commentList();this.status loading;}else{this.status ;} }, methods:{commentList(){let params {courseid:this.cour…

QUIC在零信任解决方案的落地实践

一 前言 ZTNA为以“网络为中心”的传统企业体系架构向以“身份为中心”的新型企业安全体系架构转变&#xff0c;提供解决方案。随着传统网络边界不断弱化&#xff0c;企业SaaS规模化日益增多&#xff0c;给终端安全访问接入创造了多元化的空间。其中BYOD办公方式尤为突出&#…