IO学习系列之使用多进程复制同一个文件内容

  • 实例要求:
  • 使用多进程复制同一个文件内容;
  • 实例分析:
  • 1.创建一个父进程和一个子进程设置光标在指定文件中的偏移量,实现对同一个文件的复制。
  • 2.比如:可以指定子进程复制文件内容的前一半,而父进程复制文件内容的后一半
  • 3.根据时间片轮询法则,最终父进程和子进程可以把同一个文件复制成功。
  • 相关的文件IO接口函数如下:
  • open函数:
#include 

#include 

#include 

int open(const char *pathname, int flags, mode_t mode);
/*
功能:

	使用文件IO打开一个文件

参数:

	pathname:文件的路径和名字

 	flag:

 	O_RDONLY	只读方式打开文件

	O_WRONLY	只写方式打开文件

	O_RDWR		读写方式打开文件

	O_APPEND	以追加的模式打开文件

	O_CREAT		创建文件  需要使用第三个参数 mode

		给mode传参最大能传 0666
		文件最终的权限还与umask掩码有关 umask默认是 0002
		也可以使用 umask 0666 等修改 一般我们都使用默认值
		(mode & ~umask)
		我们创建的普通文件,最高的权限是 0666
		0666 & ~0002 == 0664
		文件最终的权限 = (mode & ~umask)

 	O_EXCL		需要和O_CREAT配合使用,如果文件不存在则新建,

                                	如果存在则报错 错误码EEXIST

	O_TRUNC		清空文件

	mode:
			如果第二个参数指定了O_CREAT 

                               		则需要使用第三个参数mode来指定文件访问模式

			如果第二个参数没有 O_CREAT 则第三个参数可以不写

			用八进制表示
			
	返回值:
	
			成功  文件描述符

			失败  -1  重置错误码
*/
  • close函数:
#include 

int close(int fd);
/*
功能:

	关闭一个文件

参数:

	fd 文件描述符

返回值:   

	成功 0 

	失败 -1 重置错误码
*/
  • read函数:
#include 

ssize_t read(int fd, void *buf, size_t count);
/*
功能:

   	尝试从文件fd中读取count个字节到buf中

参数:

	fd:	文件描述符

	buf:	用来存储读取内从的缓冲区的首地址

	count:	想要读取的字节数
	
返回值:

	成功  	实际读取的字节数,读到文件结尾会返回0

	失败  	-1  重置错误码
*/
  • write函数:
#include 

ssize_t write(int fd, const void *buf, size_t count);

/*
功能:

	尝试把buf中的内容写count个到文件fd中

参数:

	fd:	文件描述符

	buf:	要写入的数据的首地址

	count:	想要写入的字节数
	
返回值:

	成功  	实际写入的字节数 (如果返回0 表示没有写入内容)

	失败  	-1  重置错误码
*/
  • lseek函数:
#include 

#include 

off_t lseek(int fd, off_t offset, int whence);
/*
功能:

    设置光标的位置

参数:

	fd:文件描述符

	offset:偏移量

	>0  向后偏移

	0  不偏移

	<0  向前偏移

whence:

 	SEEK_SET  相对于文件开头

	SEEK_CUR  相对于当前位置

 	SEEK_END  相对于文件结尾
 	
返回值:

	成功  返回光标距离文件开头的偏移量

  	失败  -1  重置错误码 
*/
  • fork函数:
#include 

#include 

pid_t fork(void);
/*
功能:

	拷贝父进程,产生子进程

参数:

	无
	
返回值:

	成功 	给子进程(即返回值等于0)返回0或者给父进程(即返回值大于0)返回子进程的pid

	失败 	-1 	重置错误码,不会创建子进程  
*/
//注意:在不关心返回值的情况下n次fork会产生2^n个进程 
  • 示例代码:
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

//获取源文件的大小(字节)
//创建目标文件
int get_src_file_size_and_create_dest_file(const char *src_file,const char *dest_file);

//复制源文件内容到目标文件内容中
void cp_src_file_to_dest_file(const char *src_file,const char *dest_file,int offset,int size);


int main(int argc, char const *argv[])
{
    if(3 != argc)
    {
        printf("Usage : %s src_file dest_file\n",argv[0]);
        return -1;
    }

    int size = 0;

    size = get_src_file_size_and_create_dest_file(argv[1],argv[2]);

    //创建进程
    pid_t pid = 0;
    if(-1 == (pid = fork()))
    {
        perror("fork error");
        return -1;
    }else if(0 == pid){ //子进程

        cp_src_file_to_dest_file(argv[1],argv[2],0,size/2);

    }else if(0 < pid){  //父进程
        
        cp_src_file_to_dest_file(argv[1],argv[2],size/2,size - size/2);
    }
    
    return 0;
}

int get_src_file_size_and_create_dest_file(const char *src_file,const char *dest_file)
{
    //获取源文件的大小(字节)
    int src_fd = open(src_file,O_RDONLY);

    if(-1 == src_fd)
    {
        perror("open error");
        return -1;
    }

    int size = lseek(src_fd,0,SEEK_END);

    //创建目标文件

    int dest_fd = open(dest_file,O_WRONLY | O_CREAT | O_TRUNC,0666);

    if(-1 == dest_fd)
    {
        perror("open error");
        return -1;
    }

    return size;

}

void cp_src_file_to_dest_file(const char *src_file,const char *dest_file,int offset,int size)
{
    int src_fd = 0;

    int dest_fd = 0;

    //打开源文件
    if(-1 == (src_fd = open(src_file,O_RDONLY)))
    {
        perror("open error");
        exit(-1);
    }
    //打开目标文件
    if(-1 == (dest_fd = open(dest_file,O_WRONLY)))
    {
        perror("open error");
        exit(-1);
    }

    //定位光标
    lseek(src_fd,offset,SEEK_SET);

    lseek(dest_fd,offset,SEEK_SET);

    int ret = 0;
    int num = 0;
    char buf[64] = {0};

    while (true)
    {
        ret = read(src_fd,buf,sizeof(buf));

        if(0 == ret)
        {
            break;
        }

        num += ret;

        if(num > size)
        {
            write(dest_fd,buf,size - (num - ret));
            break;
        }

        write(dest_fd,buf,ret);
       
    }
    //关闭文件
    close(src_fd);

    close(dest_fd);
    

}



  • 运行结果:
linux@ubuntu:~$ gcc proc2.c 
linux@ubuntu:~$ ./a.out k1.c k2.c
linux@ubuntu:~$ diff k1.c k2.c 
linux@ubuntu:~$
  • 本示例代码,仅供参考

你可能感兴趣的:(学习,Linux,算法,c语言,多进程)