IO进程线程day6

目录

1.使用有名管道,完成两个进程的相互通信

2.使用无名管道完成父子进程间的通信

3.使用标准IO完成两个文件的拷贝

4.使用文件IO实现两个文件的拷贝

5.使用多进程完成两个文件的拷贝

6.使用多线程完成两个文件的拷贝

7.将互斥锁的案例重新写一遍

8.将无名信号量实现生产者消费者程序重新实现一遍

9.将条件变量实现生产者消费者程序重新实现一遍

思维导图:


1.使用有名管道,完成两个进程的相互通信

test1.c

#include <head.h>


//定义线程体函数
void *task(void *arg){
	/*********************test1分支线程发送数据************************/

	//打开管道文件2
	int wfd=-1;
	if((wfd=open("fifo2",O_WRONLY))==-1){
		perror("wfd open error");
		return NULL;
	}

	//向管道文件2中写入数据
	char wbuf[128]="";
	while(1){
		printf("请输入>>>>>\n");
		//从终端输入字符串
		fgets(wbuf,sizeof(wbuf),stdin);
		wbuf[strlen(wbuf)-1]=0;
		//将字符串写入管道中
		write(wfd,wbuf,sizeof(wbuf));
		//判断是否要退出
		if(strcmp(wbuf,"quit")==0){	
			printf("test1的写已退出\n");
			break;
		}

	}
	//关闭管道文件2
	close(wfd);


	//退出线程
	pthread_exit(NULL);


}

int main(int argc, const char *argv[])
{

	//创建分支线程
	pthread_t tid =-1;
	if(pthread_create(&tid,NULL,task,NULL)!=0){
		perror("tid create error");
		return -1;
	}

	/*********************test1主线程接收数据**************************/


	//打开管道文件1
	int rfd=-1;
	if((rfd=open("fifo1",O_RDONLY))==-1){
		perror("rfd open error");
		return -1;
	}

	//从管道文件1中读取数据
	char rbuf[128]="";
	while(1){
		//清空内容
		bzero(rbuf,sizeof(rbuf));
		//将数据从管道文件1中读取出来
		read(rfd,rbuf,sizeof(rbuf));
		printf("test1收到一条消息:%s\n",rbuf);

		//判断是否要退出
		if(strcmp(rbuf,"quit")==0){
			printf("test1的读已退出\n");
			break;
		}

	}
	//关闭管道文件1
	close(rfd);

	//线程资源回收
	pthread_join(tid,NULL);
	return 0;
}

test2.c

#include <head.h>


//定义线程体函数
void *task(void *arg){
	/*********************test2分支线程发送数据************************/

	//打开管道文件1
	int wfd=-1;
	if((wfd=open("fifo1",O_WRONLY))==-1){
		perror("wfd open error");
		return NULL;
	}

	//向管道文件1中写入数据
	char wbuf[128]="";
	while(1){
		printf("请输入>>>>>\n");
		//从终端输入字符串
		fgets(wbuf,sizeof(wbuf),stdin);
		wbuf[strlen(wbuf)-1]=0;
		//将字符串写入管道中
		write(wfd,wbuf,sizeof(wbuf));
		//判断是否要退出
		if(strcmp(wbuf,"quit")==0){	
			printf("test2的写已退出\n");
			break;
		}

	}
	//关闭管道文件1
	close(wfd);


	//退出线程
	pthread_exit(NULL);

}


int main(int argc, const char *argv[])
{

	//创建分支线程
	pthread_t tid =-1;
	if(pthread_create(&tid,NULL,task,NULL)!=0){
		printf("tid create error\n");
		return -1;
	}

	/************************test2主线程接收数据*************************/ 


	//打开管道文件2
	int rfd=-1;
	if((rfd=open("fifo2",O_RDONLY))==-1){
		perror("rfd open error");
		return -1;
	}

	//从管道文件2中读取数据
	char rbuf[128]="";
	while(1){
		//清空内容
		bzero(rbuf,sizeof(rbuf));
		//将数据从管道文件2中读取出来
		read(rfd,rbuf,sizeof(rbuf));
		printf("test2收到一条消息:%s\n",rbuf);

		//判断是否要退出
		if(strcmp(rbuf,"quit")==0){
			printf("test2的读已退出\n");
			break;
		}

	}
	//关闭管道文件2
	close(rfd);

	//线程资源回收
	pthread_join(tid,NULL);
	return 0;
}

