IO进程线程的通信操作

1.编程实现互斥机制

程序代码:

  1 #include<myhead.h>
  2 int num=520;//临界资源
  3 //1.创建一个互斥锁变量
  4 pthread_mutex_t mutex;//定义一个pthread_mutex_t类型的变量
  5 //定义任务1函数
  6 void *task1(void *arg)
  7 {
  8     printf("不畏过去\n");
  9     //获取锁资源
 10     pthread_mutex_lock(&mutex);//互斥锁地址
 11     num=1314;
 12     sleep(3);
 13     printf("task1:num=%d\n",num);
 14     //释放锁资源
 15     pthread_mutex_unlock(&mutex);//互斥锁地址
 16 }
 17 //定义任务2函数
 18 void *task2(void *arg)
 19 {
 20     printf("不惧将来\n");
 21     //获取锁资源
 22     pthread_mutex_lock(&mutex);
 23     num++;   //521
 24     sleep(1);  //休眠,执行任务一的赋值语句num=1314
 25     //遇到任务1中的互斥锁,回到这等休眠结束,执行任务二所有程序
 26     printf("task2:num=%d\n",num);
 27     //释放锁资源
 28     pthread_mutex_unlock(&mutex);
 29     //释放完再回到任务一的互斥锁位置,执行任务一所以程序
 30 }
 31 int main(int argc, const char *argv[])
 32 {
 33     //2.初始化互斥锁
 34     pthread_mutex_init(&mutex,NULL);//互斥锁地址,互斥锁属性,成败返回0
 35     //创建两个线程
 36     pthread_t tid1,tid2;//线程号变量
 37     if(pthread_create(&tid1,NULL,task1,NULL)!=0)
 38     //创建分支线程,成0败错误码(不是置位错误码)
 39    //线程号指针,线程属性,线程体(函数指针),线程体的参数
 40     {
 41         printf("tid1 create error\n");//是POSIX库错误码,不能用ferror()
 42         return 0;
 43     }
 44     if(pthread_create(&tid2,NULL,task2,NULL)!=0)
 45     {
 46         printf("tid2 create error\n");
 47         return 0;
 48     }
 49     printf("tid1:%#lx,tid2:%#lx\n",tid1,tid2);//线程号
 50     //回收线程资源
 51     pthread_join(tid1,NULL);//阻塞等待指定线程的退出,收尸,成0败错误码
 52     pthread_join(tid2,NULL);//要回收的线程号,要回收的线程退出时的状态,NULL
 53     //销毁锁资源
 54     pthread_mutex_destroy(&mutex);//互斥锁指针
 55     return 0;
 56 }  

运行结果:

2.编程实现无名信号量

(1)生产和销售

程序代码:

  1 #include<myhead.h>
  2 //1.创建无名信号量
  3 sem_t sem;//定义一个sem_t类型的变量
  4 //定义生产线程
  5 void *task1(void *arg)
  6 {
  7     int num=5;//定义循环量
  8     while(num--)
  9     {
 10         sleep(1);
 11         printf("生产三蹦子\n");
 12         //4.释放资源
 13         sem_post(&sem);//释放无名信号量资源,value加1,
 14         //无名信号量地址
 15     }
 16     //退出线程
 17     pthread_exit(NULL);//线程退出时状态,NULL
 18 }
 19 //定义消费线程
 20 void *task2(void *arg)
 21 {
 22     int num=5;
 23     while(num--)
 24     {
 25         //3.申请资源
 26         sem_wait(&sem);//申请资源,value减1,为0时阻塞,无名信号量地址
 27         printf("消费三蹦子\n");
 28     }
 29     pthread_exit(NULL);
 30 }
 31 int main(int argc, const char *argv[])
 32 {
 33     //2.初始化无名信号量
 34     sem_init(&sem,0,0);
 35     //无名信号量地址,0线程间同步,当前无名信号量维护的value值初始值
 36     //创建两个线程,生产和消费
 37     pthread_t tid1,tid2;
 38     if(pthread_create(&tid1,NULL,task1,NULL)!=0)
 39     //线程号指针,线程属性,线程体(函数体),线程体的参数
 40     //成0败POSIX库中错误码,不能perror()
 41     {
 42         printf("tid1 create error\n");
 43         return 0;
 44     }
 45     if(pthread_create(&tid2,NULL,task2,NULL)!=0)
 46     {
 47         printf("tid2 create error\n");
 48         return 0;
 49     }
 50     printf("tid1:%#lx,tid2:%#lx\n",tid1,tid2);
 51     //回收线程资源
 52     pthread_join(tid1,NULL);//阻塞等待指定线程退出,收尸
 53     pthread_join(tid2,NULL);//要回收的线程号、要回收线程退出时状态
 54     //释放无名信号量
 55     sem_destroy(&sem);//无名信号量地址
 56     return 0;
 57 } 

