Linux环境编程第三天笔记

Linux环境编程第三天笔记

标准文件I/O与系统文件I/O
  1. 系统文件I/O是Linux内核提供的系统调用函数,无缓冲机制,直接与内核交互。

  2. 标准文件I/O是基于C标准库,实现的函数,在用户空间维护缓冲区

效率:标准I/O > 系统文件I/O

各类文件

在Linux中,文件分为7种

文件类型 ls -l下的文件类型缩写 特点
普通文件 - 存在于外部存储器种,用于存储普通数据
目录文件 d 用于存放目录项,是文件系统管理的重要文件类型
管道文件 p 用于进程间通信的特殊文件,也称命名通道FIFO
套接字文件 s 用于网络间通信的特殊文件
链接文件 l 用于间接访问另外一个目标文件,相当于Windows的快捷方式
块设备文件 b 块设备在应用层的访问接口
open和openat

调用open或openat可以打开或创建一个文件。

返回值:若成功,返回文件描述符,若失败,返回-1。

复制代码
 #include <fcntl.c>
 ​
 int open(const char *path,int oflag);
 int open(const char *path,int oflag,mode_t mode);//mode为八进制权限
 ​
 int1 openat(int fd,const char *pa1th,int oflag)

path是打开或创建的文件名,oflag是函数的选项

情况 path类型 fd参数
1 绝对路径 任意值 fd被忽略,openat等价于open
2 相对路径 已打开的目录fd 相对于该目录文件描述符指向的目录
3 相对路径 AT_FDCWD 相对于进程的当前工作目录
oflag的值 效果
O_RDONLY 以只读的形式打开文件
O_WRONLY 以只写的形式打开文件
O_RDWR 以读/写的形式打开文件
O_CREAT 若文件不存在,创建文件
O_EXCL 如果使用O_CREAT选项且文件存在,返回错误信息
O_NOCTTY 如果文件为终端,那么终端不可以作为调用open()系统调用的那个进程的控制信息
O_TREAT 如果文件已经存在,则删除文件中原有数据
O_APPEND 以追加的形式打开文件
复制代码
     // 场景2:使用目录fd
     int dir_fd = open("/home", O_RDONLY | O_DIRECTORY);//打开目录
     int fd4 = openat(dir_fd, "user/file.txt", O_RDONLY);
     // 在/home/user/file.txt
     
     // 场景3:使用openat + AT_FDCWD
     int fd2 = openat(AT_FDCWD, "data.txt", O_RDONLY);//默认工作目录为进程的启动目录
     
     // 场景3:改变当前工作目录后
     chdir("/tmp");
     int fd3 = openat(AT_FDCWD, "temp.txt", O_RDONLY);
     // 在/tmp目录下打开temp.txt
  
close

可以调用close关闭一个打开的文件。

返回值:若成功,返回0,若失败返回-1

复制代码
 #include <unistd.h>
 int closen (int fd);

关闭一个文件时还会释放该进程加在该文件上的所有记录锁。

当一个进程终止时,内核自动关闭它所有的打开文件。

lseek

每个打开的文件都有一个与其相关联的"当前文件偏移量",通常读写操作都从当前文件偏移量处开始,当打开一个文件时,偏移量默认为0。

lseek可以显示地为一个打开文件设置偏移量。

返回值:若成功,返回新的文件偏移量,若失败,返回-1。

复制代码
 #include <unistd.h>
 off_t lseek(int fd,off_t offset,int whence);
whence 值 常量定义 含义说明 偏移量计算公式 offset 取值范围
SEEK_SET 0 从文件开头开始偏移 新偏移量 = offset offset ≥ 0(通常,负值可能导致错误)
SEEK_CUR 1 从当前位置开始偏移 新偏移量 = 当前偏移量 + offset 可正可负(正数向后,负数向前)
SEEK_END 2 从文件末尾开始偏移 新偏移量 = 文件长度 + offset 可正可负(正数超过文件尾,负数向前)

通过返回值可以用来测试文件是否可以设置偏移量

文件偏移量可以大于等于文件当前长度,这种情况下,文件下次写将加长该文件。

文件中未被写的字节都被读为0。

read

read函数可以从打开的文件中读数据

返回值:成功:读到字节数(若已到文件尾,返回0),失败:返回-1

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

参数buf为用户申请的缓冲区,参数count为要读取的字节数。

当从终端开始读时,通常最多一次读一行(如果标准输出是连接到终端,则它是行缓冲的,否则是全缓冲的)。

write

write可以向打开的文件写入数据

返回值:成功:返回写入的字节数;失败:返回-1

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

参数buf为用户申请的缓冲区,参数count要写入的字节数。

对于普通文件,写操作从文件当前偏移量处开始。

ioctl和fcntl

除非不得已,否则尽量使用fcntl。

复制代码
 #include <sys/ioctl.h>
 ​
 int ioctl(int fd, unsigned long request, ...);
  • fd:文件描述符(通常是设备文件)

  • request:请求码(设备特定)

  • ...:可变参数,通常是指向数据的指针

