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.hqwc.cn/news/286207.html

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

相关文章

css3实现类似地图定位循环扩散光圈效果

1.效果图,重点opacity,animation,transform:scale 2.html <div class"icon-warnCom"><icon class"icon-warns"><i class"dot"></i><i class"pulse"></i></icon></div><div class…

客观题测试-第8章排序

第1关&#xff1a;排序客观题测试&#xff08;一&#xff09; 1、内排序要求待排序列一定要用顺序方式存储。 A、对 B、错 2、稳定的排序算法优于不稳定的排序算法&#xff0c;因为稳定的排序方法效率高。 A、对 B、错 3、对5个互异的整数进行排序&#xff0c;至少需要1…

基于JAVA+SpringBoot的线上智能问诊就医平台

✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取项目下载方式&#x1f345; 一、项目背景介绍&#xff1a; 智慧医药系统&#xf…

Leetcode: 203. 移除链表元素

题目 给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删除链表中所有满足 Node.val val 的节点&#xff0c;并返回 新的头节点 。 难度&#xff1a;简单 题目链接&#xff1a;203. 移除链表元素 示例 1&#xff1a; 输入&#xff1a;head [1,2,6,3,4,5,6], val …

亚信安慧AntDB 数据库:超融合数据库引领实时计算新时代

近期&#xff0c;亚信科技成功举办了以“数智驱动 全栈赋能”为主题的2022年度系列产品发布会的“数据库专场”。在这次发布会上&#xff0c;亚信科技发布了AntDB V7.2数据库&#xff0c;这是一款“超融合一体流式引擎”的重要产品&#xff0c;并分享了在通信、交通等行业中的应…

056:vue工具 --- CSS在线格式化

第056个 查看专栏目录: VUE ------ element UI 专栏目标 在vue和element UI联合技术栈的操控下&#xff0c;本专栏提供行之有效的源代码示例和信息点介绍&#xff0c;做到灵活运用。 &#xff08;1&#xff09;提供vue2的一些基本操作&#xff1a;安装、引用&#xff0c;模板使…

密码明文传输漏洞 原理以及修复方法

漏洞名称 : 密码明文传输 漏洞描述 : 密码明文传输一般存在于web网站登录页面&#xff0c;用户名或者密码采用了明文传输&#xff0c;容易 被嗅探软件截取。 检测条件 &#xff1a;1、 已知Web网站具有登录页面。 检测方法&#xff1a; 1、 找到网站或者web系统登录页面。…

VR党建:VR全景技术如何助力党建知识传播

导语&#xff1a; 随着科技的不断发展&#xff0c;虚拟现实技术逐渐深入人们生活的方方面面。VR全景技术作为一种全新的沉浸式体验方式&#xff0c;被广泛应用于娱乐、教育、医疗等领域。而在党建学习中&#xff0c;VR全景技术也展现出了巨大的潜力&#xff0c;成为了一种创新…

[学习笔记]批量迁移数据库文件

拷贝数据库文件 首先在本地运行如下SQL语句&#xff0c;查看数据库文件的磁盘位置 SELECT name, physical_name AS CurrentLocation, state_desc FROM sys.master_files默认是保存在C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\DATA目录下 首先复制数据…

青藤销售云助力企业数智化销售

青藤销售云助力企业数智化销售覆盖&#xff1a; 1.人工自动外呼群呼 2.AI电销销售机器人自动筛选意向客户 3.crm企业微信智能客户管理运行系统 4.电话回拨系统不限拨打频次高频外呼不封号 5.语音通知系统覆盖工单提醒、发货提醒、缴费提醒等场景 6.手机号外显专号专用高接通率线…

GO 的 socks5代理 编写

这里学习一下 socks5 代理的编写 网上有很多 学习一下 go 语言实战入门案例之实现Socks5 - 知乎 滑动验证页面 socks5协议原理学习-腾讯云开发者社区-腾讯云 (tencent.com) 首先我们要了解一下socks5的代理方式 socks5 是基于 认证建立连接转发数据 所形成的代理 我们只…

ehr是什么意思?ehr系统主要干什么的

随着科技的发展&#xff0c;企业管理方式也在不断变革。其中&#xff0c;ehr系统作为一种新兴的人力资源管理工具&#xff0c;受到了越来越多企业的关注。那么&#xff0c;ehr到底是什么意思&#xff1f;它是干什么的&#xff1f;主要能解决哪些企业痛点呢&#xff1f;接下来&a…