多线程-互斥锁-拷贝文件

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>


/**********
 * 全局变量
 * *******/
#define LEN 20
#define THREADS 5

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
struct file_info
{
    int num;
    char fileName[LEN];
};
int i = 1;      // 添加保存文件的后缀名

/*********************
 * 拷贝图片或者是文件
 * 参数:指向文件的地址
 * ******************/
void copy_file(char * name, int num) 
{
    char buff[1024] = {0};
    int  typeNum = 0;
    char copyName[LEN];
    char addName[2];
    char add;

    /* 循环拷贝文件 */
    
    int fdr = open(name, O_RDONLY);
    if (fdr == -1)
    {
        perror("error open.\n");
        exit(1);
    }
    /* 修改copy的文件名 */
    strcpy(copyName, name); 
    //itoa(i, addName, 10); // UNIX,stdlib.h没有这个函数了?
    sprintf(addName, "%d", i);      // 代替itoa,整数转字符串
    add = addName[0];

    /* 手动实现数组后移,和调用函数实现,哪个好 */
    //strcat(copyName, addName);      // 添加后缀名,不能直接加载后面
    int len = strlen(copyName);
    //printf("len is %d.\n", len);
    for (int i = 0; i < len; i++)
    {
        copyName[len + 2 - i] = copyName[len - i];
        if (copyName[len - i] == '.')
            break;
    }
    copyName[len - 4] = '_';            // 怎么修改拷贝文件名是比较方便的?
    copyName[len - 3] = add;
    printf("name is %s.\n", copyName);

    /* 读取文件 */
    int fdw = open(copyName, O_WRONLY | O_CREAT, 0600);
    if (fdw == -1)
    {
        perror("error open copy.");
        exit(1);
    }
    while ((typeNum = read(fdr, buff, 50)) > 0) // 50?
    {
        write(fdw, buff, typeNum);
    }
    i++;        // 全局变量加一
    close(fdw);
    close(fdr);
    
}

/************
 * 多线程函数
 * *********/
void * copy_fn(void *arg)   // 多线程的函数需要是指针函数,函数加static会怎么样?void *函数retuen是什么意思?
{
    // 为什么man手册上不加强制类型转换?
    // struct file_info *root = arg;
    struct file_info *pt = (struct file_info *)arg;  
    int num = pt->num;
    char * name = pt->fileName;
    pthread_mutex_lock(&mutex);         // 感觉加锁的位置不对???
    copy_file(name, num);               // 需要引用嘛?
    pthread_mutex_unlock(&mutex);
}


/***************
 * 创建多线程
 * ************/
void thread_fn(void)
{
    int err;
    pthread_t tid[THREADS];
    struct file_info fileInfo;

    //fileInfo.fileName = "asd.jpg";
    strcpy(fileInfo.fileName, "./asd.png"); // 数组赋值字符串,自动添加‘\0’
    fileInfo.num = 5;

    /* 初始化互斥锁 */
    pthread_mutex_init(&mutex, NULL);   // 第一个参数需要指针,第二个是属性的指针
    
    /* 创建多线程 */
    for (int i = 0; i < THREADS; i++)
    {
        // 第二个参数是属性,不要忘记了,第四个参数直接传递常量可以吗?并且不强制类型转换,且加引用&???,第三个参数加引用&???
        // err = pthread_create(&tid1, NULL, &copy_fn, &num)
        err = pthread_create(&tid[i], NULL, copy_fn, (void *)&fileInfo);    // 为什么需要引用&
        if (err != 0)   // 成功是0,失败是错误码
        {
            perror("error pthread create.\n");
            exit(1);
        }
        /* 线程连接 */
        err = pthread_join(tid[i], NULL); 
        if (err != 0)
        {
            perror("error join.\n");
            exit(1);
        }
    }

    /* 销毁互斥锁 */
    pthread_mutex_destroy(&mutex);  // 能不能不销毁呢?
}


/**********************
 * 主函数
 * *******************/
int main(int argc, char *argv[])
{
    char cmd = 'c';
    // 执行任务
    switch (cmd)
    {
        case 'c':
            thread_fn();    // 多线程拷贝图片
            break;
        default:
            break;
    }

    return 0;
}

posted @ 2022-04-16 18:59  starc的miao  阅读(44)  评论(0)    收藏  举报