一、作业
用两个线程完成文件的拷贝
代码:
#include<myhead.h>
int main(int argc, const char *argv[])
{
//定义变量接受进程号
pid_t pid = fork();
if(pid > 0)
{
//这是父进程
pid_t pid1 = fork();
if(pid1>0)
{
printf("我是父进程\n");
}else if(pid1==0)
{
printf("我是小儿子\n");
//退出进程
sleep(8);
printf("second die\n");
exit(EXIT_SUCCESS);
}else
{
perror("fork error");
return -1;
}
}else if(pid == 0)
{
printf("我是老大\n");
//退出进程
sleep(5);
printf("first die\n");
exit(EXIT_SUCCESS);
}else
{
perror("fork error");
return -1;
}
//阻塞回收子进程资源
wait(NULL);
wait(NULL);
printf("wohaihuozhe\n");
sleep(3);
return 0;
}
ubuntu@ubuntu:0801$ cat 07thread.c
#include<myhead.h>
//传入子进程函数的数据结构体
struct Buf
{
const char *pd1;//源文件
const char *pd2;//目标文件
int len;//文件长度
char x;//判断是哪个子进程
};
//求文件长度函数
int line(const char *pd1,const char *pd2)
{
int fd1 = -1;
int fd2 = -1;
//以只读的形式打开源文件
if((fd1 = open(pd1,O_RDONLY))==-1)
{
perror("open fd1 error");
return -1;
}
//以创建的形式打开目的文件
if((fd2 = open(pd2,O_WRONLY|O_CREAT|O_TRUNC,0664))==-1)
{
perror("open fd2 error");
return -1;
}
//求出源文件长度
int len = 0;
len = lseek(fd1,0,SEEK_END);
//关闭文件
close(fd1);
close(fd2);
//返回文件长度
return len;
}
//定义一个拷贝函数
void copy(const char *pd1,const char *pd2,int start,int len)
{
int fd1 = -1;
int fd2 = -1;
//以只读的形式打开源文件
if((fd1 = open(pd1,O_RDONLY))==-1)
{
perror("open fd1 error");
return ;
}
//以只写的形式打开目的文件
if((fd2 = open(pd2,O_WRONLY))==-1)
{
perror("open fd2 error");
return ;
}
//光标位置
lseek(fd1,start,SEEK_SET);
lseek(fd2,start,SEEK_SET);
//定义搬运工
char buf[128] = "";
int res = 0;
int sum = 0;
//拷贝
while(1)
{
res = read(fd1,buf,sizeof(buf));
sum += res; //读取字节个数累加
if(res ==0||sum>len)//不在读取文件
{
write(fd2,buf,res-sum+len);//把最后一次读取进来的拷贝进进行前半段拷贝的子进程中
break;
}
write(fd2,buf,res);
}
//结束文件
close(fd1);
close(fd2);
return ;
}
//执行拷贝的两个子进程函数
void *task(void *arg)
{
//把传入子进程的数据导出
const char*fd1 = (*((struct Buf*)arg)).pd1;
const char*fd2 = (*((struct Buf*)arg)).pd2;
int len = (*((struct Buf*)arg)).len;
char x = (*((struct Buf*)arg)).x;
//判断传过来的信息
if(x=='a')
{
//线程1执行的内容
//利用拷贝函数拷贝前半段内容
copy(fd1,fd2,0,len/2);
//退出子进程
pthread_exit(NULL);
}else if(x=='b')
{
//线程2执行的内容
//利用拷贝函数拷贝后半段内容
copy(fd1,fd2,len/2,len-len/2);
//退出子进程
pthread_exit(NULL);
}else
{
printf("pthread_create error\n");
}
}
/***************主函数**************/
int main(int argc, const char *argv[])
{
//判断传入是否为2个文件
if(argc !=3)
{
printf("input file error\n");
return -1;
}
//使用求文件长度函数得到文件长度
int len = 0;
len = line(argv[1],argv[2]);
//定义结构体传入子线程
struct Buf buf1 = {argv[1],argv[2],len,'a'};
struct Buf buf2 = {argv[1],argv[2],len,'b'};
//定义线程变量
pthread_t tid1,tid2;
//创建两个线程
if(pthread_create(&tid1,NULL,task,&buf1)!=0)
{
printf("tid1 创建失败\n");
return -1;
}
if(pthread_create(&tid2,NULL,task,&buf2)!=0)
{
printf("tid2 创建失败\n");
return -1;
}
//阻塞等待线程的结束
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
printf("拷贝成功\n");
return 0;
}
运行结果:
二、思维导图(线程)