Linux 文件系统调用 文件操作
Linux 文件系统调用 文件操作:
1
在Linux 中文件都以 二进制形式
文件操作:
windows:
c库函数: fopen fead fwrite fclose fseek
路径+文件名 模式
Linux中:路径+文件名 模式 权限
操作硬件需要 内核函数,内核态
文件操作头文件: #include<fcntl.h>
man open
O_APPEND:是一个原子操作,移动到末端,写数据。
#include<stdio.h>
#include<fcntl.h>//系统调用的 文件操作
#include<stdlib.h>
#include<unistd.h>
int main()
{
open("./a.txt",O_WRONLY);
//在当前路径下打开a.txt 权限为 只读:O_WRONLY
//如果不存在a.txt 不会创建a.txt 直接返回失败
open("./a.txt",O_WRONLY | O_CREAT,0600);
//如果 |上 O_CREAT就可以创建a.txt 并给上0600 权限
open("./a.txt",O_WRONLY | O_REONLY | O_CREAT,0600);
//可读 可写 不存在可创建
//fd 文件描述符 一个fd对应一个文件,文件关闭后,文件描述符归还给操作系统 fd>=0
//fd ==-1 文件打开失败
//标准输入stdin 0 标准输出stdout 1 标准错误stderr 2
close(fd);//关闭文件
exit(0);
}
2
#include<stdio.h>
#include<fcntl.h>//系统调用的 文件操作
#include<stdlib.h>
#include<unistd.h>
int main()
{
int fd = open("./a.txt",O_WRONLY |O_APPEND| O_CREAT,0600);
open("./a.txt",O_WRONLY);
//在当前路径下打开a.txt 权限为 只读:O_WRONLY
//如果不存在a.txt 不会创建a.txt 直接返回失败
open("./a.txt",O_WRONLY | O_CREAT,0600);
//如果 |上 O_CREAT就可以创建a.txt 并给上0600 权限
// open("./a.txt",O_WRONLY | O_REONLY | O_CREAT,0600);
//可读 可写 不存在可创建
fd 文件描述符 一个fd对应一个文件,文件关闭后,文件描述符归还给操作系统 fd>=0
//fd ==-1 文件打开失败
//标准输入stdin 0 标准输出stdout 1 标准错误stderr 2
close(fd);//关闭文件
exit(0);
}
将a.txt 内容拷贝到 b.txt:(cp命令实现 mycp命令)
#include<stdio.h>
#include<fcntl.h>//系统调用的 文件操作
#include<stdlib.h>
#include<unistd.h>
#include<assert.h>
//将a.txt 拷贝到 b.txt
int main()
{
char*s_name = "a.txt";
char*new_name = "b.txt";
int fdr = open(s_name,O_RDONLY);//文件存在
assert(fdr!=-1);
int fdw = open(new_name,O_WRONLY|O_CREAT,0600);//不存在,要创文件
assert(fdw!=-1);
//依次读取a.txt 写入 b.txt 大文件
char buff[128] = {0};
int num = 0;
while( (num=read(fdr,buff,128)) >0)// 注意: > 优先级大于 =
{
//num == 0 读取完成
write(fdw,buff,num);
}
close(fdr);
close(fdw);
exit(0);
}
找文件
find 大体路径 -name “文件名”
例:sudo find /etc/ -name “passwd”
//fd 文件描述符 一个fd对应一个文件,文件关闭后,文件描述符归还给操作系统 fd>=0
int fd = open(); + fork
先open 再fork()
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
#include<assert.h>
int main()
{
int fd = open("a.txt",O_RDONLY);//abcde
assert(fd!=-1);
pid_t pid = fork();
if(pid == 0)
{
char buff[10]={0};
read(fd,buff,1);
printf("son:buff=%s\n",buff);
sleep(1);
read(fd,buff,1);
printf("son:buff=%s\n",buff);
}
else
{
char buff[10]={0};
read(fd,buff,1);
printf("father:buff=%s\n",buff);
sleep(1);
read(fd,buff,1);
printf("father:buff=%s\n",buff);
}
close(fd);
exit(0);
}
结果:abcd
son:a father:b son:c father:d
PCB
**文件表:**存储在PCB
0 stdin
1 stdout
2 stderr
3 a.txt (struct file)
struct file:
打开方式
计数器(全局变量):几处地方引用a.txt
inode 节点号 (通过ls -i查看):节点唯一标识哪个文件 —>指a.txt
文件偏移量:pos=0
. . . . . .
使用fork()后 父子进程共同读取文件,每读一个,记录文件的结构体中的文件偏移量 +1 ,故不会将a 读两次。
close(fd); 一次计数器-1 计数器==0时 回收相关的信息
先open 再fork() a.txt 只打开了一次 close(fd)只管一次
先fork() 再open
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
#include<assert.h>
int main()
{
pid_t pid = fork();
assert(pid!=-1);
int fd = open("a.txt",O_RDONLY);//abcde
assert(fd!=-1);
if(pid == 0)
{
char buff[10]={0};
read(fd,buff,1);
printf("son:buff=%s\n",buff);
sleep(1);
read(fd,buff,1);
printf("son:buff=%s\n",buff);
}
else
{
char buff[10]={0};
read(fd,buff,1);
printf("father:buff=%s\n",buff);
sleep(1);
read(fd,buff,1);
printf("father:buff=%s\n",buff);
}
close(fd);
exit(0);
}
结果:abcd
son:a father:a son:b father:b
close(fd); 父子进程都要执行
额外:
printf(“a\n”);//放在缓冲区,\n刷新到屏幕上
printf();通过调用write 系统调用函数,为用户态->内核态切换过程
printf(“a\n”); == write(1,“a”,1);//write(1,“hello”,5); 直接将数据输入到屏幕,不经过缓冲区
int main()
{
printf("A");
write(1,"B",1);
fork();
exit(0);//此时刷新缓冲区
}
结果:BAA