Linux学习之----多进程复制文件小练习

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <math.h>
#include <iostream>
#include <string.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/wait.h>

using namespace std;

int string2Int(const char *s)
{
	int ret = 0;

	if (s != NULL)
	{
		unsigned int len = strlen(s);

		for (int i = len - 1; i >= 0; i--)
		{
			int v = s[i] - '0';

			if ((0 <= v) && (v <= 9))
			{
				ret += (pow(10, len - i - 1) * v);
			}
			else
			{
				return -1;
			}
		}
	}

	return ret;
}

//格式 ./程序名  要复制的文件  复制到哪个文件  要开启的进程数

int main(int argc, const char *argv[])
{
	int ret = 0;

	if (argc < 2)
	{
		dprintf(STDOUT_FILENO, "%s : Paramter count must be more than two ...", argv[0]);
		exit(1);
	}

	int pro_count = string2Int(argv[3]);

	if (pro_count == -1)
	{
		printf("%s : Process count must be more than 0 ...", argv[0]);
		exit(1);
	}

	int fd_r = open(argv[1], O_RDWR | O_CREAT, 0644);
	int fd_w = open(argv[2], O_RDWR | O_CREAT, 0644);

	if ((fd_r == -1) || (fd_w == -1))
	{
		perror("open ");
		exit(1);
	}

	int file_size = lseek(fd_r, 0, SEEK_END);
	ret = ftruncate(fd_w,file_size);

	if(ret == -1)
	{
		perror("ftruncate error ");
		close(fd_r);
		close(fd_w);
		exit(1);
	}

	char *p = reinterpret_cast<char*>(mmap(NULL, file_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_r, 0));

	if (p == MAP_FAILED)
	{
		perror("mmap error ");
		close(fd_r);
		close(fd_w);
		exit(1);
	}

	ret = read(fd_r, p, file_size);

	if (ret == -1)
	{
		perror("read error ");
		close(fd_r);
		close(fd_w);
		ret = munmap(p, file_size);

		if (ret == -1)
		{
			perror("munmap error ");
		}

		exit(1);
	}

	//单个进程读多少个字节,最后一个进程把剩下的读完
	int single_read_count = static_cast<int>(1.0 * file_size / pro_count);
	//从哪里开始读写
	char* rw_pos = p;
	//该进程负责读写多少字节
	int rw_count = single_read_count;

	int flag = 0;
	for(flag = 0;flag < pro_count - 1;flag++)
	{
		ret = fork();

		if(ret == 0)
		{
			//子进程
			rw_pos = p + (flag + 1) * single_read_count;

			if((flag + 1) == (pro_count - 1))
			{
				//是最后一个进程
				rw_count = file_size - (single_read_count * (pro_count - 1));
			}

			flag++;
    
			break;
		}
		else
		{
			//是父进程
			if((flag + 1) == (pro_count - 1))
			{
				flag = 0;
				break;
			}
		}
	}

	printf("flag = %d , rw_pos = %p , rw_count = %d \n",flag,rw_pos,rw_count);

	lseek(fd_w,rw_pos - p,SEEK_SET);
	write(fd_w,rw_pos,rw_count);

	close(fd_r);
	close(fd_w);

	ret = munmap(p, file_size);

	if (ret == -1)
	{
		perror("munmap error ");
		exit(1);
	}

	//父进程,要回收子进程
	if(flag == 0)
	{
		sleep(2);
		int i = 0;
		while(wait(NULL) != -1)
		{
			printf("父进程回收了一个子进程,i = %d\n",i++);
		}
	}

	return ret;
}

测试如图:

在这里插入图片描述

发布了16 篇原创文章 · 获赞 1 · 访问量 1119

猜你喜欢

转载自blog.csdn.net/u012321968/article/details/104659842