【操作文件的系统调用】


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

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

打开文件

打开一个已存在的文件: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<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<fcntl.h>
#include<assert.h>
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。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

*闲鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值