Linux--多线程拷贝文件案例及其传参说明
来源:互联网 发布:linux服务器优点 编辑:程序博客网 时间:2024/06/05 21:54
下面的简单案例模拟了多线程拷贝一个文件
#include <stdio.h>#include <unistd.h>#include <string.h>#include <stdlib.h>#include <fcntl.h>#include <assert.h>#include <sys/stat.h>#include <sys/types.h>#include <pthread.h>#define MAX_PATH 255#define BLOCK_SIZE 4096typedef struct {int srcFd;int dstFd;int start;int end;}thread_info;int copy(const char *src, const char *dst, int threads);void *run(void *arg);pthread_t *tid = NULL;thread_info *tinfo = NULL;int main(int argc, char *argv[]){if (argc != 4){printf("usage: %s src dst sum_of_thread\n", argv[0]);return -1;}char src[MAX_PATH] = {0};char dst[MAX_PATH] = {0};int threads;memcpy(src, argv[1], strlen(argv[1]));memcpy(dst, argv[2], strlen(argv[1]));threads = atoi(argv[3]);if (threads <= 0){threads = 1;}struct stat srcInfo;struct stat dstInfo;if (stat(src, &srcInfo) < 0){perror("main: stat src");return -1;}if (srcInfo.st_mode & S_IFDIR){printf("the src must be file\n");return -1;}if (access(dst, F_OK) == 0){if (stat(dst, &dstInfo) < 0){perror("main: stat dst");return -1;}if (!(dstInfo.st_mode & S_IFDIR)){unlink(dst);}}int fd = open(dst, O_CREAT | O_EXCL, 0644);if (fd < 0){perror("main: open dst");return -1;}tid = (pthread_t *)malloc(threads * sizeof(pthread_t));if (tid == NULL){printf("main: malloc pthread");return -1;}tinfo = (thread_info *)malloc(threads * sizeof(thread_info));if (tinfo == NULL){printf("main: malloc thread_info");return -1;}copy(src, dst, threads);int i = 0;for (; i < threads; ++i){pthread_join(tid[i], NULL);} free(tid);free(tinfo);return 0;}int copy(const char *src, const char *dst, int threads){assert(src != NULL);assert(dst != NULL);int srcFd = open(src, O_RDWR);if (srcFd < 0){perror("copy: open src");return -1;}int dstFd = open(dst, O_RDWR);if (dstFd < 0){perror("copy: open dst");return -1;}struct stat srcInfo;if (stat(src, &srcInfo) < 0){perror("copy: stat src");return -1;}off_t size = srcInfo.st_size;lseek(dstFd, size, SEEK_SET);write(dstFd, '\0', 1);int i = 0;for(; i < threads; ++i){//printf("i=%d\n", i);int start = i * (size/threads);int end = 0;if (i == threads - 1){end = size;}else{end = (i+1) * (size/threads);}tinfo[i].srcFd = srcFd;tinfo[i].dstFd = dstFd;tinfo[i].start = start;tinfo[i].end = end;//printf("begin-info: src_fd(%d), dst_fd(%d), start(%d), end(%d)\n", tinfo[i].srcFd, tinfo[i].dstFd, tinfo[i].start, tinfo[i].end);pthread_create(&tid[i], NULL, run, (void *)&tinfo[i]);}}void *run(void *arg){thread_info tinfo = *(thread_info *)arg;//printf("info: src_fd(%d), dst_fd(%d), start(%d), end(%d)\n", tinfo.srcFd, tinfo.dstFd, tinfo.start, tinfo.end);if (lseek(tinfo.srcFd, tinfo.start, SEEK_SET) < 0){perror("run: lseek src");pthread_exit((void *)-1);}if (lseek(tinfo.dstFd, tinfo.start, SEEK_SET) < 0){perror("run: lseek dst");pthread_exit((void *)-1);}int length = tinfo.end - tinfo.start;int size = 0;char line[BLOCK_SIZE] = {0};int readSize = 0;do{if (length > 0 && length <= BLOCK_SIZE){readSize = length;}else if (length > 0 && length > BLOCK_SIZE){readSize = BLOCK_SIZE;}else{break;}size = read(tinfo.srcFd, line, readSize);write(tinfo.dstFd, line, size);length -= size;memset(line, 0x0, sizeof(line));}while(1);return (void *)0;}
*其中需要注意的是,对于多线程的传参问题。之前很多案例上都是在main函数中调用pthread_create,然后传递一个参数给线程主函数。这样几乎不会出现问题,能够出现问题的情况是,对于以下案例,将pthread_create在另一个函数中调用,传递参数的问题
#include <stdio.h>#include <unistd.h>#include <string.h>#include <stdlib.h>#include <pthread.h>int start = 1000;void *run(void *arg){int start = *(int *)arg;printf("start = %d\n", start);}void startThread(pthread_t *tid){int state = 200;//pthread_create(tid, NULL, run, (void *)&start);pthread_create(tid, NULL, run, (void *)&state);}int main(){pthread_t tid;startThread(&tid);//pthread_join(tid, NULL);sleep(3);return 0;}
在run中打印start得到的是一个0值。在前后打印出地址,发现地址没有改变,值却变了。经过摸索,得到的结论是,在startThread函数中,当调用pthread_create之后整个函数返回,相当于函数的堆栈解旋了。那时候的局部变量state被覆盖,显而易见地址是不变的。当调用run函数时候,run函数的堆栈段是一个新的地址空间,或许就是覆盖了startThread函数的。
那么,如果我想在线程函数中传递参数,可以使用以下三类:
1. 全局变量,静态变量
2. 简单的传值(这里的传值指在run函数中能够不需要间接引用就能获取的)
3. 堆数据(malloc,new)
0 0
- Linux--多线程拷贝文件案例及其传参说明
- linux 多线程拷贝文件
- 多线程实现文件拷贝(Linux下C++)
- 多线程拷贝文件
- 多线程拷贝文件
- 多线程拷贝文件
- 多线程实现文件拷贝
- 利用多线程拷贝文件
- 6.多线程文件拷贝
- 多线程拷贝文件
- 多线程文件拷贝
- 多线程断点文件拷贝
- 多线程实现文件拷贝
- Linux 中/etc/inittab文件的字段及其说明
- linux /etc/inittab文件的字段解释及其说明
- C# 多线程目录拷贝 文件拷贝
- 多线程文件拷贝整体架构
- 多线程处理文件(拷贝)
- 今日头条 面试题一例
- angular中controller在不同场景下的状态
- 掩码学习笔记(不断更新)
- Spark学习笔记(一)
- perl unload oracle gbk
- Linux--多线程拷贝文件案例及其传参说明
- 最小栈
- 排队买票(歌)
- ElasticSearch性能调优
- leetcode283~Move Zeroes
- Quartz+JAVA+Servlet实现任务调度系统(简洁)
- 洛谷 P1144 最短路计数
- leetcode382 Linked List Random Node java
- BOOTSTRAP栅格系统解析