Linux系统编程-文件IO
文件IO
标准库IO函数和linux系统调用IO函数的区别:
-
标准C库的文件IO函数是跨平台的,在不同的平台上调用不同的系统API
-
标准C库的IO函数有缓冲区,而linux系统调用的没有缓冲区
因此,在网络通信时尽量使用系统调用提高效率,而在读写磁盘时尽量使用库函数减少读写次数
标准库函数和系统调用的关系是 调用与被调用 的关系
文件描述符
在PCB中有一个文件描述符表,记录这个进程打开的所有文件信息。一般默认大小是1024,有3个默认打开的文件:标准输入,标准输出,标准错误默认都是打开的状态,文件描述符分别是0,1,2。这三个文件都指向当前终端 /dev/tty
每次新打开一个文件都会分配一个最小的可分配的文件描述符。
对于同一个进程,可以对同一个文件打开多次,每次分配的文件描述符是不一样的
常用函数
1. 对文件的操作函数
-
open() 打开一个存在的文件 或者 创建一个新文件
-
close() 关闭一个打开的文件,文件描述符被释放掉
/* int open(const char *pathname, int flags); int open(const char *pathname, int flags, mode_t mode); 参数: -pathname: 包括文件名的路径 -flags: O_WRONLY, O_RDONLY, O_RDWR, 可选项 O_APPEND O_CREAT, 用|连接 -mode: 若需要创建文件,则传入要创建的文件权限,八进制 例如0664 最终权限是 mode&~umask 不同的用户的umask是不同的,直接输入umask就能查看,可以自己设置 umask的作用就是抹去某些权限,使得权限更加合理 返回值: 调用失败返回-1,否则返回文件描述符 */ #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdio.h> #include <unistd.h> int main(){ int fd = open("a.txt", O_RDONLY); if(fd == -1){ perror("open: "); } close(fd); return 0; }
-
read() 读数据
-
write() 写数据
/* #include <unistd.h> ssize_t read(int fd, void *buf, size_t count); 参数: -fd 文件描述符,open得到的,通过这个文件描述符来操作某个文件 -buf: 需要读取数据存放的地方,数组的地址(传出参数) -count: 指定的数组的大小 读出来的数据保存到buf 返回值: 成功返回读取到的字节数量(返回0就表示到文件的末尾了) 失败了返回-1,并且设置errno #include <unistd.h> ssize_t write(int fd, const void *buf, size_t count); -fd 文件描述符 -buf 要往磁盘写入的数据 -count 要写数据的实际大小 返回值: 实际写入的字节数,失败返回-1 */ #include <unistd.h> #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int main(){ int src = open("create.txt", O_RDONLY); if(src==-1){ perror("open:"); } int destfd = open("cpy.txt", O_WRONLY | O_CREAT, 0664); if(destfd == -1){ perror("open:"); } char buf[1024] = {0}; int len = 0; while((len=read(src, buf, sizeof(buf))) > 0){ write(destfd, buf, len); } close(src); close(destfd); return 0; }
-
lseek() 移动文件指针
/* C库: fseek #include <stdio.h> int fseek(FILE *stream, long offset, int whence); linux lseek系统调用 #include <sys/types.h> #include <unistd.h> off_t lseek(int fd, off_t offset, int whence); 参数: -fd: 文件描述符 -offset: 偏移量 whence: SEEK_SET 设置文件指针的偏移量(文件头开始) SEEK_CUR 设置偏移量: 当前位置 + 第二个参数offset的值 SEEK_END 设置偏移量: 文件大小(文件结尾) + 第二个参数offset的值 返回值: 返回文件指针的位置 作用: 移动文件指针 获取当前文件指针的位置 获取文件长度 拓展文件的长度 lseek(fd, 100, SEEK_END); 移动后最好再写入一个空数据 */
-
stat()
/*
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int stat(const char *pathname, struct stat *statbuf);
作用: 获取一个文件的相关信息 可以直接使用stat a.txt在shell终端查看文件信息
参数:
-pathname: 操作的文件路径
-statbuf: 结构体变量,传出参数,用于保存获取到的文件信息
返回值: 成功返回0,失败返回-1并设置errno
int lstat(const char *pathname, struct stat *statbuf);
获取软链接的信息,否则stat获取的是软链接指向的文件的信息
*/
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
int main() {
struct stat statbuf;
int ret = stat("cpy.txt", &statbuf);
if(ret == -1){
perror("stat: ");
}
printf("size: %ld\n", statbuf.st_size);
return 0;
}
分类:
Linux
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!