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

进程间通信:多个进程之间数据相互交换。
进程间通信的方式:信号、管道(无名管道、有名管道)、信号量、消息队列、共享内存、套接字。
进程的创建: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]);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值