12----进程间的通信:管道

来源:互联网 发布:游戏编程培训学费多少 编辑:程序博客网 时间:2024/05/09 08:37

一. IPC

        1. 基于文件

                 1.1 无序文件

                 1.2 有序文件

                             管道:

                                          有名

                                           无名

                                               socket

       2. 基于内存

                2.1 无序内存

                          2.1.1 匿名内存

                          2.1.2 共享内存

               2.2 有序内存

                           2.2.1 消息队列

      3. 同步:基于内存IPC应用(共享内存数组)

               信号量/ 信号灯



二. 命名管道(FIFO)

        命名管道是一种特殊类型的文件。

     1.创建管道文件

       #include <sys/types.h>
       #include <sys/stat.h>

       int mkfifo(const char *pathname, mode_t mode);

案例:

(1)fifoA.c 文件

    建立管道文件

    打开管道文件

    写数据

    关闭管道文件

    删除管道

(2) fifoB.c

     打开管道

     读数据

     关闭管道


// fifoA.c#include <stdio.h>#include <fcntl.h>#include <unistd.h>#include <sys/stat.h>#include <stdlib.h>#include <string.h>#include <signal.h>int fd;int i = 0;const char *filename = "/tmp/my.pipe";void deal(int s){// 3.关闭管道   close(fd);//4.删除管道unlink(filename);exit(0);}main(){signal(SIGINT,deal);//1. 建立管道mkfifo( filename,0666);//2. 打开管道fd = open(filename,O_RDWR);while(1){ // 每个1s写数据sleep(1);write(fd,&i,sizeof(4));++i;}}

// fifoB.c#include <stdio.h>#include <fcntl.h>#include <unistd.h>#include <sys/stat.h>#include <stdlib.h>#include <string.h>#include <signal.h>int fd;const char* filename = "/tmp/my.pipe";void deal(int s){// 关闭管道close(fd);exit(-1);}main(){int i;signal(SIGINT,deal);//建立管道mkfifo(filename,0666);// 打开管道fd = open(filename,O_RDWR);// 读取数据while(1){read(fd,&i,sizeof(i));printf("%d\n",i);}}

实例解析: 程序A循环发送数据,程序B循环接收数据。无论那个程序接收到中断信号(Ctrl + C),都会执行FIFO文件的删除工作

总结:

       (1)read没有数据,read就会阻塞,程序挂起。而read后数据是被删除的。

       (2)数据有序。

       (3)打开的描述符号可以读写(two-way 双工)

       (4)管道文件关闭后,数据不持久。

       (5)管道的数据存储在内核缓冲中。(可以说数据没有写入文件中)

三.匿名管道

     有名管道的名字仅仅是内核,是否返回一个fd标识(zhi)符。

     在父子进程之间: 打开文件描述符后创建进程。

     父子进程都有文件描述符。管道文件名没有价值了。

    所以在父子进程中引入一个没有名字的管道: 匿名管道。

    结论: 匿名管道只能使用在父子进程之间。

    1. 匿名管道的创建

       #include <unistd.h>

       int pipe(int pipefd[2]);

       #define _GNU_SOURCE             /* See feature_test_macros(7) */
       #include <fcntl.h>              /* Obtain O_* constant definitions */
       #include <unistd.h>

       int pipe2(int pipefd[2], int flags);

     fd[0]: 只读(不能写)

     fd[1]: 只写(不能读)

案例: 匿名管道的创建。


#include <unistd.h>#include <stdlib.h>#include <stdio.h>#include <string.h>int main(){int fd;int file_pipes[2];const char data[] ="自强不息,知行合一";char bufer[BUFSIZ + 1];memset(bufer,0,sizeof(bufer));if(pipe(file_pipes) == 0){if(fork() == 0) // child{    //sleep(1);fd = read(file_pipes[0],bufer,BUFSIZ);printf("Read %d bytes:%s\n",fd,bufer);exit(0);}else // fild{fd = write(file_pipes[1],data,strlen(data));printf("Wrot %d bytes\n",fd);}}exit(0);}

实验解析: 这个程序使用 pipe 函数创建一个管道,接着fork函数创建一个新进程。创建成功后,父进程写数据到管道中,而子进程从管道中读取数据。

综合案例:

            (1)建立两个子进程:

                  一个负责计算: 1-50000 的素数

                  另一个负责计算: 50001-1000000

           (2) 父进程负责存储。

//demo2.c#include <stdio.h>#include <unistd.h>#include <signal.h>#include <stdlib.h>#include <string.h>#include <fcntl.h>int idx = 0;int fddata;/// 信号处理函数void deal(int s){int status;if(s == SIGCHLD){wait(&status);idx++;if(idx == 2){close(fddata);printf("任务完成\n");exit(-1);}}}int isprimer(int s){int i = 2;for(i; i<s; ++i){if(s%i== 0)return 0;}return 1;}main(){int a,b;int id = 1;int fd[2];signal(SIGCHLD,deal);pipe(fd);/// 创建有名管道while(1){if(id == 1){a=2;b=50000;}if(id == 2){a=50001;b=100000;}if(fork()){id++;if(id > 2)break;continue;}else{ /// 子进程int i;close(fd[0]);for(i=a; i<=b;++i){if(isprimer(i)){write(fd[1],&i,sizeof(int));}}printf("[%d]任务完成!\n",getpid());exit(0);}}int re;char buf[20];// 打开文件准备存储close(fd[1]);fddata = open("/tmp/result.txt",O_RDWR | O_CREAT,0666);while(1)// 父进程{read(fd[0],&re,sizeof(int));sprintf(buf,"%d\n",re);write(fddata,buf,strlen(buf)); ///以流的方式写入文件}}


————————————————————————————————
$ cat  resut.txt   查看
$ cat resut.txt | more 10 --- 每次只显示10个数据
________________________________





  

    



0 0
原创粉丝点击