转自:https://www.cnblogs.com/zxl0715/articles/5365989.html

  1. 、具体思路
  2. 把一个文件分成N份,分别用N个线程copy
  3. 每个线程只读取指定长度字节大小的内容
  4. 最后一个线程的源文件所指定的结束位置是文件的实际大小
  5. 每个线程读取指定源文件部分的起始位置和结束位置的内容到缓冲区
  6. 每个线程将缓存中的内容写入目的文件的指定开始位置和结束位置
  7. 主线程必须等到所有线程copy完成后才能退出
  8.  
  9. .有关文件操作的函数
  10. 2.1. 文件的打开和关闭
  11. 2.1. open()函数
  12. open()函数的作用是打开文件, 其调用格式为:
  13. int open(char *filename, int access);
  14. 该函数表示按access的要求打开名为filename的文件,
  15. 返回值为文件描述字
  16. open()函数打开成功, 返回值就是文件描述字的值(非负值), 否则返回-。
  17. 2.1. close()函数
  18. close()函数的作用是关闭由open()函数打开的文件, 其调用格式为:
  19. int close(int handle);
  20. 该函数关闭文件描述字handle相连的文件。
  21. 2.2.读写函数
  22. 2.2. read()函数
  23. read()函数的调用格式为:
  24. int read(int handle, void *buf, int count);
  25. read()函数从handle(文件描述字)相连的文件中, 读取count个字节放到buf所指的缓冲区中,
  26. 返回值为实际所读字节数, 返回-1表示出错。返回0 表示文件结束。
  27.  
  28. 2.2. write()函数
  29. write()函数的调用格式为:
  30. int write(int handle, void *buf, int count);
  31.  
  32. write()函数把count个字节从buf指向的缓冲区写入与handle相连的文件中,
  33. 返回值为实际写入的字节数
  34. 2.3.随机定位函数
  35. lseek()函数
  36. lseek()函数的调用格式为:
  37. int lseek(int handle, long offset, int fromwhere);
  38. 该函数对与handle相连的文件位置指针进行定位, 功能和用法与fseek() 函数相同。
  39.  
  40. .源文件(copyfn.c
  41. 源文件在ubuntu10.04下编译通过
  42.  
  43. #include <stdio.h>
  44. #include <unistd.h>
  45. #include <stdlib.h>
  46. #include <string.h>
  47. #include <errno.h>
  48. #include <pthread.h>
  49. #include <dirent.h>
  50. #include <fcntl.h>
  51. #include <sys/types.h>
  52. #include <sys/stat.h>
  53. #include <sys/time.h>
  54.  
  55. #define THREADS_COUNT 3
  56. #define THREADS_BUFF_SIZE 1*1024
  57. struct thread_block
  58. {
  59. int infd; ///源文件句柄
  60. int outfd;//目的文件句柄
  61. size_t start;///文件的写入起始位置
  62. size_t end; ///文件写入的终止位置
  63. };
  64.  
  65. void usage()
  66. {
  67. printf("copy %%src %%dst\n");
  68. }
  69. ///获取文件大小
  70. size_t get_filesize(int fd)
  71. {
  72. struct stat st;
  73. fstat(fd,&st);
  74. return st.st_size;
  75. }
  76. void *thread_copy_fn(void *arg);
  77. int main(int argc,char *argv[])
  78. {
  79. if(argc < )
  80. {
  81. usage();
  82. return -;
  83. }
  84. ///打开文件
  85. int infd = open(argv[],O_RDONLY);
  86. int outfd = open(argv[],O_CREAT|O_WRONLY,);
  87. // 0644也就是-文件所有者有读写权限,组有读权限,其他用户有读权限
  88. if(infd == -|| - ==outfd)
  89. {
  90. printf("error while open file \n");
  91. return -;
  92. }
  93. size_t file_size = get_filesize(infd);
  94.  
  95. size_t thread_size = THREADS_COUNT;
  96. struct thread_block *blocks = (struct thread_block *)
  97. malloc(sizeof(struct thread_block )* thread_size);
  98. size_t percent = file_size / thread_size;
  99. printf("filesize = %d\t percent_blocks = %d\n",\
  100. file_size,percent);
  101. int i = ;
  102. //init-thread-block
  103. for(; i < thread_size;++i)
  104. {
  105. blocks[i].infd = infd;
  106. blocks[i].outfd = outfd;
  107. blocks[i].start = i * percent;
  108. blocks[i].end = blocks[i].start + percent;
  109. }
  110. //the last thread
  111. blocks[i].end = file_size;
  112. pthread_t ptid[thread_size];
  113. ///创建线程
  114. for(i = ; i < thread_size; ++i)
  115. {
  116. pthread_create(&ptid[i],NULL,thread_copy_fn,&(blocks[i]));
  117. }
  118. ///线程Join
  119. for(i = ; i < thread_size; ++i)
  120. {
  121. pthread_join(ptid[i],NULL);
  122. }
  123. ///释放资源
  124. free(blocks);
  125. close(infd);
  126. close(outfd);
  127. printf("Copy Successfully \n");
  128. return ;
  129. }
  130.  
  131. void *thread_copy_fn(void *arg)
  132. {
  133. struct thread_block *block = (struct thread_block *)arg;
  134. char buf[THREADS_BUFF_SIZE];
  135. int ret;
  136. size_t count = block->start;
  137.  
  138. printf("In Thread\t%ld\nstart = %ld\t end = %ld\n",\
  139. pthread_self(),block->start,block->end);
  140.  
  141. ///lseek到同样的位置
  142. ret = lseek(block->infd,block->start,SEEK_SET);
  143. ret = lseek(block->outfd,block->start,SEEK_SET);
  144. int bytes_read;
  145. int bytes_write;
  146. while(count < block->end)
  147. {
  148. bytes_read = read(block->infd,buf,sizeof(buf));
  149. if(bytes_read >)
  150. {
  151. printf("thread = %ld\t read = %ld\t count %d\n",\
  152. pthread_self(),bytes_read,count);
  153. count += bytes_read;
  154.  
  155. //read()返回-1,同时errno为EINTR,表示读的过程中遇到了中断
  156. if((bytes_read == -)&&(errno !=EINTR))
  157. break;
  158. char *ptr_write = buf;
  159. while((bytes_write = write(block->outfd,ptr_write,bytes_read))!=)
  160. {
  161. //write()会返回-1,同时errno为EINTR,表示在写的过程中遇到了中断
  162. if((bytes_write == -)&&(errno!=EINTR))
  163. break;
  164. if(bytes_write == bytes_read)
  165. break;
  166. else if(bytes_write > )
  167. {
  168. ptr_write += bytes_write;
  169. bytes_read -= bytes_write;
  170. }
  171. printf("thread = %ld\t write = %ld\t read %d\n",\
  172. pthread_self(),bytes_write,bytes_read);
  173. }//end-write;
  174. ///error while write
  175. if(bytes_write == -)
  176. break;
  177.  
  178. }
  179. }
  180. printf("#####Thread exit %ld#####\n",pthread_self());
  181. pthread_exit(NULL);
  182. }
  183. 本文欢迎转载,转载请注明作者与出处

linux下c语言实现多线程文件复制【转】的更多相关文章

  1. linux 下C语言编程库文件处理与Makefile编写

    做开发快3年了,在linux下编译安装软件算是家常便饭了.就拿gcc来说,都有不下10次了,可基本每次都会碰到些奇奇怪怪的问题.看来还是像vs.codeblocks这样的ide把人弄蠢了.便下定决心一 ...

  2. linux下C语言实现多线程通信—环形缓冲区,可用于生产者(producer)/消费者(consumer)【转】

    转自:http://blog.chinaunix.net/uid-28458801-id-4262445.html 操作系统:ubuntu10.04 前言:     在嵌入式开发中,只要是带操作系统的 ...

  3. linux下c语言的多线程编程

    我们在写linux的服务的时候,经常会用到linux的多线程技术以提高程序性能 多线程的一些小知识: 一个应用程序可以启动若干个线程. 线程(Lightweight Process,LWP),是程序执 ...

  4. Linux下c语言TCP多线程聊天室

    开发环境:Linux,GCC 相关知识:TCP(博客:传送门),线程 附加:项目可能还有写不足之处,有些bug没调出来(如:对在线人数的控制),希望大佬赐教. 那么话不多说,放码过来: 码云:传送门, ...

  5. linux下C语言多线程编程实例

    用一个实例.来学习linux下C语言多线程编程实例. 代码目的:通过创建两个线程来实现对一个数的递加.代码: //包含的头文件 #include <pthread.h> #include ...

  6. LINUX下C语言编程调用函数、链接头文件以及库文件

    LINUX下C语言编程经常需要链接其他函数,而其他函数一般都放在另外.c文件中,或者打包放在一个库文件里面,我需要在main函数中调用这些函数,主要有如下几种方法: 1.当需要调用函数的个数比较少时, ...

  7. Windows10下配置Linux下C语言开发环境

    今天为大家介绍如在Windows10下配置Linux下C语言开发环境,首先安装linux子系统:启用开发者模式 1.打开设置 2.点击更新和安全3.点击开发者选项 4.启用开发人员模式 5.更改系统功 ...

  8. linux 下C语言学习路线

    UNIX/Linux下C语言的学习路线.一.工具篇“公欲善其事,必先利其器”.编程是一门实践性很强的工作,在你以后的学习或工作中,你将常常会与以下工具打交道, 下面列出学习C语言编程常常用到的软件和工 ...

  9. Linux下C语言编程实现spwd函数

    Linux下C语言编程实现spwd函数 介绍 spwd函数 功能:显示当前目录路径 实现:通过编译执行该代码,可在终端中输出当前路径 代码实现 代码链接 代码托管链接:spwd.c 所需结构体.函数. ...

随机推荐

  1. webstorm的git操作使用

    0. 前言 在上一篇文章中,讲述了使用webstorm去调试node程序,最近研究了一下如何使用webstorm去操作git. 对于git的使用,大家的使用方式均有不同,最王道的方式非命令行莫属,基于 ...

  2. vue操作select获取option值

    如何实时的获取你选中的值 只用@change件事 @change="changeProduct($event)" 动态传递参数 vue操作select获取option的ID值 如果 ...

  3. 【BZOJ1443】[JSOI2009]游戏Game(二分图+博弈)

    BZOJ 题意: 给出一个\(n*m\)的网格,其中有一些障碍点. 现在两个人玩游戏,首先先手选定一个点,然后从后手开始轮流移动,不能移动者即输掉这次游戏. 规定不能移动到那些之前已经到过的格子上. ...

  4. 初学JavaScript正则表达式(六)

    JavaScript预定义类 ab+数字+任意字符 ab[0-9][^\r\n] 等价于 ab\d. '@123@abc@'.replace(/@./g,'Q') Q23Qbc@ 将"@加任 ...

  5. apache配置文件详解(中英文对照版)

    # This is the main Apache server configuration file. It contains the # configuration directives that ...

  6. day71_10_16多表断关联

    ---恢复内容开始--- 本次环境: 配置settings INSTALLED_APPS = [ # ... 'rest_framework', ] DATABASES = { 'default': ...

  7. Log日志级别从高到低排序 ERROR、WARN、INFO、DEBUG

    Log4j建议只使用四个级别,优先级从高到低分别是 ERROR.WARN.INFO.DEBUG.通过在这里定义的级别,您可以控制到应用程序中相应级别的日志信息的开关.比如在这里定义了INFO级别,则应 ...

  8. 剑指Offer-13.调整数组顺序使奇数位于偶数前面(C++/Java)

    题目: 输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变. 分析: 这道题做法有很 ...

  9. Python网络编程基础 ❸ struct模块 基于upd的socket服务

    struct模块 基于upd的socket服务

  10. <Array> 277 243 244 245

    277. Find the Celebrity knows(i, j): By comparing a pair(i, j), we are able to discard one of them 1 ...