进程间通信——管道(有名管道、无名管道)

来源:互联网 发布:ubuntu安装 虚拟机 编辑:程序博客网 时间:2024/05/22 07:59

进程间通信:多个进程之间数据相互交换。
进程间通信的方式:信号、管道(无名管道、有名管道)、信号量、消息队列、共享内存、套接字。
进程的创建:pid_t fork(void);

管道的原理:
这里写图片描述
有名管道:应用于两个进程之间数据的单向传递。
创建:命令方式:mkfifo 函数方式:mkfifo()
打开:open
写数据:write
读数据:read
关闭:close
在文件目录数中有一个文件标示(管道文件)实际不占据磁盘空间,数据缓存在内存上。
阻塞运行函数:函数调用后不会立即返回,需要等待某些条件的发生才会返回,open操作管道文件时,阻塞运行的函数。
如果一个进程以只写(读)方式打开一个管道文件,open会阻塞运行,直到有一个以读(写)方式打开管道文件,open才会返回,进程才会接着运行。
read函数也会阻塞运行,直到写端写入数据或者所有的写端都关闭,read读取数据并且会将内存上的已读数据清空。

void mian(){    int fd = open("FIFO",O_WRONLY);    if(fd == -1)    {        exit(0);    }    printf("FIFO open success\n");    //sleep(10);    write(fd,"hello world",11);    printf("write success\n");    close(fd);}void main(){    int fd = open("FIFO",O_RDONLY);    if(fd == -1)    {        exit(0);    }    printf("FIFO open success\n");    char buff[128] = {0};    read(fd,buff,127);    printf("read data:%s\n",buff);    close(fd);}

练习:A 进程负责循环接受用户输入的数据, 以”end”为结束标志, B 进程负责统计用户输入的字母个数。

//testa 接受用户输入的数据,以end为结束标志#include <stdio.h>#include <stdlib.h>#include <fcntl.h>#include <string.h>void main(){    int fd = open("FIFO",O_WRONLY);    if(fd == -1)    {        exit(0);    }    while(1)    {        printf("please input:");        fflush(stdout);        char arr[128] = {0};        fgets(arr,127,stdin);        write(fd,arr,strlen(buff)-1);        if(strncmp(buff,"end",3) == 0)        {            break;        }    }    close(fd);}//testb 统计用户输入的字母个数#include <stdio.h>#include <stdlib.h>#include <fcntl.h>#include <string.h>void main(){    int fd = open("FIFO",O_RDONLY);    if(fd == -1)    {        exit(0);    }    while(1)    {        char buff[128] = {0};        int count = 0;         read(fd,buff,127);        if(strncmp(buff,"end",3) == 0)        {            break;        }        count += strlen(buff);        printf("%d\n",count);        }    }    close(fd);}

无名管道:无名是相对于有名而言的,其在使用时产生,不使用后释放。不会在系统上留下蛛丝马迹。因为它在使用前没有任何标示,所以它只能用于父子进程之间。
创建与打开:int pipe(int fd[2]) 若成功则返回0,失败返回-1。fd[0]代表读, fd[1]代表写。
读:read(fd[]0],buff,size);
写:write(fd[1],buff,len);
关闭:close(fd[1]); close(fd[0]);
使用:int arr[2]; pipe(arr);
需要注意的是:管道都是半双工通讯, 无名管道创建后,父进程在 fork 产生子进程后,两个进程分别有一对读写,要在父子进程分别关闭读或写。

与上面相同的例题,用无名管道来做:

void main(){    int fd[2] = {0};    pipe(fd);    pid_t pid = fork();    if(pid == 0)    {        while(1)        {            close(fd[0]);            printf("please input:");            fflush(stdout);            fgets(buff,127,stdin);            write(fd[1],buff,strlen(buff)-1);            if(strncmp(buff,"end",3) == 0)            {                break;            }        }    }    else    {        close(fd[1]);        while(1)        {            int count = 0;             read(fd[0],buff,127);            if(strncmp(buff,"end",3) == 0)            {                break;            }            count += strlen(buff);            printf("%d\n",count);        }    }    close(fd[0]);    close(fd[1]);}
阅读全文
1 0