进程间通信(pipie、ctime、access、fifo、fifo_fork)

声明:

1、进程间通信,即进程与进程进行信息交换,两个进程必须处于运行,否则,通信结束
2、管道分为有名管道和无名管道都为半双工通信(数据流是单向的)
3、通信,即信息交互需求不同,方式不同(电话、发电报、发邮箱、微信等等)

普通管道

概念:

无名管道,只能用于解决具有共同祖先进程之间的通信(必须具有亲缘关系)

步骤:

1、fork出一个进程
2、pipie出一根管道
3、关闭不使用的文件描述符,操作,关闭使用过的文件描述符

半双工通信

这里写图片描述

 84 #include<stdio.h>
 85 #include<unistd.h>
 86 #include<string.h>
 87 int main()
 88 {
 89     char *msg="Hello Pipe";
 90     int fd[2];
 91     int res= pipe(fd);
 92     pid_t pid = fork();
 93     if(pid>0)
 94     {
 95         close (fd[0]);
 96         write(fd[1],msg,strlen(msg)+1);
 97         close (fd[1]);
 98     }
 99     else if(pid == 0)
100     {
101         close (fd[1]);
102         //建议
103         char buffer[256];
104         read(fd[0],buffer,256);
105         printf("From Parent Meg %s\n",buffer);
106         close (fd[0]);
107     }
108     else
109         perror("fork");
110     return 0;
111 }

用两根管道模拟全双工通信

这里写图片描述

1 #include<stdio.h>
  2 #include<unistd.h>
  3 #include<stdlib.h>
  4 #include<string.h>
  5 #include<time.h>
  6 int main()
  7 {
  8     char *parent_talk[]={"Hello","What time is it now?","I have no time ,byebye",NULL};
  9     char *child_talk[]={"Hi","No problem","byebye",NULL};
 10     int fd1[2];
 11     int fd2[2];
 12     int res = pipe(fd1);
 13     if(res == -1)
 14     {
 15         printf("Creat Pipe1 Fail\n");
 16         exit(1);
 17     }
 18     res = pipe(fd2);
 19     if(res == -1)
 20     {
22         exit(1);
 23     }
 24     pid_t pid = fork();
 25     if(pid>0)
 26     {
 27         close(fd1[0]);
 28         close(fd2[1]);
 29         int i=0;
 30         char buffer[256];
 31         char *parent = parent_talk[i];
 32         while(parent != NULL)
 33         {
 34             write(fd1[1],parent,strlen(parent)+1);
 35             read(fd2[0],buffer,256);
 36             printf("From Child >%s\n",buffer);
 37             i++;
 38             parent = parent_talk[i];
 39         }
 40         close(fd1[1]);
 41         close(fd2[0]);
 42     }
 43     else if(pid == 0)
 44     {
 45         close(fd1[1]);
 46         close(fd2[0]);
 47         int i= 0;
 48         char buffer[256];
 49         char *child = child_talk[i];
 50         while(child != NULL)
 51         {
 52             read(fd1[0],buffer,256);
 53             printf("From Parent >%s\n",buffer);
 54             if(i == 1)
 55             {
 56                 time_t tt;
 57                 time(&tt);
 58                 char buffer[256];
 59                 //printf("%s",ctime(&tt));
 60                 memset(buffer,0,256);
 61                 sprintf(buffer,"%s %s",child,ctime(&tt));
 62                 //printf("buffer=%s\n",buffer);
 63                 write(fd2[1],buffer,strlen(buffer)+1);
 64             }
 65             else
 66             {
 67                 write(fd2[1],child,strlen(child)+1);
 68             }
 69             i++;
 70             child = child_talk[i];
 71         }
 72 
 73         close(fd1[0]);
 74         close(fd2[1]);
 75     }
 76     else
 77     {
 78         perror("fork");
 79     }
 80     return 0;
 81 }

这里写图片描述

获取当前日期和时间

//必须加上头文件#include<time.h>
time_t tt;//时间结构体
time(&tt);//时间种子
printf("%s",ctime(&tt));//获取时间

命名管道

概念:

命名管道:最大优点可以实现非亲缘关系的进程之间的通信,常见模型:服务器与客户端模型

理解:

命名管道即是对文件的操作,利用文件描述符来进行操作

步骤:

1、建立管道文件
2、打开管道,进行操作
3、关闭文件描述符

access函数,用于检查文件

//条件成立返回0,不成立返回-1
 int access(const char *path, int amode);
 amode:R_OK, W_OK, F_OK 用于检查

这里写图片描述
解释:

write_fifo和read_fifo,这两根管道,在服务器的角度命名
2、服务器一直开着,客户端可以断掉
3、实现一直良好通信原因是因为:write、read均属于阻塞函数

实现

一句一句回应


//uitli.h
 #pragma once
  2 #include<stdio.h>
  3 #include<unistd.h>
  4 #include<sys/stat.h>
  5 #include<fcntl.h>
  6 #include<string.h>
  7 #include<stdlib.h>
  8 const char *write_fifo ="write_fifo";
  9 const char *read_fifo = "read_fifo";
//Ser.c
 1 #include"utili.h"
  2 int main()
  3 {
  4     //看管道文件是否存在,不存在新建
  5     if(access(write_fifo,F_OK) != 0)
  6     {
  7          int res = mkfifo(write_fifo,O_CREAT|O_EXCL|0755);
  8         if(res == -1)
  9         {
 10             perror(" fifo");
 11             exit(1);
 12         }
 13     }
 14     //打开管道
 15     printf("12345678\n");
 18     {
 19         perror("write_fd");
 20         exit(1);
 21     }
 22     int read_fd;
 23     printf("222222222222222222\n");
         //打开读管道,看客户端是否开启
 24     while((read_fd=open(read_fifo,O_RDONLY))== -1)
 25     {
 26         printf("Client not start up.\n");
 27         sleep(1);
 28     }
         //进行操作
 29     char send_buf[256];
 30     char recv_buf[256];
 31     while(1)
 32     {
 33         printf("Ser>");
 34         scanf("%s",send_buf);
 35         write(write_fd,send_buf,strlen(send_buf)+1)    ;
 36         printf("Cli>");
 37         read(read_fd,recv_buf,256);
 38         printf("%s\n",recv_buf);
 39     }
         //关闭文件描述符
 40     close(write_fd);
 41     colse(read_fd);
 42     return 0;
 43 }
//Cli.c
  1 #include"utili.h"
  2 int main()
  3 {
  4     printf("rdrdrdrdrdrdrdrdrrd\n");
  5     int read_fd;
          //打开读管道 (对于服务器为写管道)
  6     read_fd = open(write_fifo,O_RDONLY);
  7     if(read_fd == -1)
  8     {
  9         perror("read_fd");
 10         exit(1);
 11     }
         //判断读文件书否存在,不存在,则新建
 12     if(access(read_fifo,F_OK) !=0)
 13     {
            int res = mkfifo(read_fifo,O_CREAT|O_EXCL|0755);     
 15         if(res == -1)
 16         {
 19             exit(1);
 20         }
 21     }
         //打开写管道(对于服务器是写管道)
 22     int write_fd = open(read_fifo,O_WRONLY);
 23     if(write_fd == -1)
 24     {
 25         perror("write_fd");
 26         exit(1);
 27     }
 28     char send_buf[256];
 29     char recv_buf[256];
 30     while(1)
 31     {
 32         read(read_fd,recv_buf,256);
 33         printf("Ser>%s\n",recv_buf);
 34         printf("Cli>");
 35         scanf("%s",send_buf);
 36         write(write_fd,send_buf,strlen(send_buf+1));
 37     }
 38     close(read_fd);
 39     colse(write_fd);
 40     return 0;
 41 }
//Makefile
1 all: ser cli
  2 ser:
  3     gcc -o ser ser.c
  4 cli:
  5     gcc -o cli cli.c
  6 clean:
  7     rm ser cli
  8 

result

这里写图片描述

可以重复发送
原理:利用多进程实现,用两个子进程来实现,一个专门用来 读,另一个专门用来写

这里写图片描述

实现

//utili.h
  1 #pragma once
  2 #include<stdio.h>
  3 #include<unistd.h>
  4 #include<sys/stat.h>
  5 #include<fcntl.h>
  6 #include<string.h>
  7 #include<stdlib.h>
  8 const char *write_fifo ="write_fifo";
  9 const char *read_fifo = "read_fifo";
 10 void write_msg(int fd);
 11 void read_msg(int fd);
 12 

利用多进程实现可以发多句信息

//ser.c
1 #include"utili.h"
  2 int main()
  3 {
  4     //创建管道
  5     if(access(write_fifo,F_OK) != 0)
  6     {
  7         int res = mkfifo(write_fifo,O_CREAT|O_EXCL|0755);
  8         if(res == -1)
  9         {
 10             perror(" fifo");
 11             exit(1);
 12         }
 13     }
 14     //打开管道
 15     int write_fd = open(write_fifo,O_WRONLY);
 16     if(write_fd == -1)
 17     {
 18         perror("write_fd");
 19         exit(1);
 20     }
 21     int read_fd;
 22     while((read_fd=open(read_fifo,O_RDONLY))== -1)
 23     {
 24         printf("Client not start up.\n");
 25         sleep(1);
 26     }
 27     pid_t pid = fork();
         //2
 28     if(pid == 0)
 29     {
 30         //write
 31         write_msg(write_fd);
 32     }
 33     else if(pid > 0)
 34     {
 35         pid = fork();
             //1
 36         if(pid == 0)
 37         {
 38             //read
 39             read_msg(read_fd);
 40         }
             // 0
 41         else if(pid >0)
 42         {
 43             int status;
 44             wait(&status);
 45             close(write_fd);
 46             close(read_fd);
 47         }
 48         else
 49             perror("fork");
 50     }
 51     else
 52     {
 53         perror("fork");
 54     }
 55     return 0;
 56 }
 57 void write_msg(int fd)
 58 {
 59     char buf[256];
 60     while(1)
 61     {
 62 
 63         printf("Ser>");
 64         scanf("%s",buf);
 65         if(!strcmp(buf,"quit"))
 66         {
 67             break;
 68         }
 69         write(fd,buf,strlen(buf)+1);
 70     }
 71 }
 72     void read_msg(int fd)
 73     {
 74         char buf[256];
 75         while(1)
 76         {
 77             read(fd,buf,256);
 78             printf("Cli>%s\n",buf);
 79         }
 80     }
//Cli.c
1 #include"utili.h"
  2 int main()
  3 {
        int read_fd = open(write_fifo,O_RDONLY);
  4     if(read_fd == -1)
  5     {
  6         perror("read_fd");
  7         exit(1);
  8     }   
  9     if(access(read_fifo,F_OK) !=0)
 10     {   
 11         int res = mkfifo(read_fifo,O_CREAT|O_EXCL|0755);
 12         if(res == -1)
 13         {
 14             perror("read_fifo");
 15             close(read_fd);
 16             exit(1);
 17         }   
 18     }       
 19     int write_fd = open(read_fifo,O_WRONLY);
 20     if(write_fd == -1)
 21     {
 22         perror("write_fd");
 23         exit(1);
 24     }
 25     pid_t pid = fork();
        //2
 26     if(pid==0)
 27     {
 28         //write
 29         write_msg(write_fd);
 30     }
 31     else if(pid>0)
 32     {
 33         pid = fork();
            // 1
 34         if(pid == 0)
 35         {
 36             //read
 37             read_msg(read_fd);
 38         }
            //0
 39         else if(pid >0)
 40         {
 41             int status;
 42             wait(&status);
 43         }
 44         else
 45         {
 46             perror("fork");
 47         }
 48     }
 49     else
 50     {
 51         perror("fork");
 52     }
 53 
 54 
 55     return 0;
 56 }
 57 void read_msg(int fd)
 58 {
 59     char buf[256];
 60     while(1)
 61     {
 62         read(fd,buf,256);
 63         printf("Ser>%s\n",buf);
 64     }
 65 
 66 }
 67 void write_msg(int fd)
 68 {
 69     while(1)
 70     {
 71 
 72         printf("Cli>");
 73         char buf[256];
 74         scanf("%s",buf);
 75         if(!strcmp(buf,"quit"))
 76             break;
 77         write(fd,buf,strlen(buf)+1);
 78     }
 79 }

阻塞函数&非阻塞函数

阻塞函数:我要以写打开,必须对面一定要有为读打开,不然阻塞在写操作;若要以只读方式打开,必须有以为读打开的写文件,不然一直阻塞在读操作
非阻塞函数:虽然不阻塞,但是打开又不成功

非阻塞函数:

1、read() write()

总结:

1、熟悉pipe、fifo管道以及优缺点
2、掌握常用的几个函数ctime 、access函数
3、阻塞函数与非阻塞函数
4、使用多进程实现重复发消息,用不同的进程负责读或者写操作

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值