多线程,多在那呢?

今天闲来没事就写了个下面的程序。目的就是采用10个线程copy 同一文件的不同部位。然后写进同一文件。目的是实现了但结果却是不尽人意。
我没见过多线程的下载软件源码我也不了解他们的原理。
所以我又写了个简单的copy单线程直读直写。

测试了下 。复制一个680M的电影。所花的时间多线程(10个)是单线程的一倍……好慢……
为什么呢?
源码贴上吧。希望有人指教。

#include <stdio.h>
#include <pthread.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <errno.h>
#include <time.h>

#define    MAXLINE    8192
#define    SLEN    11  
#define    PATH    "./"
#define    NEW        "new_"  
/* 在同一目录下 如出现重名文件则加上 "new_" */
#define     FILE_MODE         (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)

typedef struct {
    char    *    s_read;
    char    *    s_writ;
    pthread_t    s_tid;
    off_t    s_seek;
    size_t    s_bytes;
}s_pthread;
/*
    为了避免加锁 我为每个线程结构保存读,写文件的路径,在各自线程内在打开
    这样就为每个线程创建了一个file。又因为写的操作在不同部位,所以避免了
    各进程的竞争。不使用任何互斥量。估计很大原因就慢在这里了。
    s_seek 每个线程的偏移量。
    s_bytes 每线程所必读的字节数。
*/

static     void    err_msg(char *);
static    void    err_bmsg(char *);
static    void    init_pthread_file(s_pthread * , off_t , char* , char* );
static    void*    do_pthread(void *);
static    ulong    gettime(struct timeval *, struct timeval *);
static    void    do_no_pthread(int , int);
static    char*    getfilename(char *);

int
main(int argc, char **argv)
{
    struct stat        statbuf;
    s_pthread        sq[SLEN];
    char            path[128], *mssg;
    int                rfd, wfd, i;
    struct    timeval    in, out;
   
    if(argc < 2)
        err_msg("no find of cp file……");
    setbuf(stdout, NULL);
    rfd = open(argv[1], O_RDONLY);
    if(rfd < 0)
        err_msg("open error");
    if(fstat(rfd, &statbuf) < 0)
        err_msg("read file size error");
    sprintf(path, "%s%s", PATH, getfilename(argv[1]));
/*
    getfilename( 1 ) 取文件名 如 /home/shana/xx.xx  取出 xx.xx
*/
    if(open(path, O_RDONLY) > 0) { /*以打开方式查看 是否存在, 想不到别的方法来查看了*/
        char    mnt[128];
        sprintf(mnt, "%s%s%s", PATH, NEW, path+2); /*path 包含了 "./" 2个字符 */
        strcpy(path, mnt);
        wfd = open(mnt, O_TRUNC | O_CREAT | O_RDWR, FILE_MODE);
        if(wfd < 0)
            err_msg("creat 1 new file error");
    } else {
        wfd = open(path, O_TRUNC | O_CREAT | O_RDWR, FILE_MODE);
        if(wfd < 0)
            err_msg("creat 2 new file error");
    }

    init_pthread_file(sq, statbuf.st_size, path, argv[1]);
/*
    初始化线程结构
*/
    if(argv[2] != NULL) {
        if(atoi(argv[2]) == 2) {
            gettimeofday(&in, NULL);
            do_no_pthread(rfd, wfd);  /*如果第三个参数不为空 且为 2 就使用 单线程cpoy */
            gettimeofday(&out, NULL);
            goto    out;
        }
    }

    gettimeofday(&in, NULL);
    for(i = 0; i < SLEN; ++i)
        pthread_create(&sq[i].s_tid, NULL, &do_pthread, &sq[i]);
    for(i = 0; i < SLEN; ++i) {
        pthread_join(sq[i].s_tid, (void*)&mssg);
        printf("pthread : No.%d : %s/n", i, mssg);
    }
    gettimeofday(&out, NULL);
out:
    printf("have time = %u ms/n",    gettime(&out, &in));
    close(rfd);
    close(wfd);
    return (0);
}

static     void   
err_msg(char * err)
{
    printf("%s/n", err);
    exit(-1);
}

static    void
err_bmsg(char *err)
{
    printf("%s/n", err);
}

/*
    线程初始化 copy文件总长度 除以10 然后保留 余数。
    每个线程copy十分之一
    如余数不为0 则必须在打开一个线程copy 余数
*/
static    void   
init_pthread_file(s_pthread *qp , off_t len, char *wfd, char *rfd)
{
    int        i;
    size_t    bytes = len / (SLEN - 1);
    size_t    modby = len % (SLEN - 1);

    bzero(qp, sizeof(s_pthread) * SLEN);
    if(modby == 0) {
        for(i = 0; i < ( SLEN - 1 ); ++i, qp++) {
            qp->s_read = rfd;
            qp->s_writ = wfd;
            qp->s_seek = i * bytes;
            qp->s_bytes = bytes;
        }
    }
    else {
        for(i = 0; i < (SLEN - 1); ++i, qp++) {
            qp->s_read = rfd;
            qp->s_writ = wfd;
            qp->s_seek = i * bytes;
            qp->s_bytes = bytes;
        }   
        qp->s_read = rfd;
        qp->s_writ = wfd;
        qp->s_seek = (i++) * bytes;
        qp->s_bytes = modby;
    }
}

/*
    线程copy 函数 每个线程打开读写文件
    设置偏移量,进行读写操作
*/
static    void*   
do_pthread(void *datae)
{
    s_pthread    *qp = (s_pthread *)datae;
    off_t        leek;
    int            read_d, writ_d;
    size_t        rbyte, rm = 0;
    char        data[MAXLINE];
   
    if(qp->s_bytes == 0)
        return (NULL);
    read_d = open(qp->s_read, O_RDONLY);
    writ_d = open(qp->s_writ, O_WRONLY, FILE_MODE);
    if(read_d < 0 || writ_d < 0)
        pthread_exit("pthread open error");
    if(lseek(read_d, qp->s_seek, SEEK_SET) == -1)
        pthread_exit("pthread read lseek error");
    if(lseek(writ_d, qp->s_seek, SEEK_SET) == -1)
        pthread_exit("pthread writ lseek error");
    while( rm < qp->s_bytes ) {
        rbyte = read(read_d, data, MAXLINE);
        if(rbyte < 0)
            pthread_exit("read error");
        if( write(writ_d, data, rbyte) != rbyte)
            pthread_exit("write error");
        rm += rbyte;
    }
    close(read_d);
    close(writ_d);
    pthread_exit("ok");
}
   
static    ulong   
gettime(struct timeval *out, struct timeval *in)
{
    return ((out->tv_sec - in->tv_sec)*1000000 + (out->tv_usec-in->tv_usec));    
}

/*
    单线程读写
*/
static    void   
do_no_pthread(int rfd, int wfd)
{
    char    data[MAXLINE];
    size_t    rbyte;
   
    lseek(wfd, 0, SEEK_SET);
no_pthread_agin:
    while( (rbyte = read(rfd, data, MAXLINE) ) > 0) {
        if( write(wfd, data, rbyte) != rbyte)
            err_msg("no pthread write");
    }
    if(rbyte < 0)
        if(errno == EINTR)
            goto no_pthread_agin;
}

static    char*   
getfilename(char *path)
{
    char    *top;
    int        len;

    len = strlen(path);
    top = path + len;
    while(*top-- != '/') len--;
    if(len == 0) return (top);
    return (top + 2);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值