效果图:

2.使用无名管道完成父子进程间的通信

代码:

#include <head.h>

int main(int argc, const char *argv[])
{
	//使用无名管道完成父子进程间的通信

	//定义进程号变量
	pid_t pid = -1;
	//定义存放管道文件描述符的数组
	int pipefd[2] = {0};

	//创建管道文件
	if(pipe(pipefd) == -1)
	{
		perror("pipe error");
		return -1;
	}

	//创建一个子进程 
	pid=fork();
	if(pid>0){
		printf("父进程\n");
		//关闭父进程中管道的读端
		close(pipefd[0]);

		char buf[128] = "";
		while(1)
		{
			//从终端上获取数据放入buf中
			fgets(buf, sizeof(buf), stdin);
			buf[strlen(buf)-1] = 0;   //将'\n'换成'\0'
			//将数据写入管道文件中   
			write(pipefd[1], buf, sizeof(buf));

			if(strcmp(buf, "quit") == 0) //退出条件
			{
				break;
			}
		}

		//关闭写端
		close(pipefd[1]);
		//回收子进程资源
		wait(NULL);
	}else if(pid==0){

		//子进程关闭管道的写端
		close(pipefd[1]);

		char rbuf[128] = "";
		while(1)
		{
			bzero(rbuf, sizeof(rbuf));    //将数组内容置0
			//从管道文件中读取数据
			read(pipefd[0], rbuf, sizeof(rbuf));      

			printf("子进程收到父进程消息: %s\n", rbuf);   
			if(strcmp(rbuf, "quit") == 0)
			{
				break;
			}
		}

		//关闭读端
		close(pipefd[0]);
		//退出子进程
		exit(EXIT_SUCCESS);
	}else{
		printf("fork error\n");
		return -1;
	}
	return 0;
}

效果图:

3.使用标准IO完成两个文件的拷贝

代码:

#include <head.h>

int main(int argc, const char *argv[])
{
	//使用标准IO完成两个文件的拷贝

	//判断终端输入的个数
	if(argc!=3){
		perror("error");
		return -1;
	}
	//定义两个文件指针
	FILE *srcfp=NULL; //源文件
	FILE *destfp=NULL; //目标文件

	//以只读打开源文件
	if((srcfp=fopen(argv[1],"r"))==NULL){
		perror("fopen srcfp error");
		return -1;
	}

	//以只写打开目标文件
	if((destfp=fopen(argv[2],"w"))==NULL){
		perror("fopen destfp error");
		return -1;
	}

	char buf[10]=""; //定义一个搬运工

	while(1){
		size_t ret=	fread(buf,1,sizeof(buf),srcfp); //从源文件中读取数据
		fwrite(buf,1,ret,destfp); //写入目标文件
		if(feof(srcfp)){ //读取结束的条件
			break;
		}
	}
	printf("拷贝成功!\n");
	//关闭文件
	fclose(srcfp);
	fclose(destfp);
	return 0;
}

效果图:

4.使用文件IO实现两个文件的拷贝

代码:

#include <head.h>

int main(int argc, const char *argv[])
{
	//使用文件IO实现两个文件的拷贝
	
	//判断终端输入的个数
	if(argc!=3){
		perror("error");
		return -1;
	}
	
	//定义两个文件描述符
	int srcfd=-1; //源文件
	int destfd=-1; //目标文件
	//以只读打开源文件
	if((srcfd=open(argv[1],O_RDONLY))==-1){
		perror("open srcfd error");
		return -1;
	}

	//以只写打开目标文件
	if((destfd=open(argv[2],O_WRONLY|O_CREAT|O_TRUNC,0664))==-1){
		perror("open destfd error");
		return -1;
	}

	char buf[10]=""; //定义一个搬运工
	while(1){
		int ret=read(srcfd,buf,sizeof(buf)); //从源文件中读取数据
		if(ret==0){
			break;
		}
		write(destfd,buf,ret); //写入目标文件
	}
	printf("拷贝成功!\n");
	//关闭文件
	close(srcfd);
	close(destfd);
	return 0;
}

效果图:

5.使用多进程完成两个文件的拷贝

代码:

#include <head.h>

//计算源文件的大小,并且创建目标文件函数
int Getfile_size(const char *srcfile,const char *destfile){
	//以只读的方式打开源文件
	int srcfd=-1;
	if((srcfd=open(srcfile,O_RDONLY))==-1){
		perror("open srcfile error");
		return -1;
	}

	int size=lseek(srcfd,0,SEEK_END); //计算源文件的大小

	//以只写的方式打开目标文件
	int destfd=-1;
	if((destfd=open(destfile,O_WRONLY|O_CREAT|O_TRUNC,0664))==-1){
		perror("open destfile error");
		return -1;
	}

	//关闭文件
	close(srcfd);
	close(destfd);
	return size;
}

//拷贝文件函数
int Copyfile(const char *srcfile,const char *destfile,int start,int size){
	//以只读的方式打开源文件
	int srcfd=-1;
	if((srcfd=open(srcfile,O_RDONLY))==-1){
		perror("open srcfile error");
		return -1;
	}
	//以只写的方式打开目标文件
	int destfd=-1;
	if((destfd=open(destfile,O_WRONLY))==-1){
		perror("open destfile error");
		return -1;
	}

	//将读和写的光标移动到开始的位置
	lseek(srcfd,start,SEEK_SET);
	lseek(destfd,start,SEEK_SET);

	char buf[10]=""; //定义搬运工
	int sum=0; //定义变量统计已经拷贝的总大小
	while(1){
		int ret=read(srcfd,buf,sizeof(buf)); //读取
		sum+=ret;
		if(sum>=size || ret==0){
			write(destfd,buf,ret-(sum-size)); //将剩余的内容拷贝到目标文件中
			break;
		}
		write(destfd,buf,ret); //写入
	}

	//关闭文件
	close(srcfd);
	close(destfd);
	return 0;
}

/*****************************主函数**************************************/

int main(int argc, const char *argv[])
{
	//使用多进程完成两个文件的拷贝

	//判断终端输入个数
	if(argc!=3){
		perror("error");
		return -1;
	}

	//计算出源文件的大小,并且创建目标文件
	int size=Getfile_size(argv[1],argv[2]);

	//创建子进程
	pid_t pid=-1;
	pid=fork();

	if(pid>0){
		//父进程拷贝文件前一半内容
		Copyfile(argv[1],argv[2],0,size/2);
		printf("前一半内容拷贝成功!\n");

		//父进程回收子进程资源
		wait(NULL);
	}else if(pid==0){
		//子进程拷贝文件后一半内容
		Copyfile(argv[1],argv[2],size/2,size-size/2);
		printf("后一半内容拷贝成功!\n");

		//关闭子进程
		exit(EXIT_SUCCESS);
	}else{
		perror("fork error");
		return -1;
	}
	return 0;
}

效果图:

6.使用多线程完成两个文件的拷贝

代码:

#include <head.h>

//定义结构体
struct File
{
	const char *srcfile;
	const char *destfile;
	int size;
};

//计算源文件大小并创建目标文件函数
int getfilesize(const char* srcfile,const char* destfile){

	//以只读打开源文件
	int srcfd=-1;
	if((srcfd=open(srcfile,O_RDONLY))==-1){
		perror("open srcfd error");
		return -1;
	}
	int size=lseek(srcfd,0,SEEK_END); //计算文件大小
	//以只写打开目标文件
	int destfd=-1;
	if((destfd=open(destfile,O_WRONLY|O_CREAT|O_TRUNC,0664))==-1){
		perror("open destfd error");
		return -1;
	}

	//关闭文件
	close(srcfd);
	close(destfd);
	return size;
}

