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
原创粉丝点击