linux应用编程之文件属性
文章目录
- 前言
- 1.linux中各种文件类型
- 2.常用文件属性获取
- 4.文件权限管理
- 5.读取目录文件
前言
本文是对朱有鹏相关课程的归纳总结。下面是linux应用编程整理的文章。
linux应用编程基础:
1.文件IO
2.文件属性
3.获取系统信息
4.linux进程
5.linux中的信号
6.高级IO
7.linux线程
8.网络基础
1.linux中各种文件类型
1.1、普通文件(- regular file)
(1)我们如何知道一个文件是文本文件还是二进制文件?在linux系统层面是不区分这两个的(譬如之前学过的open、read、write等方法操作文件文件和二进制文件时一点区别都没有),所以我们无法从文件本身准确知道文件属于哪种,我们只能本来就知道这个文件的类型然后用这种类型的用法去用他。有时候会用一些后缀名来人为的标记文件的类型。
(2)使用文本文件时,常规用法就是用文本文件编辑器去打开它、编辑它。用这些文本文件编辑器去打开文件的时候,编辑器会read读出文件二进制数字内容。
(3)反过来用二进制阅读工具去读取文本文件会怎么样?得出的就是文本文字所对应的二进制的编码。
1.2、目录文件(d dir ectory)
(1)目录就是文件夹,文件夹在linux中也是一种文件,不过是特殊文件。用vi打开一个文件夹就能看到,文件夹其实也是一种特殊文件,里面存的内容包括这个文件的路径,还有文件夹里面的文件列表。
(2)但是文件夹这种文件比较特殊,本身并不适合用普通的方式来读写。linux中是使用特殊的一些API来专门读写文件夹的。
1.3、字符设备文件(c character)
1.4、块设备文件(b block)
(1)设备文件对应的是硬件设备,也就是说这个文件虽然在文件系统中存在,但是并不是真正存在于硬盘上的一个文件,而是文件系统虚拟制造出来的(叫虚拟文件系统,如/dev /sys /proc等)
(2)虚拟文件系统中的文件大多数不能或者说不用直接读写的,而是用一些特殊的API产生或者使用的,具体在驱动阶段会详解。
1.5、管道文件(p pipe)
1.6、套接字文件(s socket)
1.7、符号链接文件(l link)
2.常用文件属性获取
2.1、stat、fstat、lstat函数简介
(1)每个文件中都附带了这个文件的一些属性(属性信息是存在于文件本身中的,但是它不像文件的内容一样可以被vi打开看到,属性信息只能被专用的API打开看到)
(2)文件属性信息查看的API有三个:stat、fstat、lstat,三个作用一样,参数不同,细节略有不同。
(3)linux命令行下还可以去用stat命令去查看文件属性信息,实际上stat命令内部就是使用stat系统调用来实现的。
root@ubuntu:~ # stat a.cFile: 'a.c'Size: 12 Blocks: 1 IO Block: 1024 regular file
Device: 31h/49d Inode: 29830 Links: 1
Access: (0777/-rwxrwxrwx) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2020-07-16 16:12:41.000000000 +0800
Modify: 2020-07-16 16:12:41.000000000 +0800
Change: 2020-07-16 16:12:41.000000000 +0800Birth: -
(4)stat这个API的作用就是让内核将我们要查找属性的文件的属性信息结构体的值放入我们传递给stat函数的buf中,当stat这个API调用从内核返回的时候buf中就被填充了文件的正确的属性信息,然后我们通过查看buf这种结构体变量的元素就可以得知这个文件的各种属性了。
(5)fstat和stat的区别是:stat是从文件名出发得到文件属性信息结构体,而fstat是从一个已经打开的文件fd出发得到一个文件的属性信息。所以用的时候如果文件没有打开(我们并不想打开文件操作而只是希望得到文件属性)那就用stat,如果文件已经被打开了然后要属性那就用fstat效率会更高(stat是从磁盘去读取文件的,而fstat是从内存读取动态文件的)。
(6)lstat和stat/fstat的差别在于:对于符号链接文件,stat和fstat查阅的是符号链接文件指向的文件的属性,而lstat查阅的是符号链接文件本身的属性。
2.2、struct stat结构体简介
struct stat {dev_t st_dev; /* ID of device containing file */ino_t st_ino; /* inode number */mode_t st_mode; /* protection */nlink_t st_nlink; /* number of hard links */uid_t st_uid; /* user ID of owner */gid_t st_gid; /* group ID of owner */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 512B blocks allocated *//* Since Linux 2.6, the kernel supports nanosecondprecision for the following timestamp fields.For the details before Linux 2.6, see NOTES. */struct timespec st_atim; /* time of last access */struct timespec st_mtim; /* time of last modification */struct timespec st_ctim; /* time of last status change */#define st_atime st_atim.tv_sec /* Backward compatibility */#define st_mtime st_mtim.tv_sec#define st_ctime st_ctim.tv_sec};
(1)struct stat是内核定义的一个结构体,在<sys/stat.h>中声明,所以我们可以用。这个结构体中的所有元素加起来就是我们的文件属性信息。
比如读几个stat信息:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#define NAME "1.txt"int main(void)
{int ret = -1;struct stat buf;memset(&buf, 0, sizeof(buf)); // memset后buf中全是0ret = stat(NAME, &buf); // stat后buf中有内容了if (ret < 0){perror("stat");exit(-1);}// 成功获取了stat结构体,从中可以得到各种属性信息了printf("inode = %d.\n", buf.st_ino);printf("size = %d bytes.\n", buf.st_size);printf("st_blksize = %d.\n", buf.st_blksize);return 0;
}
3.stat函数的应用案例
3.1、用代码判断文件类型
(1)文件类型就是-、d、l····
(2)文件属性中的文件类型标志在struct stat结构体的mode_t st_mode元素中,这个元素其实是一个按位来定义的一个位标志(有点类似于ARM CPU的CPSR寄存器的模式位定义)。这个东西有很多个标志位共同构成,记录了很多信息,如果要查找时按位&操作就知道结果了,但是因为这些位定义不容易记住,因此linux系统给大家事先定义好了很多宏来进行相应操作。
(3)譬如S_ISREG宏返回值是1表示这个文件是一个普通文件,如果文件不是普通文件则返回值是0.
3.2、用代码判断文件权限设置
(1)st_mode中除了记录了文件类型之外,还记录了一个重要信息:文件权限。
(2)linux并没有给文件权限测试提供宏操作,而只是提供了位掩码,所以我们只能用位掩码来自己判断是否具有相应权限。
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#define NAME "1.txt"int main(void)
{int ret = -1;struct stat buf;memset(&buf, 0, sizeof(buf)); // memset后buf中全是0ret = stat(NAME, &buf); // stat后buf中有内容了if (ret < 0){perror("stat");exit(-1);}
#if 0 // 判断这个文件属性//int result = S_ISREG(buf.st_mode);int result = S_ISDIR(buf.st_mode);printf("result = %d\n", result);
#endif// 文件权限测试//unsigned int result = (buf.st_mode & S_IRWXU) >> 8;unsigned int result = ((buf.st_mode & S_IRUSR)? 1: 0);printf("file owner: %u.\n", result); return 0;
}
4.文件权限管理
4.1、st_mode中记录的文件权限位
(1)st_mode本质上是一个32位的数(类型就是unsinged int),这个数里的每一个位表示一个含义。
(2)文件类型和文件的权限都记录在st_mode中。我们用的时候使用专门的掩码去取出相应的位即可得知相应的信息。
4.2、ls -l打印出的权限列表
(1)123456789一共9位,3个一组。第一组三个表示文件的属主(owner、user)对该文件的可读、可写、可执行权限;第2组3个位表示文件的属主所在的组(group)对该文件的权限;第3组3个位表示其他用户(others)对该文件的权限。
(2)属主就是这个文件属于谁,一般来说文件创建时属主就是创建这个文件的那个用户。但是我们一个文件创建之后还可以用chown命令去修改一个文件的属主,还可以用chgrp命令去修改一个文件所在的组。
4.3、文件操作时的权限检查规则
(1)一个程序a.out被执行,a.out中试图去操作一个文件1.txt,这时候如何判定a.out是否具有对1.txt的某种操作权限呢?
(2)判定方法是:首先1.txt具有9个权限位,规定了3种人(user、group、others)对该文件的操作权限。所以我们判定1.txt是否能被a.out来操作,关键先搞清楚a.out对1.txt到底算哪种人。准确的说是看a.out被谁执行,也就是当前程序(进程)是哪个用户的进程。
(3)刚才上面说的是我的分析,到底对不对还得验证。
4.4、access函数检查权限设置
(1)文件权限管控其实蛮复杂,一般很难很容易的确定对一个文件是否具有某种权限。设计优秀的软件应该是:在操作某个文件之前先判断当前是否有权限做这个操作,如果有再做如果没有则提供错误信息给用户。
(2)access函数可以测试得到当前执行程序的那个用户在当前那个环境下对目标文件是否具有某种操作权限。
4.5、chmod/fchmod与权限修改
(1)chmod是一个linux命令,用来修改文件的各种权限属性。chmod命令只有root用户才有权利去执行修改。
(2)chmod命令其实内部是用linux的一个叫chmod的API实现的。
4.6、chown/fchown/lchown与属主修改
(1)linux中有个chown命令来修改文件属主
(2)chown命令是用chown API实现的
4.7、umask与文件权限掩码
(1)文件掩码是linux系统中维护的一个全局设置,umask的作用是用来设定我们系统中新创建的文件的默认权限的。
(2)umask命令就是用umask API实现的
access检查权限:
#include <stdio.h>
#include <unistd.h>
#define NAME "3.txt"int main(void)
{int ret = -1;ret = access(NAME, F_OK);if (ret < 0){printf("文件不存在 \n");return -1;}elseprintf("文件存在 ");ret = access(NAME, R_OK);if (ret < 0)printf("不可读 ");elseprintf("可读 ");ret = access(NAME, W_OK);if (ret < 0)printf("不可写 ");elseprintf("可写 ");ret = access(NAME, X_OK);if (ret < 0)printf("不可执行 \n");elseprintf("可执行 \n"); return 0;
}
属主修改:
#include <stdio.h>
#include <sys/stat.h>
int main(int argc, char **argv)
{int ret = -1; if (argc != 2){printf("usage: %s filename\n", argv[0]);return -1;}ret = chmod(argv[1], S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWOTH);if (ret < 0){perror("chmod");return -1;}return 0;
}
5.读取目录文件
5.1、opendir与readdir函数
(1)opendir打开一个目录后得到一个DIR类型的指针给readdir使用
(2)readdir函数调用一次就会返回一个struct dirent类型的指针,这个指针指向一个结构体变量,这个结构体变量里面记录了一个目录项(所谓目录项就是目录中的一个子文件)。
(3)readdir调用一次只能读出一个目录项,要想读出目录中所有的目录项必须多次调用readdir函数。readdir函数内部会记住哪个目录项已经被读过了哪个还没读,所以多次调用后不会重复返回已经返回过的目录项。当readdir函数返回NULL时就表示目录中所有的目录项已经读完了。
5.2、dirent结构体
struct dirent {ino_t d_ino; /* inode number */off_t d_off; /* not an offset; see NOTES */unsigned short d_reclen; /* length of this record */unsigned char d_type; /* type of file; not supportedby all filesystem types */char d_name[256]; /* filename */};
5.3、读取目录:
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
int main(int argc, char **argv)
{DIR *pDir = NULL;struct dirent * pEnt = NULL;unsigned int cnt = 0;if (argc != 2){printf("usage: %s dirname\n", argv[0]);return -1;}pDir = opendir(argv[1]);if (NULL == pDir){perror("opendir");return -1;}while (1){pEnt = readdir(pDir);if(pEnt != NULL){// 还有子文件,在此处理子文件printf("name:[%s] ,", pEnt->d_name);cnt++;if (pEnt->d_type == DT_REG)printf("是普通文件\n");elseprintf("不是普通文件\n");}elsebreak;};printf("总文件数为:%d\n", cnt);return 0;
}
5.4、可重入函数介绍
(1)readdir函数和我们前面接触的一些函数是不同的,首先readdir函数直接返回了一个结构体变量指针,因为readdir内部申请了内存并且给我们返回了地址。多次调用readdir其实readir内部并不会重复申请内存而是使用第一次调用readdir时分配的那个内存。这个设计方法是readdir不可重入的关键。
(2)readdir在多次调用时是有关联的,这个关联也标明readdir函数是不可重入的。
(3)库函数中有一些函数当年刚开始提供时都是不可重入的,后来意识到这种方式不安全,所以重新封装了C库,提供了对应的可重复版本(一般是不可重入版本函数名_r)。
linux应用编程之文件属性相关推荐
- 嵌入式Linux文件提取,嵌入式 Linux系统编程(四)——文件属性
嵌入式 Linux系统编程(四)--文件属性 一.文件属性概述 Linux 文件的属性主要包括:文件的节点.种类.权限模式.链接数量.所归属的用户和用户组.最近访问或修改的时间等内容.文件属性示例如下 ...
- (47)LINUX应用编程和网络编程之二Linux文件属性
Linux下的文件系统为树形结构,入口为/ 树形结构下的文件目录: 无论哪个版本的Linux系统,都有这些目录,这些目录应该是标准的.各个Linux发行版本会存在一些小小的差异,但总体来说,还是大体差 ...
- 外网访问arm嵌入式linux_嵌入式Linux系统编程——文件读写访问、属性、描述符、API
Linux 的文件模型是从 Unix 的继承而来,所以 Linux 继承了 UNIX 本身的大部分特性,然后加以扩展,本章从 UNIX 系统接口来描述 Linux 系统结构的特性. 操作系统是通过一系 ...
- Linux网络编程——黑马程序员笔记
01P-复习-Linux网络编程 02P-信号量生产者复习 03P-协议 协议: 一组规则. 04P-7层模型和4层模型及代表协议 分层模型结构: OSI七层模型: 物.数.网.传.会.表.应TCP/ ...
- Linux串口编程详解
Linux串口编程详解(阻塞模式.非阻塞模式.select函数) 之前一直觉得串口编程很简单,这两天仔细研究后发现串口里的各种参数还挺复杂,稍不注意就容易出错,这里总结一下网上的各种文章及自己的理解与 ...
- 嵌入式Linux系统编程学习之二常用命令
嵌入式Linux系统编程学习之二常用命令 文章目录 嵌入式Linux系统编程学习之二常用命令 前言 一.常用命令 1.su(用户切换) 2.useradd(添加用户) 3.passwd(修改密码) 4 ...
- 4. linux调用文件计算阶乘前5项和_嵌入式Linux系统编程——文件读写访问、属性、描述符、API
Linux 的文件模型是从 Unix 的继承而来,所以 Linux 继承了 UNIX 本身的大部分特性,然后加以扩展,本章从 UNIX 系统接口来描述 Linux 系统结构的特性. 操作系统是通过一系 ...
- 计算机网络(二)Linux网络编程
layout: post title: 计算机网络(二)Linux网络编程 description: 计算机网络(二)Linux网络编程 tag: 计算机网络 文章目录 资源共享 Linux高性能服务 ...
- I.MX6U嵌入式Linux应用编程学习
I.MX6U嵌入式Linux应用编程学习 目录 I.MX6U嵌入式Linux应用编程学习 〇.备忘 0.0 本文大写字母缩写说明 0.1 C编译 0.2 NFS与文件夹挂载 一.应用编程概念 1.1 ...
最新文章
- 谷歌健康的「文化围墙」:空降的CEO,敌不过傲慢的Jeff Dean,和一群狂热的AI信徒
- linux top p 乱码,将Linux top命令输入到指定文件时的乱码问题
- c调用python代码找不到模块_构建 Python C 扩展模块
- vue.js踩坑之ref引用细节点
- Webscalesql代码浏览记录
- 如何从标签创建新分支?
- Binary translation is incompatible with long mode on this platform
- Cannot detect Web Project version. Please specify version of Web Project through Maven project ...报错
- netlink 0010 -- Generic Netlink 实现通信
- 弘辽科技:复购率太低怎么办呢?
- java 串口通信读取电子秤
- 【python】自动发送微信消息或文件
- SOAP实例入门(转)
- 图灵专访:郭霖的成长之路
- 怎样一次性删掉word或wps文档里的空格行
- python itchat教程_Python学习教程:教你用Python通过微信来控制电脑摄像头
- 惠普暗影精灵8 Pro酷睿版和锐龙版的区别 哪个更值得入手
- 常见的图片比例有哪些?App中不同图片比例适用场景
- Java基础篇——选择结构
- Jenkins生成APP二维码下载链接
热门文章
- Android的动画机制一 ----逐帧动画
- ADB Fastboot Recovery Hboot Bootloader介绍
- 施耐德昆腾plc怎么获取日志消息
- 男人甜言蜜语是女人“精神鸦片”
- HTML5停留时长统计,平均停留时间
- LaTeX 学习资料汇总
- java double 计算_Java中的Double类型计算
- Android 中实现上下文菜单(Context menu)详解
- 记一次删除.bash_profile文件
- Android高级工程师必备知识!Android学习路线指南,复习指南