作业
1.将一个文件中的数据打印到终端上,类似cat一个文件。要求如下:
a.A线程读取文件中的数据
b.B线程将A线程读取到的数据打印到终端上
c.文件打印完毕后,结束进程。
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <semaphore.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
sem_t sem1, sem2;
int res;
int fp;
off_t size;
char c;
//B线程写到终端上
void *CallBack_printf(void *arg)
{
int i=0;
while(1)
{
if(res < 0)
break;
sem_wait(&sem2);
write(1, &c, res);
sem_post(&sem1);
}
pthread_exit(NULL);
}
//A线程读取文件中的数据
void *CallBack_read(void *arg)
{
while(1)
{
sem_wait(&sem1);
if((res=read(fp, &c, 1)) < 0)
{
perror("read");
pthread_exit(NULL);
}
if(res==0)
{
break;
}
sem_post(&sem2);
}
pthread_exit(NULL);
}
int main(int argc, const char *argv[])
{
//打开一个文件
if((fp = open("./01_cond.c", O_RDONLY)) < 0)
{
perror("open");
return -1;
}
if(fp < 0)
{
perror("open");
return -1;
}
//偏移量
size = lseek(fp, 0, SEEK_END);
printf("size = %ld\n", size);
lseek(fp, 0, SEEK_SET);
//创建两个线程
pthread_t tid1;
pthread_t tid2;
if(pthread_create(&tid1, NULL, CallBack_read, NULL) < 0)
{
fprintf(stderr, "pthread_create failedi\n");
return -1;
}
if(pthread_create(&tid2, NULL, CallBack_printf, NULL) < 0)
{
fprintf(stderr, "pthread_create failed\n");
return -1;
}
//创建2个信号量
if(sem_init(&sem1, 0, 1) < 0)
{
perror("sem_init");
return -1;
}
if(sem_init(&sem2, 0, 0) < 0)
{
perror("sem_init");
return -1;
}
//阻塞主线程销毁
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
//关闭文件
close(fp);
//销毁信号量
sem_destroy(&sem1);
sem_destroy(&sem2);
printf("打印成功\n");
return 0;
}
输出结果:
ubuntu@ubuntu:Day7$ gcc 01_homework.c -pthread
ubuntu@ubuntu:Day7$ ./a.out
size = 1872
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
//临界资源
char buf[] = "1234567";
//互斥锁的建立
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
//创建条件变量
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int flag = 0; //0:打印, 1:倒置
void* CallBack_printf(void *arg)
{
while(1)
{
/******************临界区***************/
//上锁
pthread_mutex_lock(&mutex);
if(flag != 0)
{
//可以解开互斥锁,同时阻塞当前线程,让线程进入休眠操作
//等待被唤醒
pthread_cond_wait(&cond, &mutex);
//被唤醒的同时,尝试上锁
}
printf("%s\n", buf);
flag = 1;
//此时尝试唤醒另一个线程进行任务
pthread_cond_signal(&cond);
//解锁
pthread_mutex_unlock(&mutex);
}
pthread_exit(NULL);
}
//线程执行体
void* CallBack_swap(void *arg)
{
char temp = 0;
int len = sizeof(buf);
while(1)
{
/****************临界区******************/
//上锁
pthread_mutex_lock(&mutex);
if(flag != 1)
{
pthread_cond_wait(&cond, &mutex);
}
for(int i=0; i<len/2; i++)
{
temp = buf[i];
buf[i] = buf[len-i-2];
buf[len-i-2] = temp;
}
flag = 0;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
}
pthread_exit(NULL);
}
//
int main(int argc, const char *argv[])
{
pthread_t tid1, tid2;
//创建两个新线程
if(pthread_create(&tid1, NULL, CallBack_printf, NULL) != 0)
{
fprintf(stderr, "pthread_create have failed __%d__\n", __LINE__);
return -1;
}
if(pthread_create(&tid2, NULL, CallBack_swap, NULL) != 0)
{
fprintf(stderr, "pthread_create have failed __%d__\n", __LINE__);
return -1;
}
//对主线程进行阻塞
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
//摧毁互斥锁
pthread_mutex_destroy(&mutex);
//摧毁条件变量
pthread_cond_destroy(&cond);
return 0;
}
2.用条件变量实现,有编号为ABC的三个线程,线程内分别打印自己的线程编号,要求打印的顺序为ABC.
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
sem_t sem1, sem2, sem3;
void *CallBack_A(void *arg)
{
while(1)
{
sem_wait(&sem1);
printf("A");
sem_post(&sem2);
}
}
void *CallBack_B(void *arg)
{
while(1)
{
sem_wait(&sem2);
printf("B");
sem_post(&sem3);
}
}
void *CallBack_C(void *arg)
{
while(1)
{
sem_wait(&sem3);
printf("C\n");
sem_post(&sem1);
}
}
int main(int argc, const char *argv[])
{
//创建两个信号量
if(sem_init(&sem1, 0, 1) < 0)
{
perror("sem_init");
return -1;
}
if(sem_init(&sem2, 0, 0) < 0)
{
perror("sem_init");
return -1;
}
if(sem_init(&sem3, 0, 0) < 0)
{
perror("sem_init");
return -1;
}
//创建ABC三个线程
pthread_t tid1, tid2, tid3;
if(pthread_create(&tid1, NULL, CallBack_A, NULL) < 0)
{
fprintf(stderr, "pthread_create failed\n");
return -1;
}
if(pthread_create(&tid2, NULL, CallBack_B, NULL) < 0)
{
fprintf(stderr, "pthread_create failed\n");
return -1;
}
if(pthread_create(&tid3, NULL, CallBack_C, NULL) < 0)
{
fprintf(stderr, "pthread_create failed\n");
return -1;
}
//对主线程进程阻塞
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
pthread_join(tid3, NULL);
//摧毁信号量
sem_destroy(&sem1);
sem_destroy(&sem2);
sem_destroy(&sem3);
return 0;
}
输出结果:
ABC
ABC
ABC
ABC
ABC
ABC
ABC
ABC
ABC
ABC
ABC
ABC
ABC
ABC
ABC
ABC
ABC
3.要求用信号量的方式实现,打印一次倒置一次。不允许使用flag
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <semaphore.h>
//临界资源
char buf[] = "1234567";
//互斥锁的建立
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
//创建条件变量
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
//信号量
sem_t sem; //用来上锁
sem_t sem1; //用来充当条件变量
//sem_t sem2;
//int flag = 0; //0:打印, 1:倒置
void* CallBack_printf(void *arg)
{
while(1)
{
/******************临界区***************/
//用信号量进行上锁 p操作
sem_wait(&sem);
printf("%s\n", buf);
sem_post(&sem1);
}
pthread_exit(NULL);
}
//线程执行体
void* CallBack_swap(void *arg)
{
char temp = 0;
int len = sizeof(buf);
while(1)
{
/****************临界区******************/
//上锁
sem_wait(&sem1);
for(int i=0; i<len/2; i++)
{
temp = buf[i];
buf[i] = buf[len-i-2];
buf[len-i-2] = temp;
}
sem_post(&sem);
}
pthread_exit(NULL);
}
int main(int argc, const char *argv[])
{
//创建一个信号量
if(sem_init(&sem, 0, 1) < 0)
{
perror("sem_init");
return -1;
}
if(sem_init(&sem1, 0, 0) < 0)
{
perror("sem_init");
return -1;
}
//创建两个新线程
pthread_t tid1, tid2;
if(pthread_create(&tid1, NULL, CallBack_printf, NULL) != 0)
{
fprintf(stderr, "pthread_create have failed __%d__\n", __LINE__);
return -1;
}
if(pthread_create(&tid2, NULL, CallBack_swap, NULL) != 0)
{
fprintf(stderr, "pthread_create have failed __%d__\n", __LINE__);
return -1;
}
//对主线程进行阻塞
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
// 摧毁信号量
sem_destroy(&sem);
sem_destroy(&sem1);
return 0;
}
输出结果:
1234567
7654321
1234567
7654321
1234567
7654321
1234567
7654321
1234567
7654321
1234567
7654321