//拷贝函数
int Copyfile(const char* srcfile,const char* destfile,int start,int size){
	//以只读打开源文件
	int srcfd=-1;
	if((srcfd=open(srcfile,O_RDONLY))==-1){
		perror("open srcfd error");
		return -1;
	}

	//以只写打开目标文件
	int destfd=-1;
	if((destfd=open(destfile,O_WRONLY))==-1){
		perror("open destfd error");
		return -1;
	}

	lseek(srcfd,start,SEEK_SET);  //将源文件光标移到开始位置
	lseek(destfd,start,SEEK_SET);  //将目标文件光标移到开始位置

	char buf[10]="";   //定义搬运工
	int sum=0;    //定义变量统计拷贝的总大小
	int res=0;
	while(1){
		res=read(srcfd,buf,sizeof(buf));
		sum+=res;
		if(sum>=size || res==0){
			write(destfd,buf,res-(sum-size)); //将剩余的内容拷贝到文件中
			break;
		}
		write(destfd,buf,res); //将读取的内容拷贝到目标文件中
	}

	//关闭文件
	close(srcfd);
	close(destfd);
	return 0;
}


//定义分支线程体函数
void *task(void *arg){	
	struct File s= *((struct File*)arg); //将传递的内容解析出来
	Copyfile(s.srcfile,s.destfile,s.size/2,s.size-s.size/2); //拷贝后一半内容
	printf("后一半内容拷贝成功!\n");

	//退出线程
	pthread_exit(NULL);
}


/*********************************主函数**********************************/

int main(int argc, const char *argv[])
{
	//使用多线程完成两个文件的拷贝

	//判断终端输入的个数
	if(argc!=3){
		perror("error");
		return -1;
	}

	//定义变量储存源文件大小并创建目标文件
	int filesize=getfilesize(argv[1],argv[2]);

	//定义结构体变量
	struct File s={argv[1],argv[2],filesize};

	//创建分支线程
	pthread_t tid=-1;
	if(pthread_create(&tid, NULL, task, &s) != 0)
	{
		printf("tid create error\n");
		return -1;
	}


	//主线程
	Copyfile(s.srcfile,s.destfile,0,s.size/2); //拷贝前一半内容
	printf("前一半内容拷贝成功!\n");

	//线程资源回收
	pthread_join(tid,NULL);
	return 0;
}

效果图:

7.将互斥锁的案例重新写一遍

代码:

#include <head.h>

int money=5000; //定义一个全局资源

pthread_mutex_t mutex; //定义一个互斥锁

//分支线程体
void*task(void *arg){

	//分支线程处理全局资源
	while(1){
		//上锁
		pthread_mutex_lock(&mutex);
		//花钱
		money=money-50;
		printf("分支线程花了50元,还剩%d\n",money);
		//解锁
		pthread_mutex_unlock(&mutex);
		sleep(1);

	}
		//结束分支线程
		pthread_exit(NULL);
}

/**************************主函数*************************/

int main(int argc, const char *argv[])
{
	//将互斥锁的案例重新写一遍
	
	//初始化互斥锁
pthread_mutex_init(&mutex, NULL);
	//创建分支线程
	pthread_t tid=-1;
	if(pthread_create(&tid,NULL,task,NULL)!=0){
		printf("creat tid error\n");
		return -1;
	}

	//主线程处理全局资源
	while(1){

		//上锁
		pthread_mutex_lock(&mutex);
		//花钱
		money=money-100;
		printf("主线程花了100元,还剩%d\n",money);	
		//解锁
		pthread_mutex_unlock(&mutex);
		sleep(1);
	}
	
	//回收分支线程资源
	pthread_join(tid,NULL);
	//销毁锁
	pthread_mutex_destroy(&mutex);

	return 0;
}

效果图:

8.将无名信号量实现生产者消费者程序重新实现一遍

代码:

#include <head.h>

//定义一个无名信号量
sem_t sem;

//定义生产者线程
void *task1(void *arg){
    while(1){
        sleep(1);
        printf("线程1生产了一辆特斯拉\n");
        //释放无名信号量资源
        sem_post(&sem);
    }
}

