目录
题目
通过父子进程完成对文件的拷贝(cp)
分析
- 文件长度获取: lseek
- 子进程定位到文件一半: lseek
- 父进程怎么准确读到文件一半的位置?
- fork之前打开文件,父子进程读写时,位置指针是同一个
思路
首先进行参数检查,如果命令行参数数量不是 3 个(程序名、源文件名、目标文件名),则输出错误提示信息并返回
-1
结束程序。打开源文件和目标文件:
- 使用
open
函数以只读模式打开源文件(argv[1]
),如果打开失败,输出错误信息并返回-1
。- 使用
open
函数以只写、创建新文件(如果不存在)、截断文件的模式打开目标文件(argv[2]
),并设置权限为0777
,如果打开失败,输出错误信息并返回-1
。计算源文件长度的一半:
- 使用
lseek
函数将文件指针移动到源文件末尾(第三个参数为2
),获取源文件的长度,然后将长度除以 2 得到源文件长度的一半,存储在len
变量中。创建子进程:
- 使用
fork
函数创建子进程,如果创建失败,输出错误信息并返回-1
。子进程执行的操作(拷贝后半段):
- 使用
lseek
函数将源文件指针和目标文件指针都定位到源文件长度一半的位置。- 进入循环,使用
read
函数从源文件读取内容到buf
中,每次最多读取 32 个字节,只要读取到的字节数n
大于 0,就使用write
函数将读取到的内容写入目标文件中,并且每次循环暂停 1 秒。父进程执行的操作(拷贝前半段):
- 使用
wait(NULL)
等待子进程执行完毕。- 将源文件指针和目标文件指针都定位到文件开头。
- 进入循环,根据剩余要读取的字符个数
len
来确定每次读取的字节数。如果len
大于 32,则读取 32 个字节;否则读取len
个字节。使用read
函数从源文件读取内容到buf
中,然后使用write
函数将读取到的内容写入目标文件中,同时更新剩余要读取的字符个数len
,每次循环暂停 1 秒。最后,关闭源文件和目标文件。
总的来说,这段代码的目的是将一个源文件的内容分两部分,由父进程和子进程分别拷贝前半段和后半段到一个目标文件中
代码
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(int argc, char const *argv[])
{
int fd1, fd2;
pid_t pid;
char buf[32] = "";
ssize_t n;
if (argc != 3)
{
printf("err: %s <srcfile> <destfile>\n", argv[0]);
return -1;
}
fd1 = open(argv[1], O_RDONLY);
if (fd1 < 0)
{
perror("fd1 err");
return -1;
}
fd2 = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0777);
if (fd2 < 0)
{
perror("fd2 err");
return -1;
}
//获取源文件长度的一半
off_t len = lseek(fd1, 0, 2) / 2;
//创建子进程
pid = fork();
if (pid < 0)
{
perror("fork err");
return -1;
}
else if (pid == 0) //拷贝后半段
{
//定位到一半的位置
lseek(fd1, len, 0);
lseek(fd2, len, 0);
//读源文件,写入目标文件
while ((n = read(fd1, buf, 32)) > 0)
{
write(fd2, buf, n);
sleep(1);
}
}
else //拷贝前半段
{
wait(NULL); //等子进程读写完父进程再拷贝
//定位到文件开头
lseek(fd1, 0, 0);
lseek(fd2, 0, 0);
//读源文件,写入目标文件
while (len > 0)
{
if (len > 32)
n = read(fd1, buf, 32);
else
n = read(fd1, buf, len);
write(fd2, buf, n);
len -= n; //len保存的是剩余要读的字符个数
sleep(1);
}
}
close(fd1);
close(fd2);
return 0;
}