复制代码
 #include <fcntl.h>
 ​
 int fcntl(int fd, int cmd, ... /* arg */ );
命令字 cmd 变参 arg 含义
F_DUPFD long arg 复制一个在数值上大于或等于 arg 并未使用的文件描述符,并且使其代表与 fd 相同的文件
F_DUPFD_CLOEXEC long arg 作用和 F_DUPFD 一样,但新复制的描述符的 FD_CLOEXEC 状态会被置为 1
F_GETFD void 获取 FD_CLOEXEC 状态
F_SETFD long arg 设置 FD_CLOEXEC 状态,若该状态位为 0 则意味着该 fd 在程序执行 execve () 加载新代码时将保持有效,否则该 fd 在新代码执行时将被关闭
F_GETFL void 获取 status 状态
F_SETFL long arg 设置 status 状态 在 Linux 中,以下选项不可设置: O_RDONLY、O_WRONLY、O_RDWR、O_CREAT、O_EXCL、O_NOCTTY、O_TRUNC 以下的选项可以设置: O_APPEND、O_ASYNC、O_DIRECT、O_NOATIME、O_NONBLOCK
F_SETLK struct flock *arg 将 arg.l_type 设置为以下值意味着加锁: FD_RDLCK、FD_WRLCK 将 l_type 设置为以下值意味着解锁: FD_UNLCK 如果当前区域已经有冲突的锁存在,那么将立即返回 - 1,且 errno 将被设置为 EACCES 或 EAGAIN
F_SETLKW struct flock *arg 和 F_SETLK 一样,但在冲突的情况下将会阻塞等待
F_GETLK struct flock *arg 用 arg 中的信息检查是否有冲突,如果无冲突,则将 arg.l_type 设置为 FD_UNLCK,别的成员保持不变;如果有冲突,则 arg 将会储存当前冲突的锁的相关信息
F_GETOWN void 获取收到由 fd 输入或输出状态改变而触发的信号 SIGIO 和 SIGURG 的进程或进程组 ID。进程 ID 用正整数表示,进程组 ID 用负整数表示
F_SETOWN long arg 设置接收由 fd 输入或输出状态改变而触发的信号 SIGIO 和 SIGURG 的进程或进程组 ID 为 arg。进程 ID 用正整数表示,进程组 ID 用负整数表示
F_GETOWN_EX struct f_owner_ex *arg 作用同 F_GETOWN,但还能获取线程的 TID,且只能适用于 Linux-2.6.32 及以后的版本
F_SETOWN_EX struct f_owner_ex *arg 作用同 F_SETOWN,但还能设置线程的 TID,且只能适用于 Linux-2.6.32 及以后的版本
F_GETSIG void 获取由 fd 输入或输出状态改变而触发的信号
F_SETSIG long arg 设置由 fd 输入或输出状态改变而触发的信号
F_GETPIPE_SZ void 获取管道文件缓冲区的大小
F_SETPIPE_SZ long arg 设置管道文件缓冲区的大小为 arg。arg 必须介于 Linux 内存页大小和系统支持的最大尺寸(见 /proc/sys/fs/pipe-size-max)之间
mmap

mmap可以在进程的虚拟内存空间种映射出一块内存区域,并指定一个文件,用文件数据初始化这块内存,文件数据和内存中的数据一一对应

复制代码
 #include <sys/mman.h>
 ​
 void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
参数 说明
addr 内存映射的起始地址。 如果该参数为NULL,则系统将会自动寻找一个合适的起始地址 如果该参数为NULL,则系统会以此为依据寻找一个合适的起始地址。在Linux中一般为页地址的整数倍
length 映射区域的大小(字节)
prot 内存保护标志(按位或) PROT_EXEC :可执行 PROT_READ :可读 PROT_WRITE :可写 PROT_NONE :不可访问
flags 映射类型和特性(按位或)
fd 文件描述符(匿名映射时为-1)
offset 文件映射的偏移量(必须是页大小的倍数)
相关推荐
狐572 小时前
2026-01-18-LeetCode刷题笔记-1895-最大的幻方
笔记·算法·leetcode
~光~~2 小时前
【嵌入式linux学习】04_Pinctrl 和 GPIO子系统
linux·rk3588·嵌入式linux
475.352 小时前
linux-journal日志清理
linux·运维·服务器
weixin_438732102 小时前
ChromeDriver谷歌驱动下载
linux·chrome·selenium·自动化·mac·chrome devtools·chromedriver
Black__Jacket2 小时前
Ubuntu下,/dev下,无法读取到CH340串口芯片的端口号
linux·运维·ubuntu
AI视觉网奇3 小时前
Epic linux 打包。
笔记·学习·ue5
清泉影月3 小时前
Linux:Squid正向代理实现内网访问互联网
linux·运维·服务器
切糕师学AI3 小时前
ARM 中的 SVC 监管调用(Supervisor Call)
linux·c语言·汇编·arm开发
陌上花开缓缓归以3 小时前
linux jiffies 初始化不为0问题分析
linux·arm开发