【操作文件的系统调用】
创始人
2024-02-01 17:00:47
0

目录

  • 文件操作系统调用的基本库函数
    • 打开文件
    • 读取文件
    • 写入文件
    • 关闭文件
  • 应用
    • 文件操作代码举例
    • 文件操作与进程复制的结合
      • 先打开文件再复制进程
      • 先进程复制,再进行打开文件
    • 缓冲区的知识回顾

在上一篇讲述僵尸进程的文章中对文件的系统调用做了一点点的代码讲述,这篇文章对操作文件的系统调用进行细节讲述。

文件操作系统调用的基本库函数

打开文件

打开一个已存在的文件:int open(const char* pathname, int flags);
新建一个文件,并设置访问权限:int open(const char* pathname, int flags,mode_t mode);

  • pathname:要打开的文件的路径和文件名
  • flags:打开标志,即:
参数适应情况
O_WRONLY只写打开
O_RDONLY只读打开
O_RDWR读写方式打开
O_CREAT文件不存在则创建
O_APPEND文件末尾追加
O_TRUNC清空文件,重新输入
  • mode:权限(0600读写权限)
  • 返回值:文件描述符(fd)

读取文件

读取文件: ssize_t read(int fd, void* buf, size_t count);

  • fd:对应打开的文件描述符
  • buf:存放数据的容器
  • count:计划一次从文件中读取字节的个数
  • 返回值 :实际读到的字节数

写入文件

写入文件:ssize_t write(int fd, const void* buf,size_t count);

  • fd:对应打开文件的描述符
  • buf:待写入的数据
  • count:计划一次向文件中写入多少数据

关闭文件

关闭文件:int close(int fd)

  • fd:文件描述符

应用

文件操作代码举例

我们通过编写一个自己的拷贝文件来运用一下刚刚库函数
如下代码,将etc下的passwd文件拷贝到当前目录下:

#include
#include
#include
#include
#include
int main(int argc,char* argv[]){
char* s_name=argv[1];
char* new_name=argv[2];
int fdr=open(s_name,O_RDONLY);
assert(fdr!=-1);
int fdw=open(new_name,O_WRONLY|O_CREAT,0600);
assert(fdw!=-1);
char buff[128]={0};
int num=0;
while(num=read(fdr,buff,128)){write(fdw,buff,num);
}
close(fdr);
close(fdw);
return 0;
}

在该文件中用了main函数的参数,main函数参数中argc为参数个数,argv[]为参数内容,因为第一个参数是参数个数本身,所以应用时从第二个参数开始使用,我们在执行main程序时,编译后执行用的是./main命令,可以通过./main后直接加入参数来对参数进行赋值。如下图:在这里插入图片描述
此处要想和cp命令一样使用,只需要将该程序重命名为mycp,然后将编译后的文件移动到/bin路径下即可。(用到的命令:mv ./main.c mycp.c ,gcc -o mtco mycp.c ,sudomv ./mycp /bin)
在这里移动了之后我们如何判断是否移动过去了呢,就需要我们查找这个文件:

  • 查找命令:sudo find /etc/ -name “mycp”
  • 管道过滤:ls /etc | grep “mycp”(这里可以不需要全名,查找需要全名)

文件操作与进程复制的结合

此处我们复习一下僵尸进程:子进程先于父进程结束,且未获取退出码,子进程处于僵死状态。defunct
解决方法:waut,
父进程wait获取子进程退出码,wait(NULL),获取子进程推出码,不用退出码

先打开文件再复制进程

我们看下面程序猜想输出结果是什么?此处b.txt中内容为abcde
在这里插入图片描述
输出结果为:在这里插入图片描述
为什么会这样输出呢,我们要从内存进行分析,看下图在这里插入图片描述
在进程的PCB中有一个文件表,就是上图中带有标号0123的,然后调用文件时,实际上用了文件结构体,结构体图中又展示,结构体中又打开文件当时,计数器,节点号,文件偏移量等变量,因为上代码是先打开文件再进行进程复制,所以拷贝了父进程的PCB(PID不同),把相同的文件表复制了一份,所以操作文件的编号都一样,为此操作就在同一个文件的结构上操作,读取文件时,文件偏移量+1,通过偏移量结点号和偏移量找到输出内容,所以才会导致输出不会刷新,输出abcd。此处也只需要close一次,因为公用一个文件。
在这里插入图片描述

先进程复制,再进行打开文件

如下图,此处底下代码同上,不做展示,求输出结果:
在这里插入图片描述
在这里插入图片描述

因为是先复制进程,再输出,所以此是上图,复制进程时PCB中文件表还没有文件的结构体,所以是不同进程调用了不同的结构体,所以两个进程分开,通过不同的结构体在同一文件中找到输出内容。关闭文件时自然也需要关闭两次,此处的计数器是全局变量,所以要计数器的值为2,子进程父进程各close一次,就会计数器减一,等到计数器等于0时就会文件关闭。

缓冲区的知识回顾

write(1,“B”,1);:直接将数据输出屏幕,不经过缓冲区

int main(){
printf("A");
write(1,"B",1);
fork();
exit(0);
}

输出结果为BAA,此处因为进程复制时复制了缓冲区中的一个A,所以是BAA。

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
一帆风顺二龙腾飞三阳开泰祝福语... 本篇文章极速百科给大家谈谈一帆风顺二龙腾飞三阳开泰祝福语,以及一帆风顺二龙腾飞三阳开泰祝福语结婚对应...
美团联名卡审核成功待激活(美团... 今天百科达人给各位分享美团联名卡审核成功待激活的知识,其中也会对美团联名卡审核未通过进行解释,如果能...