IO进程线程 0827作业
作业
作业一:创建3个线程,一个子线程拷贝文件的前一半,一个子线程拷贝后一半文件,主线程回收子线程资源。
将1.txt内容拷贝到2.txt中
#include <myhead.h>
/*
创建3个线程,一个子线程拷贝文件的前一半,
一个子线程拷贝后一半文件,主线程回收子线程资源。
将源文件1.txt拷贝到目标文件2.txt
*///传入子进程函数的数据结构体
struct Buf
{const char *pd1;//源文件const char *pd2;//目标文件int len;//文件长度char x;//判断是哪个子进程
};//求文件长度函数
int get_len(const char *p1,const char *p2)
{int fd1 = open(p1,O_RDONLY);//打开源文件if(fd1==-1){perror("open1");return -1;}int fd2 = open(p2,O_WRONLY|O_CREAT|O_TRUNC,0664);//打开创建目标文件if(fd1==-1){perror("open1");return -1;}int len = lseek(fd1,0,SEEK_END);//计算源文件长度close(fd1);close(fd2);return len;
}//定义一个拷贝函数
int copy_file(const char *p1,const char *p2,int start,int len)
{int fd1,fd2;fd1 = open(p1,O_RDONLY);//只读方式打开1.txtif(fd1==-1){perror("open1");return -1;}fd2 = open(p2,O_WRONLY);//只写方式打开2.txtif(fd2==-1){perror("open2");return -1;}lseek(fd1,start,SEEK_SET);lseek(fd2,start,SEEK_SET);char buff[1024];int sum=0;while(1){int res = read(fd1,buff,sizeof(buff));sum+=res;//读取的总长度sum大于等于文件的一半len结束if(sum>=len||res==0)//sum>=len大儿子读取长度不应大于len,二儿子读取到文件结束res==0{//写入剩下的一点点write(fd2,buff,res-(sum-len));break;}write(fd2,buff,res);}printf("拷贝成功\n");return 0;
}//执行拷贝的两个子进程函数
void *copy1(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_file(fd1,fd2,0,len/2);//退出子进程pthread_exit(NULL);}else if(x=='b'){//线程2执行的内容//利用拷贝函数拷贝后半段内容copy_file(fd1,fd2,len/2,len-len/2);//退出子进程pthread_exit(NULL);}else{perror("ptcreat");}
}int main(int argc, const char *argv[])
{//判断传入是否为2个文件if(argc !=3){printf("外部传参错误\n");return -1;}//使用求文件长度函数得到文件长度int len = get_len(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,copy1,&buf1)!=0){perror("ptcreat");return -1;}if(pthread_create(&tid2,NULL,copy1,&buf2)!=0){perror("ptcreat");return -1;}//阻塞等待线程的结束pthread_join(tid1,NULL);pthread_join(tid2,NULL);return 0;
}
运行结果:
作业二:使用无名信号量实现循环输出 春、夏、秋、冬。
#include <myhead.h>
//使用无名信号量实现循环输出 春、夏、秋、冬。
sem_t sem1,sem2,sem3,sem4;
void *fun1(void *ggg)
{while(1){sem_wait(&sem4);//sleep(1);printf("春\t");fflush(stdout);sem_post(&sem3);}pthread_exit(NULL);
}
void *fun2(void *ggg)
{while(1){sem_wait(&sem3);//sleep(1);printf("夏\t");fflush(stdout);sem_post(&sem2);}pthread_exit(NULL);
}
void *fun3(void *ggg)
{while(1){sem_wait(&sem2);//sleep(1);printf("秋\t");fflush(stdout);sem_post(&sem1);}pthread_exit(NULL);
}
void *fun4(void *ggg)
{while(1){sem_wait(&sem1);//sleep(1);printf("冬\t");fflush(stdout);sem_post(&sem4);}pthread_exit(NULL);
}int main(int argc, const char *argv[])
{pthread_t tid1,tid2,tid3,tid4;sem_init(&sem1,0,0);sem_init(&sem2,0,0);sem_init(&sem3,0,0);sem_init(&sem4,0,1);if(pthread_create(&tid1,NULL,fun1,NULL) != 0){perror("ptcreat");return -1;}if(pthread_create(&tid2,NULL,fun2,NULL) != 0){perror("ptcreat");return -1;}if(pthread_create(&tid3,NULL,fun3,NULL) != 0){perror("ptcreat");return -1;}if(pthread_create(&tid4,NULL,fun4,NULL) != 0){perror("ptcreat");return -1;}sem_destroy(&sem1);sem_destroy(&sem2);sem_destroy(&sem3); sem_destroy(&sem4); pthread_join(tid1,NULL);pthread_join(tid2,NULL);pthread_join(tid3,NULL);pthread_join(tid4,NULL);return 0;
}
运行结果:
作业三:互斥锁,无名信号量,条件变量再练习一遍。
1.1 解决竞态,(加入互斥锁后)
/*
解决竞态,(加入互斥锁后)
线程加上互斥锁,哪个线程抢到锁资源,哪个线程就执行,
其他线程只能等待,抢占锁资源时没有先后顺序的。
*/
#include <myhead.h>
#define MAX 5
#define SIZE 1000000
//pthread_mutex_t fastmutex = PTHREAD_MUTEX_INITIALIZER;//静态初始化互斥锁pthread_mutex_t fastmutex;//定义互斥锁int num = 0;//临界资源
void *fun1(void *arg)
{int i;pthread_mutex_lock(&fastmutex);//给线程体函数上锁for(i=0;i<SIZE;i++)//每一个线程都对num+1操作{num+=1;}pthread_mutex_unlock(&fastmutex);//给线程体函数解锁pthread_exit(NULL);//线程退出函数
}
int main(int argc, const char *argv[])
{pthread_mutex_init(&fastmutex,NULL);//动态初始化互斥锁pthread_t tid[MAX];int i;for(i=0;i<MAX;i++)//定义一个线程组{if(pthread_create(&tid[i],NULL,fun1,NULL) != 0){perror("ptcreat");return -1;}}for(i=0;i<MAX;i++)//回收线程资源{pthread_join(tid[i],NULL);}printf("预期结果是5000000\n");printf("实际结果是:%d\n",num);//加锁之后每一次结果都一样,避免竞态pthread_mutex_destroy(&fastmutex);return 0;
}
运行结果:
1.2 生产者和消费者线程同步时(加入无名信号量)。
/*
生产者和消费者线程同步时(加入无名信号量)。
*/
#include <myhead.h>
#define MAX 10
sem_t fastsem;//定义无名信号量
void *prodect(void *sss)
{int i;for(i=0;i<MAX;i++){printf("我是%ld,我生产了一台法拉利\n",pthread_self());}sem_post(&fastsem);pthread_exit(NULL);
}void *custom(void *ccc)
{sem_wait(&fastsem);printf("我是%ld,我消费了一台法拉利\n",pthread_self());sem_post(&fastsem);pthread_exit(NULL);
}
int main(int argc, const char *argv[])
{sem_init(&fastsem,0,0);pthread_t tid1,tid2[MAX];if(pthread_create(&tid1,NULL,prodect,NULL) !=0){perror("ptcreat");return -1;}int i;for(i=0;i<MAX;i++){if(pthread_create(&tid2[i],NULL,custom,NULL) != 0){perror("ptcreat");return -1;}}pthread_join(tid1,NULL);for(i=0;i<MAX;i++){pthread_join(tid2[i],NULL);}sem_destroy(&fastsem);return 0;
}
运行结果:
1.3 使用代码定义三个线程通过无名信号量 实现循环显示 绿灯、黄灯、红灯
#include <myhead.h>
//使用代码定义三个线程通过无名信号量 实现循环显示 绿灯、黄灯、红灯
//绿 黄 红
sem_t sem1,sem2,sem3;
void *fun1(void *ggg)
{while(1){sem_wait(&sem3);//sleep(1);printf("绿灯\t");fflush(stdout);sem_post(&sem2);}pthread_exit(NULL);
}
void *fun2(void *ggg)
{while(1){sem_wait(&sem2);//sleep(1);printf("黄灯\t");fflush(stdout);sem_post(&sem1);}pthread_exit(NULL);
}
void *fun3(void *ggg)
{while(1){sem_wait(&sem1);//sleep(1);printf("红灯\t");fflush(stdout);sem_post(&sem3);}pthread_exit(NULL);
}int main(int argc, const char *argv[])
{pthread_t tid1,tid2,tid3;sem_init(&sem1,0,0);sem_init(&sem2,0,0);sem_init(&sem3,0,1);if(pthread_create(&tid1,NULL,fun1,NULL) != 0){perror("ptcreat");return -1;}if(pthread_create(&tid2,NULL,fun2,NULL) != 0){perror("ptcreat");return -1;}if(pthread_create(&tid3,NULL,fun3,NULL) != 0){perror("ptcreat");return -1;}sem_destroy(&sem1);sem_destroy(&sem2);sem_destroy(&sem3);pthread_join(tid1,NULL);pthread_join(tid2,NULL);pthread_join(tid3,NULL);return 0;
}
运行结果: