目录
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;
}
效果图: