🔥 每个系统都有自己的专属函数,我们习惯称其为系统函数。系统函数并不是内核函数,因为内核函数是不允许用户使用的,系统函数就充当了二者之间的桥梁,这样用户就可以间接的完成某些内核操作了。 如:open、close、lseek、read、write这些系统IO函数又被称为不带缓冲的IO (unbuffered IO)。术语不带缓冲指的是每个read和write都调用内核中的一个系统调用,因此也常叫做系统IO,与之相对应的还有标准IO(fopen、fread、fwrite、fclose等)。 应用层程序编写如下:
其实这个函数 我们之前在这篇博客里【Linux】基础 IO(文件描述符fd & 缓冲区 & 重定向)
提过的,大家可以去看看,以及下面的 close 和 write 也有说明
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
/*
* @description : 调用open可以打开或创建一个文件
* @param - path : 指定打开或创建的文件的文件名
* @param - flags : 指定文件的打开方式,选项后面有说明
* @param - mode : 在创建新文件的时候才需要指定这个参数的值,用于指定新文件的权限(常用值0664==rw-rw-r--);
* @return : 若成功,返回内核分配的文件描述符(大于0),失败返回-1;
*/
int open(const char *path, int flags, mode_t mode);flags参数指定了文件打开方式等信息。用下列一个或多个宏常量进行“或 | ”运算构成flags参数: (这些常量在头文件<fcntl.h>中定义)。 以下为必选属性 ,在这五个宏常量属性中必须指定一个且只能指定一个
flags | 说明 |
|---|---|
O_RDONLY | 以只读方式打开文件 |
O_WRONLY | 以只写方式打开文件 |
O_RDWR. | 以读写方式打开文件 |
O_EXEC | 只执行打开 |
O_SEARCH | 只搜索打开(应用于目录) |
以下为可选属性 , 可以和上边的属性一起使用。
flags | 说明 |
|---|---|
O_APPEND | 新数据追加到文件尾部,不会覆盖文件的原来内容 |
O_CREAT | 若此文件不存在则创建它,后面必须跟mode参数指定该新文件的访问权限。如果文件存在什么也不做 |
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
//返回值:若成功,返回已写的字节数(带符号整型);若出错,返回-1
fd:指定需要偏移操作的文件描述符
buf:字符串
count:长度返回值:通常与参数count的值相同,否则表示出错。 write 出错的一个常见原因:① 磁盘已写满,② 超过了一个给定进程的文件长度限制。
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
//返回值:若成功,返回读的字节数(带符号整型);若已到文件尾,返回0;出错,返回-1
fd:指定需要偏移操作的文件描述符
buf:字符串
count:长度有多种情况可使实际读到的字节数少于要求读的字节数:
#include <unistd.h>
/*
* @description : 调用close可以关闭一个已打开的文件
* @param - fd : 指定关闭的文件的描述符;
* @return : 若成功,返回0,失败返回-1;
*/
int close(int fd);关闭一个文件时还会释放该进程加在该文件上的所有记录锁。 当一个进程终止时,如果不调用close()手动关闭打开的文件,内核将自动关闭它所有的打开文件
每个打开文件都有一个与其相关联的 “当前文件偏移量” 它通常是一个非负整数,用以度量从文件开始处计算的字节数。 通常,读、写操作都从当前文件偏移量处开始,并使偏移量增加所读写的字节数。
当然也可以调用 lseek 显式地为一个打开文件设置偏移量。
#include <sys/types.h>
#include <unistd.h>
/*
* @description : 调用lseek函数可以移动文件指针,也可以通过这个函数进行文件的拓展。
* @param - fd : 指定需要偏移操作的文件描述符;
* @param - offset : 指定偏移量,需要和第三个参数配合使用
* @param - whence : 通过这个参数指定函数实现什么样的功能:
* SEEK_SET: 从文件头部开始偏移 offset 个字节
* SEEK_CUR: 从当前文件指针的位置向后偏移 offset 个字节
* SEEK_END: 从文件尾部向后偏移 offset 个字节
* @return : 若成功,返回文件指针从头部开始计算总的偏移量;出错,返回-1
*/
off_t lseek(int fd, off_t offset, int whence);对参数offset的解释与参数whence的值(符号常量)有关:
使用代码打开当前路径下的“bite”文件(如果文件不存在在创建文件),向文件当中写入“i like linux!”.
#include <stdio.h>
#include <unistd.h>//是close, write这些接口的头文件
#include <string.h>
#include <fcntl.h>//是 O_CREAT 这些宏的头文件
#include <sys/stat.h>//umask接口头文件
int main()
{
//将当前进程的默认文件创建权限掩码设置为0--- 并不影响系统的掩码,仅在当前进程内生效
umask(0);
//int open(const char *pathname, int flags, mode_t mode);
int fd = open("./bite", O_CREAT|O_RDWR, 0664);
if(fd < 0) {
perror("open error");
return -1;
}
char *data = "i like linux\n!";
//ssize_t write(int fd, const void *buf, size_t count);
ssize_t ret = write(fd, data, strlen(data));
if (ret < 0) {
perror("write error");
return -1;
}
//off_t lseek(int fd, off_t offset, int whence);
lseek(fd, 0, SEEK_SET);
char buf[1024] = {0};
//ssize_t read(int fd, void *buf, size_t count);
ret = read(fd, buf, 1023);
if (ret < 0) {
perror("read error");
return -1;
}else if (ret == 0) {
printf("end of file!\n");
return -1;
}
printf("%s", buf);
close(fd);
return 0;
}运行结果如下:

#incldue<stdio.h>
FILE * fopen(const char *pathname, const char *method);功能:用于打开文件
参数:
具体方式如下:
FILE *fp;//定义一个指向FILE结构的指针
// 在当前路径用可读可写打开一个“ccc.txt”的文件,如果不存在则创建它
fp=fopen("./ccc.txt","w+");返回值
当打开一个流时,标准IO函数fopen返回一个指向FILE对象的指针( 文件指针)。 该对象通常是一个结构,它包含了标准IO库为管理该流需要的所有信息(流), 包括用于实际IO 的文件描述符、指向用于该流缓冲区的指针、缓冲区的长度、当前在缓冲区中的字符数以及出错标志等。
size_t fwrite(void *ptr, size_t size, size_t nmemb, FILE *stream);参数:
返回值
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);参数:
返回值
int fclose( FILE *file )返回值:
在该文件被关闭之前,冲洗缓冲中的输出数据。
则所有带未写缓冲数据的标准IO流都被冲洗,所有打开的标准IO流都被关闭
int fseek(FILE *stream, long offset, int whence);参数:
返回值:
使用代码打开当前路径下的“bite”文件(如果文件不存在在创建文件),向文件当中写入“linux so easy!”.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
FILE *fp = fopen("./byte", "wb+");
if(fp == NULL){
perror("fopen Error");
return -1;
}
fseek(fp, 0, SEEK_SET);//跳转读写位置到,从文件起始位置开始偏移0个字节
char *data = "linux so easy!\n";
size_t ret = fwrite(data, 1, strlen(data), fp);
if(ret != strlen(data)){
perror("fwrite Error");
return -1;
}
fseek(fp, 0, SEEK_SET);
char buf[1024] = {0};
//因为设置读取块大小位1,块个数为1023因此fread返回值为实际读取到的数据长度
ret = fread(buf, 1, 1023, fp);
if (ret == 0) {
if (ferror(fp)) //判断上一次IO操作是否正确
printf("fread error\n");
if (feof(fp)) //判断是否读取到了文件末尾
printf("read end of file!\n");
return -1;
}
printf("%s", buf);
fclose(fp);
return 0;
}运行结果如下:

errno 来处理错误。ferror() 等函数检查错误状态。【*★,°*:.☆( ̄▽ ̄)/$:*.°★* 】那么本篇到此就结束啦,如果我的这篇博客可以给你提供有益的参考和启示,可以三连支持一下 !!