目录
一.C文件接口
1.hello.c写文件
2.hello.c读文件
3.输出信息到显示器
二、系统文件I/O
0.系统调用和库函数
1.open
2.write
3.read
4.close
三、文件描述符fd
1. 0 & 1 & 2
2.文件描述符分配规则
3.重定向
4.使用dup2系统调用
四、FILE
一.C文件接口
1.hello.c写文件
#include<stdio.h>
#include<string.h>
int main()
{
FILE * fp = fopen("file","w");
if(!fp)
{
printf("error");
}
const char * msg = "hello";
int count = 5;
while(count--)
{
//fwrite(const void * buffer,size_t size, size_t count, FILE * stream)
//buffer 数据存储的地址,size 读取的字节大小 count 要读多少个字节 stream 等待被写入的资源
fwrite(msg,strlen(msg),1,fp);
//返回值:返回写入元素的个数
}
fclose(fp);
return 0;
}
2.hello.c读文件
#include<stdio.h>
#include<string.h>
int main()
{
FILE * fp = fopen("file","r");
if(!fp)
{
printf("fopen error");
}
char buf[1024];
const char * msg = "hello";
while(1)
{
//size_t fread(void * buffer, size_t size, size_t count, FILE * stream)
//将stream中的文件读取count个size字节到buffer中
ssize_t s = fread(buf,1,strlen(msg),fp);
if(s > 0)
{
buf[s] = 0;
prinf("%s",buf);
}
if(feof(fp))
break;
}
fclose(fp);
return 0;
}
3.输出信息到显示器
int fprintf(FILE * stream, cosnt char * format, ...)
stream是文件指针,表示要输出到的文件
format是格式化字符串
返回值是成功输出的字符个数
二、系统文件I/O
0.系统调用和库函数
fopen,close,fread,fwrite都是C库中的函数,称为库函数(libc)
open,close,read,write,lseek都是系统提供的接口,称为系统调用接口
可以认为,f#系列函数,都是对系统调用的封装,方便二次开发
1.open
返回值:返回值类型为int ,大于0,表示成功打开,这个数字称为文件描述符
#include<sys/types.h> #include<stat.h> #include<fcntl.h> int open(const char * pathname, int flags); int open(const char * pathname,int flags,mode_t mode) pathname:要打开或者要创建的目标文件 flags: O_RDONLY:只读打开 O_WRONLY: 只写打开 O_RDWR : 读,写打开 这三个常量,必须指定一个且只能指定一个 O_CREAT : 若文件不存在,则创建它。需要使用mode选项,来指明新文件的访问权限 O_APPEND: 追加写 mode:文件被新创建,指定权限为mode
2.write
#include<unistd>
//将buf中的nbyte个字节写到fd对应的文件中
ssize_t write(fd,const void * buf,size_t nbyte);
//写入成功返回写入文档的bytes,失败返回-1
3.read
#include<unistd.h>
//读取fd对应文件中的count个字符,放到buf缓冲区中
ssize_t read(int fd, void * buf, size_t count);
//成功返回读取的字节数
//返回0 表示已经读到了文件末尾
//失败返回-1,并设置errno
4.close
#include<unistd.h>
int close(int fd);
//成功返回0,出错返回errno
当一个进程终止时,内核对该进程所有尚未关闭的文件描述符,调用close关闭,所以即使用户程序不调用close,在终止时内核也会自动关闭它打开的所有文件。但是对于一个长年累月运行的程序(比如网络服务器),打开的文件描述符一定要记得关闭,否则随着打开的文件越来越多,会占用大量文件描述符和系统资源
三、文件描述符fd
通过open函数,文件描述符就是一个整数
1. 0 & 1 & 2
- Linux进程默认情况下有3个缺省打开的文件描述符,标准输入0,标准输出1,标准错误2
- 0,1,2对应的物理设备一般是:键盘,显示器,显示器
文件描述符就是从0开始的整数。进程要读取文件,首先os创建进程pcb,从磁盘向内存中加载文件,这个过程创建struct_file,里面包含文件的各种属性。pcb中有一张表,存放文件描述符,表中存放struct_file指针,通过表中数组下标索引找到对应文件指针,进而访问文件。所以,本质上文件描述符就是该数据的下标,所以拿到了fd,就可以找到对应的文件。
2.文件描述符分配规则
在file_struct 数组中,找到当前没有被使用的最小的一个下标,作为新的文件描述符
3.重定向
我们之前使用 > >> < 等符号,将数据重定向指定文件中。
重定向的本质就是:比如我们要往显示器上打印文件,应该对应1号fd,现在修改打印到myfile中,myfile是三号文件,即修改fd就可以重定向
4.使用dup2系统调用
#include<unistd.h>
int dup2(int oldfd, int newfd);
oldfd指向a.txt,newfd指向b.txt,调用成功后,newfd和b.txt关闭,newfd指向a.txt(oldfd被保留)
四、FILE
IO相关函数与系统接口对应,并且库函数封装系统调用,本质上任何文件都是通过访问fd来访问的
C库中的FILE结构体内部必定封装了fd