运行结果:

(2)创建三个线程,线程1打印A,线程2打印B,线程3打印C

程序代码:

  1 #include<myhead.h>
  2 //创建无名信号量
  3 sem_t sem1,sem2,sem3;
  4 //定义线程1
  5 void *task1(void *arg)
  6 {
  7     int num=3;
  8     while(num--)
  9     {
 10         //3.申请资源
 11         sem_wait(&sem1);
 12         sleep(1);
 13         printf("A\t");
 14         //刷新给定文件指针缓冲区,要刷新的缓冲区
 15         //stdout标准输出指针
 16         fflush(stdout);
 17         //4.释放资源
 18         sem_post(&sem2);//释放无名信号量sem2的资源,value加1
 19     }
 20     //退出线程
 21     pthread_exit(NULL);
 22 }
 23 //定义线程2
 24 void *task2(void *arg)
 25 {
 26     int num=3;
 27     while(num--)
 28     {
 29         sem_wait(&sem2);//sem2资源-1
 30         sleep(1);
 31         printf("B\t");
 32         fflush(stdout);//输出没有\n,不刷新不会打印出来,等全部运行结束直接给出结果
 33         sem_post(&sem3);//sem3资源+1,sem3才能接着用
 34     }
 35     pthread_exit(NULL);
 36 }
 37 //定义线程3
 38 void *task3(void *arg)
 39 {
 40     int num=3;
 41     while(num--)
 42     {
 43         //申请资源sem3
 44         sem_wait(&sem3);
 45         sleep(1);
 46         printf("C\t");
 47         fflush(stdout);
 48         sem_post(&sem1);//释放sem1资源,
 49     }
 50     pthread_exit(NULL);
 51 }
 52 int main(int argc, const char *argv[])
 53 {
 54     //初始化无名信号量
 55     sem_init(&sem1,0,1);//无名信号量地址
 56     sem_init(&sem2,0,0);//0线程同步
 57     sem_init(&sem3,0,0);//初始资源为1,0
 58     //定义线程号变量
 59     pthread_t tid1,tid2,tid3;
 60     if(pthread_create(&tid1,NULL,task1,NULL)!=0)//创建线程分支
 61     {
 62         printf("tid1 create error\n");
 63         return 0;
 64     }
 65     if(pthread_create(&tid2,NULL,task2,NULL)!=0)//无名信号量地址,线程属性,线程体,线程体参数
 66     {
 67         printf("tid2 create error\n");
 68         return 0;
 69     }
 70     if(pthread_create(&tid3,NULL,task3,NULL)!=0)
 71     {
 72         printf("tid3 create error\n");
 73         return 0;
 74     }
 75     printf("tid1:%#lx,tid2:%#lx,tid3:%#lx\n",tid1,tid2,tid3);
 76     //回收线程资源
 77     pthread_join(tid1,NULL);
 78     pthread_join(tid2,NULL);
 79     pthread_join(tid3,NULL);
 80     //释放无名信号量
 81     sem_destroy(&sem1);
 82     sem_destroy(&sem2);
 83     sem_destroy(&sem3);
 84     puts("");
 85     return 0;
 86 }    

运行结果:

3.编程实现条件变量

程序代码:

  1 #include<myhead.h>
  2 //1.定义条件变量
  3 pthread_cond_t cond;
  4 //定义互斥锁变量
  5 pthread_mutex_t mutex;
  6 //定义生产线程
  7 void *task1(void *arg)
  8 {
  9     int num=5;
 10     while(num--)
 11     {
 12         sleep(1);
 13         printf("%#lx:生产三蹦子\n",pthread_self());
 14         //3.唤醒一个消费
 15     //  pthread_cond_signal(&cond);//条件变量地址
 16     }
 17     //3.唤醒所以的等待线程
 18     pthread_cond_broadcast(&cond);//条件变量地址
 19     //退出线程
 20     pthread_exit(NULL);
 21 }
 22 //定义消费线程
 23 void *task2(void *arg)
 24 {
 25     //上锁
 26     pthread_mutex_lock(&mutex);
 27     //进入等待队列
 28     pthread_cond_wait(&cond,&mutex);//条件变量指针,互斥锁变量地址
 29     //该函数内部实现
 30     //将当前线程放入休眠等待队列,释放锁资源
 31     //挂起,被其他线程唤醒后:自动获取锁资源
 32     printf("%#lx:消费三蹦子\n",pthread_self());
 33     //解锁
 34     pthread_mutex_unlock(&mutex);
 35     pthread_exit(NULL);
 36 }
 37 int main(int argc, const char *argv[])
 38 {
 39     //2.初始化条件变量
 40     pthread_cond_init(&cond,NULL);//条件变量指针,条件属性
 41     //初始化互斥锁
 42     pthread_mutex_init(&mutex,NULL);//互斥锁变量地址,互斥锁属性
 43     //创建两个线程,生产和消费
 44     pthread_t tid1,tid2,tid3,tid4,tid5,tid6;
 45     if(pthread_create(&tid1,NULL,task1,NULL)!=0)//线程号指针
 46     {
 47         printf("tid1 create error\n");//成0败非0错误码,不是置位错误码
 48         return 0;
 49     }
 50     if(pthread_create(&tid2,NULL,task2,NULL)!=0)//线程属性
 51     {
 52         printf("tid2 create error\n");
 53         return 0;
 54     }
 55     if(pthread_create(&tid3,NULL,task2,NULL)!=0)//线程体,函数指针
 56     {
 57         printf("tid3 create error\n");
 58         return 0;
 59     }
 60     if(pthread_create(&tid4,NULL,task2,NULL)!=0)//线程体的参数
 61     {
 62         printf("tid4 create error\n");
 63         return 0;
 64     }
 65     if(pthread_create(&tid5,NULL,task2,NULL)!=0)
 66     {
 67         printf("tid5 create error\n");
 68         return 0;
 69     }
 70     if(pthread_create(&tid6,NULL,task2,NULL)!=0)
 71     {
 72         printf("tid6 create error\n");
 73         return 0;
 74     }
 75     printf("tid1:%#lx,tid2:%#lx,tid3:%#lx,tid4:%#lx,tid5:%#lx,\
 76             tid6:%#lx\n",tid1,tid2,tid3,tid4,tid5,tid6);
 77     //回收线程资源
 78     pthread_join(tid1,NULL);//线程号,线程回收时状态
 79     pthread_join(tid2,NULL);
 80     pthread_join(tid3,NULL);
 81     pthread_join(tid4,NULL);
 82     pthread_join(tid5,NULL);
 83     pthread_join(tid6,NULL);
 84     //销毁条件变量
 85     pthread_cond_destroy(&cond);//条件变量指针
 86     //销毁互斥锁
 87     pthread_mutex_destroy(&mutex);//无名信号量地址
 88     return 0;
 89 }      

运行结果:

4.编程实现无名管道

程序代码:

  1 #include<myhead.h>
  2 int main(int argc, const char *argv[])
  3 {
  4     //创建管道文件,并返回该管道文件的文件描述符
  5     int pipefd[2]={0};//返回pipefd[0]读端,pipefd[1]写端
  6     if(pipe(pipefd)==-1)
  7     {
  8         perror("pipe error");
  9         return -1;
 10     }
 11     printf("pipe[0]=%d,pipe[1]=%d\n",pipefd[0],pipefd[1]);
 12     //创建子进程
 13     pid_t pid=fork();
 14     if(pid>0)
 15     {
 16         //父进程
 17         //关闭管道读端
 18         //创建管道文件放在创建子进程之前,否则各自创建一个管道,无意义
 19         //父进程、子进程都创建同一个管道描述符,
 20         //要关闭父进程的读端,子进程的写端
 21         close(pipefd[0]);//pipefd[0]    读
 22         char wbuf[128]="";
 23         while(1)
 24         {
 25             bzero(wbuf,sizeof(wbuf));//清空数组内容,
 26             //每次写入不同长度,写短了就会保留长的一部分
 27             fgets(wbuf,sizeof(wbuf),stdin);//终端输入数据
 28             wbuf[strlen(wbuf)-1]=0;//把读取的字符串,最后一个改为0,便于比较
 29             //将数据写入管道文件
 30             write(pipefd[1],wbuf,strlen(wbuf));//要操作的文件描述符,容器起始位置,读取大小
 31             //对写入数据判断
 32             if(strcmp(wbuf,"quit")==0)
 33                 break;
 34         }
 35         //关闭写端
 36         close(pipefd[1]);
 37         wait(NULL);//阻塞回收子进程资源
 38     }else if(pid==0)
 39     {
 40         //子进程
 41         //关闭写端
 42         close(pipefd[1]);
 43         char rbuf[128]="";
 44         while(1)
 45         {
 46             //清空rbuf内容
 47             bzero(rbuf,sizeof(rbuf));
 48             //从管道文件中读取数据
 49             read(pipefd[0],rbuf,sizeof(rbuf));
 50             //输出rbuf的数据
 51             printf("父进程传来数据:%s\n",rbuf);
 52             //对读取的数据判断
 53             if(strcmp(rbuf,"quit")==0)
 54                 break;
 55         }
 56         //关闭读端
 57         close(pipefd[0]);
 58         exit(EXIT_SUCCESS);//退出进程
 59     }else
 60     {
 61         perror("fork error");
 62         return -1;
 63     }
 64     return 0;
 65 }     

运行结果:

5.编程实现有名管道

程序代码:

create.c:

  1 #include<myhead.h>
  2 int main(int argc, const char *argv[])
  3 {
  4     //创建一个管道文件
  5     if(mkfifo("./myfifo",0664)==-1)
  6     {
  7         perror("mkfifo error");
  8         return -1;
  9     }
 10     getchar();//阻塞
 11     system("rm myfifo");
 12 
 13     return 0;
 14 }   