//定义消费者线程
void *task2(void *arg){
    while(1){
        sleep(1);
        //申请无名信号量资源
        sem_wait(&sem);
        printf("线程2消费一辆特斯拉\n");
    }
}
/**********************************主程序**********************************/
int main(int argc, const char *argv[])
{
	//将无名信号量实现生产者消费者程序重新实现一遍
	
	//定义两个线程号
    pthread_t tid1,tid2;

    //2.初始化一个无名信号量
    sem_init(&sem,0,0);
    //第一个0表示该无名信号量用于线程之间同步
    //第二个0表示无名信号量的初始值value为0

    //创建两个线程
    if(pthread_create(&tid1,NULL,task1,NULL)!=0){  //生产者线程 
        printf("tid1 create error");                   
        return -1;
    }
   if(pthread_create(&tid2,NULL,task2,NULL)!=0){  //消费者线程

        printf("tid2 create error");
        return -1;
    }

    //主线程输出的数据
    printf("tid1=%#lx,tid2=%#lx \n",tid1,tid2);

    //阻塞回收分支线程资源
    pthread_join(tid1,NULL);
    pthread_join(tid2,NULL);

    //销毁无名信号量
    sem_destroy(&sem);

	return 0;
}

效果图:

9.将条件变量实现生产者消费者程序重新实现一遍

代码:

#include <head.h>

//定义一个条件变量
pthread_cond_t cond ;

//定义一个互斥锁
pthread_mutex_t mutex;


//定义生产者线程
void *task1(void *arg){
	 int n=5;
	while(n--){
		sleep(1);
		printf("我生产了一辆特斯拉\n");
		//唤醒一个消费者线程
		pthread_cond_signal(&cond);
	}
	printf("工厂倒闭\n");
	pthread_exit(NULL);
}

//定义消费者线程
void *task2(void *arg){
	//上锁
	pthread_mutex_lock(&mutex);
		//将消费者线程进入休眠等待队列
		pthread_cond_wait(&cond,&mutex);
		//解锁
		pthread_mutex_unlock(&mutex);

		printf("%#lx:消费了一辆特斯拉\n",pthread_self());
		//退出线程
		pthread_exit(NULL);
	}
/********************************主线程**************************/
int main(int argc, const char *argv[])
{
	//将条件变量实现生产者消费者程序重新实现一遍
	
	//定义线程号
	pthread_t tid1,tid2,tid3,tid4,tid5,tid6;

	//初始化条件变量
	pthread_cond_init(&cond,NULL);
	//初始化互斥锁
    pthread_mutex_init(&mutex, NULL);

	//创建生产者和消费者线程
	if(pthread_create(&tid1,NULL,task1,NULL)!=0){ //生产者线程
		printf("tid1 create error");
		return -1;
	}

	if(pthread_create(&tid2,NULL,task2,NULL)!=0){ //消费者线程
		printf("tid2 create error");
		return -1;
	}
	if(pthread_create(&tid3,NULL,task2,NULL)!=0){ //消费者线程
		printf("tid3 create error");
		return -1;
	}
	if(pthread_create(&tid4,NULL,task2,NULL)!=0){ //消费者线程
		printf("tid4 create error");
		return -1;
	}
	if(pthread_create(&tid5,NULL,task2,NULL)!=0){ //消费者线程
		printf("tid5 create error");
		return -1;
	}
	if(pthread_create(&tid6,NULL,task2,NULL)!=0){ //消费者线程
		printf("tid6 create error");
		return -1;
	}

	//主线程输出的数据
	printf("tid1=%#lx\ntid2=%#lx\ntid3=%#lx\ntid4=%#lx\ntid5=%#lx\ntid6=%#lx\n",\
			tid1,tid2,tid3,tid4,tid5,tid6);

	//阻塞回收分支线程资源
	pthread_join(tid1,NULL);
	pthread_join(tid2,NULL);
	pthread_join(tid3,NULL);
	pthread_join(tid4,NULL);
	pthread_join(tid5,NULL);
	pthread_join(tid6,NULL);

	//销毁条件变量
	pthread_cond_destroy(&cond);
	//销毁互斥锁
	pthread_mutex_destroy(&mutex);
	return 0;
}

效果图:

思维导图:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值