简 述: 讲解在 Unix / Linux
下,man
手册的使用;写了一个例子调用系统库函数来读写文本文件,和打印文件描述符;阻塞和非阻塞实际是文件的属性,而非标准输入输出的 I/O 函数的属性。 以及文件详细描述的 stat
命令和 stat()
函数的使用;文件属性相关的操作;文件夹遍历和创建、删除的相关函数,可能 Linux
有时候会调用到他们,现在实际上,更多的使用 Qt 的库来对文件进行读写操作;以及关于复制文件描述符的函数 dup()
函数的讲解
[TOC]
本文初发于 “偕臧的小站“,同步转载于此。
编程环境:
💻: uos20
📎 gcc/g++ 8.3
📎 gdb8.0
💻: MacOS 10.14
📎 gcc/g++ 9.2
📎 gdb8.3
man 手册的使用:
man 2 open
在第二章里面,精确查找 open 函数man man
查看 man 手册的大致介绍 (Linux 下)mac 下安装中文 man 文档:Mac配置中文 man 手册
系统函数读写文件:
如下为 Unix / Linux系统的库函数:
open()
:打开文件read()
:对文件进行读操作write()
:对文件进行写操作lseek()
:移动文件指针;扩展文件大小(移动指针后,要进行一次写操作)文件指针移动到头部:lseek(fd, 0, SEEK_SET);
文件指针移动到尾部:lseek(fd, 0, SEEK_END);
文件指针移动到当前位置:lseek(fd, 0, SEEK_SUR);
文件大写为 100K, 扩展到 1000K:
lseek(fd, 1000, SEEK_END); //文件指针从文件尾部偏移 1000 大小,这部分用^@ 填充占位 wrire(fd, "a", 1); //随便写一个什么到文件中,进行一次写操作
全局变量 errno
:对于调用系统函数对文件进行读写操作,函数会返回一个错误 int 类型的数值。而 errno 变量就是不同的错误返回值的含义打印出来(字符串),使得人类可以看懂。调用方法:perror("[注释信息: ]");
写一例子:
将
Linux
系统的函数,调用open
、printf
、read
写一个例子:编写代码如下:
#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <stdio.h> #include <errno.h> int main() { int fp = open("hello.txt", O_RDWR); int fp2 = open("temp.txt", O_WRONLY | O_CREAT, 0777); //创建文件时候,必须要有权限 printf("fp = %d\n", fp); printf("fp2 = %d\n", fp2); if (fp == -1) perror("[注释信息: ]"); //如果返回错误,会打印人类可读懂的出字符串 char buf[4096]; int len = read(fp, buf, sizeof(buf)); while (len > 0) { int ret = write(fp2, buf, len); len = read(fp, buf, sizeof(buf)); printf("ret = %d\n", ret); } close(fp); close(fp2); return 0; }
编译:
g++-9 main.cpp -o main
运行:其中 fp 便是打开文件 hello.txt 的文件描述符(因为 0、1、2 被 stdin、stdout、stdout 占了,所以最小就是 3);然后当打开第二个文本文件 temp.txt 的时候,其返回的文件描述符自然就是 4。关于文件描述符,详细原理解释可参考 此篇 。
源码下载: 07_sysfun
阻塞和非阻塞:
终端程序: bash 为前台程序,当执行 a.out 程序时候,bash 就成为了后台程序,a.out 成为了前台程序(代码执行到,等待输入);当键盘输入完成,a.out 成为了后台程序,bash 成为了前台程序。
当输入的长度 大于 buf[10] 中的 10 时候, 多余的部分就会成为后面的命令输入。
将下面的两种,手动敲一遍。
阻塞 和 非阻塞 情况下,是文件的属性,而非标准输入输出的 I/O 函数的属性。
普通文件:hello.cpp
- 默认是非阻塞
终端设备 /dev/tty (默认是阻塞)
- 终端
- 管道
- 套接字
stat / lstat 函数 :
写一个小的程序,判断
ls -l
命令,基本可以实现 改用 switch()lstat
和stat
函数对于链接 l 的区别不一样。- lstat 读取的是链接文件, 本身的属性
- stat 读取的是链接文件指向的文件的属性 (也被称呼:追踪,穿透)
- fstat 第一个参数是指文件描述符
#对应的 stat 命令:
作用:显示文件或文件系统的状态
uinx: stat -x hello.txt
linux: stat hello.txt
运行命令可以看到:hell.txt 文件的所有信息
由 ls -l hello.txt
查看看的,前面的 -rwxrwxrwx
就是表示下图的 文件类型 、文件所有者权限 、文件所属组权限 、其他人对该文件的权限 ,
- 其用 含义就是如下:
- 其在代码里面,用 struct 所表示的为:
st_ mode -- 16位整数
0-2 bit--其他人权限
- S_IROTH 00004 读权限
- S_IWOTH 00002 写权限
- S_IXOTH 00001 执行权限
- S_IRIvxO 00007 掩码,过滤 st_mode 中除其他人权限以外的信息
3-5 bit --所属组权限
-S_IRGRP 00040 读权限
-S_IWGRP 00020 写权限
-S_IXGRP 00010 执行权限
-S_IRWXG 00070 掩码,过滤 st_mode 中除所属组权限以外的信息
6-8 bit --文件所有者权限
-S_IRUSR 00400 读权限
-S_IWUSR 00200 写权限
-S_IXUSR 00100 执行权限
-S_IRWXU 00700 掩码,过滤 st_mode 中除文件所有者权限以外的信息。
12-15 bit --文件类型
-S_IFSOCK 0140000 套接字
-S_IFLNK 0120000 符号链接(软链接)
-S_IFREG 0100000 普通文件
-S_IFBLK 0060000 块设备
-S_IFDIR 0040000 目录
-S_IFCHR 0020000 字符设备
-S_IFIFO 0010000 管道
-S_IFMT0 0017000 掩码,过滤 st_mode 中除文件类型以外的信息
// 命令对应的函数
int stat(const char *path, struct stat *buf);
int Istat(const char *path, struct stat *buf);
文件属性相关的函数:
access()
判断传入的文件,所具有的(读、写、执行、是否存)的权限chmod()
修改文件权限chown()
修改文件所有者和所属组truncate()
修改文件大小^@
文件空洞, 填充占位符号,实际就是\0
目录操作相关函数:
目录操作相关函数:
rename()
文件重命名chdir()
修改 当前进程(应用程序)的路径;cdgetcwd()
获取当前进程的工作目录;pwdmkdir()
创建目录;mkdirrmdir()
删除一个空目录;rm
目录遍历相关函数:
opendir()
打开一个目录readdir()
读目录(进入子目录,需要手动创建递归函数)close()
关闭目录
dup / dup2 / fcntl 函数:
dup()
复制文件描述符dup2()
同上,形参不同(也会称为 参数 2:文件描述符的重定向)fcntl()
修改文件的状态标志
下载地址:
https://github.com/xmuli/linuxExample
欢迎 star 和 fork 这个系列的 linux 学习,附学习由浅入深的目录。