send.c:

  1 #include<myhead.h>
  2 int main(int argc, const char *argv[])
  3 {
  4     //打开管道文件
  5     int wfd=-1;
  6     //以只写形式打开
  7     if((wfd=open("./myfifo",O_WRONLY))=
  8     {
  9         perror("open error");
 10         return -1;
 11     }
 12     //定义容器
 13     char wbuf[128]="";
 14     while(1)
 15     {
 16         printf("请输入>>>");
 17         fgets(wbuf,sizeof(wbuf),stdin);
 18         wbuf[strlen(wbuf)-1]=0;
 19         //将数据写入管道
 20         write(wfd,wbuf,strlen(wbuf));
 21         //判断结果
 22         if(strcmp(wbuf,"quit")==0)
 23             break;
 24     }
 25     //关闭文件
 26     close(wfd);
 27     return 0;
 28 }   

rec.c:

  1 #include<myhead.h>
  2 int main(int argc, const char *argv[])
  3 {
  4     //打开管道文件
  5     int rfd=-1;
  6     //以只读形式打开
  7     if((rfd=open("./myfifo",O_RDONLY))=
  8     {
  9         perror("open error");
 10         return -1;
 11     }
 12     //定义容器
 13     char rbuf[128]="";
 14     while(1)
 15     {
 16         //清空数组
 17         bzero(rbuf,sizeof(rbuf));
 18         //读取管道中数据
 19         read(rfd,rbuf,sizeof(rbuf));
 20         //输出结果
 21         printf("收到数据:%s\n",rbuf);
 22         if(strcmp(rbuf,"quit")==0)
 23             break;
 24     }
 25     //关闭文件
 26     close(rfd);
 27     return 0;
 28 }    

运行结果:

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

程序代码:

01create:

  1 #include<myhead.h>
  2 int main(int argc, const char *argv[])
  3 {
  4     //创建两个管道文件
  5     if(mkfifo("./myfifo1",0664)==-1)
  6     {
  7         perror("myfifo1 create error");
  8         return -1;
  9     }
 10     if(mkfifo("./myfifo2",0664)==-1)
 11     {
 12         perror("myfifo2 create error");
 13         return -1;
 14     }
 15     printf("create success\n");
 16     getchar();//阻塞进程
 17     system("rm myfifo1 myfifo2");//删除两>
 18     return 0;
 19 }

01send.c:

  1 #include<myhead.h>
  2 int main(int argc, const char *argv[])
  3 {
  4     //两个进程,父进程给管道1写数据,子进程从管道2读取数据
  5     pid_t pid=-1;
  6     pid=fork();
  7     if(pid==0)
  8     {
  9         //子进程管道2读取数据
 10         int rfd=-1;
 11         if((rfd=open("./myfifo2",O_RDONLY))==-1)
 12         {
 13             perror("open myfifo2 error");
 14             return -1;
 15         }
 16         char buf[128]="";
 17         while(1)
 18         {
 19             bzero(buf,sizeof(buf));//清空数组
 20             read(rfd,buf,sizeof(buf));//从管道2读取数据
 21             printf("读取数据:%s\n",buf);
 22             if(strcmp(buf,"quit")==0)
 23                 break;
 24         }
 25         //关闭文件
 26         close(rfd);
 27         //退出进程
 28         exit(EXIT_SUCCESS);
 29     }else if(pid>0)
 30     {
 31         //父进程向管道1写数据
 32         int wfd=-1;
 33         if((wfd=open("./myfifo1",O_WRONLY))==-1)
 34         {
 35             perror("open myfifo1 error");
 36             return -1;
 37         }
 38         char buf[128]="";
 39         while(1)
 40         {
 41             bzero(buf,sizeof(buf));//清空数组
 42             fgets(buf,sizeof(buf),stdin);
 43             buf[strlen(buf)-1]=0;
 44             //将数据写入管道
 45             write(wfd,buf,strlen(buf));
 46             if(strcmp(buf,"quit")==0)
 47                 break;
 48         }
 49         //关闭文件
 50         close(wfd);
 51         //回收子进程资源
 52         wait(NULL);
 53     }else
 54     {
 55         perror("fork error");
 56         return -1;
 57     }
 58     return 0;
 59 }         

02send.c:

  1 #include<myhead.h>
  2 int main(int argc, const char *argv[])
  3 {
  4     //两个进程,父进程读取管道1数据,子进程写数据给管道2
  5     pid_t pid=-1;
  6     pid=fork();
  7     if(pid<0)
  8     {
  9         perror("fork error");
 10         return -1;
 11     }else if(pid==0)
 12     {
 13         //子进程写数据给管道2
 14         int wfd=-1;
 15         if((wfd=open("./myfifo2",O_WRONLY))==-1)
 16         {
 17             perror("open myfifo2 error");
 18             return -1;
 19         }
 20         char buf[128]="";
 21         while(1)
 22         {
 23             bzero(buf,sizeof(buf));//清空数组
 24             fgets(buf,sizeof(buf),stdin);
 25             buf[strlen(buf)-1]=0;
 26             //写入数据
 27             write(wfd,buf,strlen(buf));
 28             if(strcmp(buf,"quit")==0)
 29                 break;
 30         }
 31         //关闭文件
 32         close(wfd);
 33         //退出进程
 34         exit(EXIT_SUCCESS);
 35     }else
 36     {
 37         //父进程读取管道1
 38         int rfd=-1;
 39         if((rfd=open("./myfifo1",O_RDONLY))==-1)
 40         {
 41             perror("open myfifo1 error");
 42             return -1;
 43         }
 44         char buf[128]="";
 45         while(1)
 46         {
 47             bzero(buf,sizeof(buf));
 48             //读取数据
 49             read(rfd,buf,sizeof(buf));
 50             printf("读取数据:%s\n",buf);                             
 51             if(strcmp(buf,"quit")==0)
 52                 break;
 53         }
 54         //关闭文件
 55         close(rfd);
 56         wait(NULL);//回收子进程资源
 57     }
 58     return 0;
 59 }

运行结果:

流程图:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值