#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, ©_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;
}