当前位置:网站首页>标准C库的IO函数
标准C库的IO函数
2022-07-26 22:45:00 【半块方便面】
文章目录
前言
标准C库的IO函数就是调用Linux系统的IO函数。
一、标准C的IO函数
| 库函数 | 参数 | 返回值 |
|---|---|---|
FILE* fopen(const char* pathname,const char* mode) | pathname: 路径名字,mode: 打开方式 | 成功:文件指针,失败:NULL |
int fclose(FILE* stream) | stream: 文件指针 | 成功:0,失败:-1 |
int fseek(FILE* stream,long offset,int whence)【文件偏移】 | stream: 文件指针,offset: 偏移数(负号向左,正好向右),whence:SEEK_SET文件的开头,SEEK_CUR 文件指针的当前位置,SEEK_END 文件的末尾 | 成功:0,失败 -1 |
long int ftell(FILE *stream)【返回当前文件位置】 | stream: 文件指针 | 成功:标识符的当前值,失败:-1 |
void rewind(FILE* stream) 【返回到文件开头】 | stream: 文件指针 | |
char *fgets(char *s, int size, FILE *stream) | s: 存储读到的字符,size: 最大存储字符数,stream: 文件指针 | 成功:读到的字符,失败:NULL |
int fputs(char* s,FILE* stream) | s: 写入的字符,stream: 文件指针 | 成功:0,失败:-1 |
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream) 【二进制读入】 | ptr: 存放文件内容地址,size: 读取的块大小,nmemb: 块数(读取文件大小 = 块数*每块大小) ,stream: 文件指针 | 成功读取到文件块数 |
size_t fwrite(void *ptr, size_t size, size_t nmemb, FILE *stream) 【二进制写出】 | ptr: 写入文件内容地址,size: 块大小,nmemb: 块数(写出文件大小 = 块数*每块大小),stream 文件指针 | 成功:写入到文件块数 |
int fflush(FILE *stream) 【刷新缓冲区】 | stream: 文件指针 | 成功:0,失败:-1 |
文件指针(结构体)的包含内容:
- 文件描述符,本质是一个索引指向磁盘文件
- 文件读写指针位置,读写文件过程中指针的实际位置
- I/O缓冲区(内存地址),通过寻址找到对应的内存块,默认缓冲区为 8KB
从缓冲区把内容写到磁盘的操作:
- 刷新缓冲区
fflush - 缓冲区已满
- 关闭文件,
fclose、return(main函数)、exit(main函数)
网络编程需要使用Linux内核的I/O函数,否则用户会一直等待,直到刷新缓冲区
二、虚拟地址空间
当系统启动一个程序时,就会创建一个进程,该进程执行启动的程序,进程同时对应一个虚拟地址空间,为进程所拥有的资源。虚拟地址空间在32位机器中大小位2的32次方,64位机器中大小为2的48次方,其结构图如下图所示,虚拟地址空间会被CPU中的MMU(内存管理单元)映射到真实的物理地址,在真实的物理空间中不会有4GB大小。
参加这篇文章:虚拟地址空间图解
三、文件描述符
程序只是一个文件,占用磁盘空间,进程可以理解成 操作系统为一个正在运行的程序分配资源的基本单位,进程拥有一个虚拟地址空间,其中文件描述符位于进程的虚拟地址空间的内核区,具体存在于进程控制块(一个复杂的结构体,叫做PCB)的文件描述符表中,PCB位于内核的内存管理模块,文件描述符表是一个默认大小为1024的数组。Linux系统中一切皆文件,所以把一切硬件驱动都看为文件,同一个文件可以被打开多次,且文件描述符不一样。
四、Linux的系统调用
open,打开文件
int open(const char* pathname,int flags),打开一个已经存在的文件,需要包含的头文件有三个:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
- 参数:
pathname:要打开的文件路径
flags:对文件的操作权限设置还有其他的设置,O_RDONLY, O_WRONLY, O_RDWR,这三个操作权限设置是互斥的- 返回值:返回一个新的文件描述符,如果调用失败,返回-1并设置errno
close
- int
close(int fd),关闭一个文件描述符,并且该文件描述符可以被重用。其头文件位于;
#include <unistd.h>
- 参数
fd:文件描述符;- 返回值:成功返回 0,如果调用失败,返回 -1 并设置errno
open,创建文件
- int
open(const char *pathname, int flags, mode_t mode),创建一个新文件,其头文件位于:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
参数:
- pathname:要创建的文件的路径
- flags:对文件的操作权限和其他的设置
必选项:O_RDONLY, O_WRONLY, O_RDWR 这三个之间是互斥的
可选项:O_CREAT 文件不存在,创建新文件;O_APPEND,在文件中追加内容,其他的权限这里不列出了;flags参数是一个int类型的数据,占4个字节,32位,每一位就是一个标志位。- mode:八进制的数,表示创建出的新的文件的操作权限,最终的权限是:mode & ~umask,umask的作用就是抹去某些权限。
返回值:返回一个新的文件描述符,如果调用失败,返回-1并设置errno
read
- ssize_t
read(int fd, void *buf, size_t count),从磁盘读文件数据到内存。其头文件位于;
#include <unistd.h>
- 参数:
- fd:文件描述符,open得到的,通过这个文件描述符操作某个文件
- buf:需要读取数据存放的地方,数组的地址(传出参数)
- count:指定的数组的大小,sizeof(buf)- 返回值:
- 成功:
>0: 返回实际的读取到的字节数
=0:文件已经读取完了
- 失败:-1 ,并且设置errno
write
- ssize_t
write(int fd, const void *buf, size_t count),从内存写数据到磁盘文件。其头文件位于;
#include <unistd.h>
参数:
- fd:文件描述符,open得到的,通过这个文件描述符操作某个文件
- buf:要往磁盘写入的数据
- count:要写的数据的实际的大小,buf中的有效数据,buf可能没有存满
返回值:
成功:实际写入的字节数
失败:返回-1,并设置errno
lseek
- off_t
lseek(int fd, off_t offset, int whence);。其头文件位于;
#include <sys/types.h>
#include <unistd.h>
参数:
- fd:文件描述符,通过open得到的,通过这个fd操作某个文件
- offset:偏移量
- whence:
SEEK_SET 设置文件指针的偏移量
SEEK_CUR 设置偏移量:当前位置 + 第二个参数offset的值
SEEK_END 设置偏移量:文件大小 + 第二个参数offset的值返回值:返回文件指针的位置
作用:
1.移动文件指针到文件头
lseek(fd, 0, SEEK_SET);
2.获取当前文件指针的位置
lseek(fd, 0, SEEK_CUR);
3.获取文件长度
lseek(fd, 0, SEEK_END);
4.拓展文件的长度,当前文件10b, 110b, 增加了100个字节
lseek(fd, 100, SEEK_END)
注意:需要写一次数据
stat
int stat(const char *pathname, struct stat *statbuf),作用是获取一个文件相关的一些信息,其头文件位于:
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
参数:
- pathname:操作的文件的路径
- statbuf:结构体变量(下面代码所示),传出参数,用于保存获取到的文件的信息
返回值:
- 成功:返回0
- 失败:返回-1 设置errno
struct stat {
dev_t st_dev; // 文件的设备编号
ino_t st_ino; // 节点
mode_t st_mode; // 文件的类型和存取的权限
nlink_t st_nlink; // 连到该文件的硬连接数目
uid_t st_uid; // 用户ID
gid_t st_gid; // 组ID
dev_t st_rdev; // 设备文件的设备编号
off_t st_size; // 文件字节数(文件大小)
blksize_t st_blksize; // 块大小
blkcnt_t st_blocks; // 块数
time_t st_atime; // 最后一次访问时间
time_t st_mtime; // 最后一次修改时间
time_t st_ctime; // 最后一次改变时间(指属性)
};
st_mode 变量的表示方式
st_mode 与掩码进行按位与,可以得到文件类型,同理获得文件的操作权限。
lstat
int stat(const char *pathname, struct stat *statbuf),获取软链接的信息,头文件位于:
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
参数:
- pathname:操作的文件的路径
- statbuf:结构体变量,传出参数,用于保存获取到的文件的信息
返回值:
- 成功:返回0
- 失败:返回-1 设置errno
access
int access(const char *pathname, int mode),作用为:判断某个文件是否有某个权限,或者判断文件是否存在。头文件#include <unistd.h>
参数:
- pathname: 判断的文件路径
- mode:
R_OK: 判断是否有读权限
W_OK: 判断是否有写权限
X_OK: 判断是否有执行权限
F_OK: 判断文件是否存在返回值:成功返回0, 失败返回-1
chmod
int chmod(const char *pathname, mode_t mode),修改文件的权限。头文件#include <sys/stat.h>
参数:
- pathname: 需要修改的文件的路径
- mode:需要修改的权限值,八进制的数
返回值:成功返回0,失败返回-1
chmod
int chmod(const char *pathname, uid_t owner, gid_t group),修改文件的所有者或者所在组
参数:
- pathname: 需要修改的文件的路径
- owner:文件所有者的id
- group:文件所在组的id
返回值:成功返回0,失败返回-1
truncate
int truncate(const char *path, off_t length),缩减或者扩展文件的尺寸至指定的大小。
参数:
- path: 需要修改的文件的路径
- length: 需要最终文件变成的大小
返回值: 成功返回0, 失败返回-1
mkdir
int mkdir(const char *pathname, mode_t mode),创建一个目录,头文件
#include <sys/stat.h>
#include <sys/types.h>
参数:
pathname: 创建的目录的路径
mode: 权限,八进制的数
返回值:
成功返回0, 失败返回-1
rmdir
int rmdir(const char *pathname),只能删除空目录。头文件
#include <sys/stat.h>
#include <sys/types.h>
参数:
pathname: =目录的路径
返回值:
成功返回0, 失败返回-1
rename
int rename(const char *oldpath, const char *newpath),重命名。头文件#include <stdio.h>
参数:
- oldpath:旧的名字,
- newpath:新的名字
返回值:
- 成功返回0, 失败返回-1
chdir
int chdir(const char *path), 修改进程的工作目录,比如在/home/nowcoder 启动了一个可执行程序a.out, 进程的工作目录 /home/nowcoder。头文件 #include <unistd.h>
参数:
path : 需要修改的工作目录
getcwd
char *getcwd(char *buf, size_t size),获取当前工作目录,头文件 #include <unistd.h>
作用:
参数:
- buf : 存储的路径,指向的是一个数组(传出参数)
- size: 数组的大小
返回值:
返回的指向的一块内存,这个数据就是第一个参数
opendir
DIR *opendir(const char *name),打开一个目录,头文件
#include <sys/types.h>
#include <dirent.h>
参数:
- name: 需要打开的目录的名称
返回值:
DIR * 类型,理解为目录流
错误返回NULL
readdir
struct dirent *readdir(DIR *dirp),读取目录中的数据,头文件#include <dirent.h>
- 参数:dirp是opendir返回的结果
- 返回值:
struct dirent,代表读取到的文件的信息
读取到了末尾或者失败了,返回NULL
struct dirent{
// 此目录进入点的inode
ino_t d_ino;
// 目录文件开头至此目录进入点的位移
off_t d_off;
// d_name 的长度, 不包含NULL字符
unsigned short int d_reclen;
// d_name 所指的文件类型
unsigned char d_type;
// 文件名
char d_name[256];
};
变量 d_type:
DT_BLK - 块设备
DT_CHR - 字符设备
DT_DIR - 目录
T_LNK - 软连接
DT_FIFO - 管道
DT_REG - 普通文件
DT_SOCK - 套接字
DT_UNKNOWN - 未知
closedir
int closedir(DIR *dirp),,关闭目录,头文件
#include <sys/types.h>
#include <dirent.h>
参数:
- dirp: 目录的名称
返回值:
成功返回0, 失败返回-1
dup
int dup(int oldfd),复制一个新的文件描述符, 从空闲的文件描述符表中找一个最小的,作为新的拷贝的文件描述符,头文件 #include <unistd.h>
参数: oldfd:旧的文件描述符
返回值:复制的文件描述符,失败返回-1,设置errno
fd=3, int fd1 = dup(fd),
fd指向的是a.txt, fd1也是指向a.txt
dup2
int dup2(int oldfd, int newfd),作用:重定向文件描述符,头文件 #include <unistd.h>
oldfd 指向 a.txt, newfd 指向 b.txt
调用函数成功后:newfd 和 b.txt 取消关联, newfd 指向了 a.txt
oldfd 必须是一个有效的文件描述符
oldfd和newfd值相同,相当于什么都没有做
参数:
oldfd:文件描述符 newfd:文件描述符
返回值:成功返回 newfd (文件描述符),失败返回-1
fcntl
int fcntl(int fd, int cmd, … /* arg */ ),作用:复制文件描述符 和 设置/获取文件的状态标志,头文件
#include <unistd.h>
#include <fcntl.h>
参数:
fd : 表示需要操作的文件描述符
cmd: 表示对文件描述符进行如何操作
F_DUPFD : 复制文件描述符,复制的是第一个参数fd,得到一个新的文件描述符(返回值)
int ret = fcntl(fd, F_DUPFD);
F_GETFL : 获取指定的文件描述符文件状态flag
获取的flag和我们通过open函数传递的flag是一个东西。
F_SETFL : 设置文件描述符文件状态flag
必选项:O_RDONLY, O_WRONLY, O_RDWR 不可以被修改
可选性:O_APPEND, NONBLOCK
O_APPEND 表示追加数据
NONBLOK 设置成非阻塞
阻塞和非阻塞:描述的是函数调用的行为。
errno
Liunx系统调用发生错误时,会记录错误信息到errno中, errno:属于Linux系统函数库,库里面的一个全局变量,记录的是最近的错误号。
#include <stdio.h> //perror的库
void perror(const char *s);
//作用:打印errno对应的错误描述
//s参数:用户描述,比如hello,最终输出的内容是 hello:xxx(xxx为实际的错误描述)
总结
牛客网C++课程,记录学习过程。
边栏推荐
猜你喜欢
随机推荐
23NFS共享存储服务
iptables
Summary of heap sorting related knowledge
Jenkins -- Foundation -- 02 -- Installation
十二、正则表达式
Problem feedback: the synchronization of mobile app failed: the external changes of the data warehouse were damaged. The iPad app also downloaded the warehouse as soon as it was opened, and then flash
Problems and solutions of paddleocr packaging
Mqtt protocol ----- above
VirtualBox VMS extended disk space
软件测试面试题之软件基础
14、 Sed
Shell(13)三剑客
正则表达式
ESP8266 STA_TCP_Client
十五、expect
27shell之条件语句
Basic introduction to Matlab [1]
Buuctf casual note, exec, easysql, secret file
Shortcut key introduction
十四、sed









