操作系统实验——文件复制

操作系统实验——文件复制

前期准备

  1. 安装gcc编译器
    操作系统实验——文件复制_第1张图片

  2. md5sum命令检查
    请添加图片描述

  3. 解压linux压缩包并获取程序运行的总时间
    操作系统实验——文件复制_第2张图片
    操作系统实验——文件复制_第3张图片

实验内容

1. c语言文件如下

#include
#include
#include
#include
#include
#include
#include
#include 


// 标识线程
typedef struct {
    int threadId;
} threadParm_t;
pthread_mutex_t barrier_mutex;

/**
* 复制⽂件函数
* @param sourcePath 源路径
* @param destinationPath ⽬标路径
*/
void copyFile(char sourcePath[], char destinationPath[]) {
    pthread_mutex_lock(&barrier_mutex);
    char buffer[1024];
    FILE *in, *out;//定义两个⽂件流,分别⽤于⽂件的读取和写⼊int len;
    if ((in = fopen(sourcePath, "r")) == NULL) {//打开源⽂件的⽂件流
        printf("源⽂件打开失败!\n");
        exit(1);
    }
    if ((out = fopen(destinationPath, "w")) == NULL) {//打开⽬标⽂件的⽂件流
        printf("⽬标⽂件创建失败!\n");
        exit(1);
    }
    int len;//len为fread读到的字节⻓
    while ((len = fread(buffer, 1, 1024, in)) > 0) {//从源⽂件中读取数据并放到缓冲区中,第⼆个
        //参数1也可以写成sizeof(char)
        fwrite(buffer, 1, len, out);//将缓冲区的数据写到⽬标⽂件中
    }
    fclose(out);
    fclose(in);
    pthread_mutex_unlock(&barrier_mutex);
}

/**
* 判断是否是⽬录
* @param file_name
* @return
*/
int is_dir(char *file_name) {
    struct stat info;
    stat(file_name, &info);
    if (S_ISDIR(info.st_mode))
        return 1;
    else
        return 0;
}

/**
* 如果⽂件是 . 或者 .. 跳过
* @param s
* @param c
* @return
*/
int endWith(char *s, char c) {//⽤于判断字符串结尾是否为“.”
    if (s[strlen(s) - 1] == c) {
        return 1;
    } else {
        return 0;
    }
}

void copyFolder(char *sourcePath, char *destinationPath) {
    if (opendir(destinationPath) == NULL)// 如果⽬标路径⽂件不存在,那就新建⼀个⽂件
    {
        if (mkdir(destinationPath, 0777) == -1) {
            printf("创建错误");
            exit(-1);
        }
    }
    DIR *src_dp = opendir(sourcePath);
    struct dirent *ep_src;
    char address[108] = {0};
    char totalAddress[108] = {0};
    while ((ep_src = readdir(src_dp))) //当所有⽂件都被复制退出循环
    {
        //补充⽂件所有路径
        sprintf(address, "%s%s", sourcePath, "/");
        sprintf(address, "%s%s", address, ep_src->d_name);

        //补充⽂件所有路径
        sprintf(totalAddress, "%s%s", destinationPath, "/");
        sprintf(totalAddress, "%s%s", totalAddress, ep_src->d_name);

        //如果⽂件是. 或者 .. 跳过
        if (endWith(address, '.') == 1) {
            continue;
        }

            //如果⽂件是普通⽂件
        else if ((is_dir(address) != 1)) {
            copyFile(address, totalAddress);
        }

            //复制⽬录
        else {
            copyFolder(address, totalAddress);
        }
        memset(address, 108, 1);
        memset(totalAddress, 108, 1);
    }
}

char sourcePath[100][108];//存储主目录下面的所有文件和文件夹,方便线程调用
char dstPath[100][108];//存储目标目录下面的所有文件和文件夹,方便线程调用

void *ThreadFunc(void *arg) {
    threadParm_t *p = (threadParm_t *) arg;
    int r = p->threadId;
    char *source = sourcePath[r];
    char *dst = dstPath[r];
    printf("线程 %d 正在复制 %s 到 %s\n", r, source, dst);
    copyFolder(sourcePath[r], dstPath[r]);
    printf("线程 %d 复制成功\n", r);
    pthread_exit(nullptr);
}

int main(int argc, char *argv[]) {
    if (argc != 3)//判断输⼊参数是否正确
    {
        printf("%s 缺少参数!!\n", argv[0]);
        exit(1);
    }
    printf(" main function\n");
    pthread_mutex_init(&barrier_mutex, NULL); // 初始化
    DIR *src_dp = opendir(argv[1]);
    struct dirent *ep_src;
    int thread_num = 0;//记录需要创建的线程个数
    char address[108] = {0};
    char totalAddress[108] = {0};
    // 遍历首个目录,如果是文件或者文件夹的话就创建一个新线程
    while ((ep_src = readdir(src_dp))) //当所有⽂件都被复制退出循环
    {
        //补全路径
        sprintf(address, "%s%s", argv[1], "/");
        sprintf(address, "%s%s", address, ep_src->d_name);

        //补全路径
        sprintf(totalAddress, "%s%s", argv[2], "/");
        sprintf(totalAddress, "%s%s", totalAddress, ep_src->d_name);

        //如果⽂件是. 或者 .. 跳过
        if (endWith(address, '.') == 1) {
            continue;
        } else if (is_dir(address) != 1) {
            copyFile(address, totalAddress);
            continue;
        }
        //实现字符串的拷贝
        strcpy(sourcePath[thread_num], address);
        strcpy(dstPath[thread_num], totalAddress);
        memset(address, 108, 1);
        memset(totalAddress, 108, 1);
        thread_num++;
    }
    pthread_t thread[thread_num];
    threadParm_t threadParm[thread_num]; // 创建相对应的线程标识
    for (int i = 0; i < thread_num; i++) {
        threadParm[i].threadId = i;
        pthread_create(&thread[i], nullptr, ThreadFunc, (void *) &threadParm[i]);
    }
    for (int i = 0; i < thread_num; i++) {
        pthread_join(thread[i], nullptr);
    }
    printf("此文件复制成功\n");
    return 0;
}

2. 实验验证

  1. 生成目标程序
    操作系统实验——文件复制_第4张图片

  2. 新建目标的空文件

操作系统实验——文件复制_第5张图片

  1. 开始复制

操作系统实验——文件复制_第6张图片
4. 复制成功
操作系统实验——文件复制_第7张图片
5. 开启验证,使用diff命令进行验证

操作系统实验——文件复制_第8张图片
6. 验证之后无差别,实验成功

你可能感兴趣的:(linux,运维,服务器)