1. 基本含义辨析
文件操作的系统调用 open read write close (系统调用:实现在内核中【用户态->内核态】—“陷入内核”)
man: 1 命令 2 系统调用 3 库函数
C操作文件的库函数 fopen fread fwrite fclose (fopen库函数的执行底层是调用系统调用open();printf()库函数底层是调用write()系统调用实现的)
(1)open()
若文件存在:open() //文件名,打开方式:r,w
若文件不存在:open() //文件名,打开方式:r,w|creat,设置文件权限
(2)write()
参数:文件描述符(fd)、写入的数据、数据长度。 返回值:实际写入的数据长度。
(3)read()
参数:文件描述符、要读入到的缓冲区、读多少个。 返回值:读到的数据长度。
当read()返回值为0时代表读到文件末尾。(会多读一次,最后一次返回值0代表到达文件末尾)
2. 实际应用
(1)直接使用
(2)实现对任意文件的cp拷贝功能(输入源文件名和目的文件名)
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
//read返回值==0~读到末尾
int main(int argc, char* argv[])
{
if(argc!=3)//argv[0]=./mycp argv[1]=源文件名 argv[2]=目的文件名
{
printf("argc err\n");
exit(1);
}
char *s_name = argv[1];
char *s_newname=argv[2];
int fd1=open(s_name,O_RDONLY);
if(fd1==-1)
{
printf("File:%s not exist\n",s_name);
exit(1);
}
int fd2=open(s_newname,O_WRONLY|O_CREAT,0600);
if(fd2==-1)
{
printf("Cerate File:%s error\n", s_newname);
exit(1);
}
char buff[128] = {0};
int num = 0;
while ((num=read(fd1,buff,128))>0)
{
write(fd2, buff, num);//由于不确定每次读128个,所以每次写入读到的num个
}
close(fd1);
close(fd2);
exit(0);
}
(3)fork复制文件描述符~共享读同一文件
先open再fork:父子进程共享文件偏移量;先fork后open:文件偏移量不共享。
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
int main()
{
int fd = open("a.txt", O_RDONLY);
if(fd==-1)
{
printf("open file error\n");
exit(1);
}
//fork
pid_t pid = fork();
if(pid==-1)
{
printf("fork error\n");
exit(1);
}
if(pid==0)//child 先open再fork:父子进程共享文件偏移量;先fork后open:文件偏移量不共享
{
char buff[32] = {0};
read(fd, buff, 1);
printf("child buff=%s\n", buff);
sleep(1);
read(fd, buff, 1);
printf("child buff=%s\n", buff);
}
else//parent
{
char buff[32] = {0};
read(fd, buff, 1);
printf("parent buff=%s\n", buff);
sleep(1);
read(fd, buff, 1);
printf("parent buff=%s\n", buff);
}
close(fd);
exit(0);
}
对于a.txt(内容为abcdefg),运行结果为:
3. 任何一个进程开启运行,便会自动打开三个文件。
(1)stdin 标准输入 FILE* 文件描述符fd=0
(2)stdout 标准输出 FILE* 文件描述符fd=1 当printf的打印缓冲区中数据攒够后便由用户态->内核态交给write()处理输出。
(3)stderr 标准错误输出 FILE* 文件描述符fd=2
对于PCB中的内容之一:文件表(实质是结构体)