管道

1.知识

(1)管道的局限性

  管道有两个局限性:

  【1】半双功

  【2】只能在具有公共祖先进程之间使用

 

(2)建立管道

int pipe(int filedes[2]);

 filedes返回两个文件描述符,filedes[0] 为读而打开,filedes[1]为写而打开,filedes[1]的输出是filedes[0]的输入

 

单个进程的管道没有任何用处,但由于管道存在于内核,fork后会复制文件描述符,于是父子进程可以通过管道进行通信。

当管道一端被关闭后,下列两条规则起作用:

  【1】读一个写端关闭的管道,在所有数据都被读取后,read返回0,以指示到达文件结束。

  【2】写一个读端关闭的管道,会产生 SIGPIPE。SIGPIPE的默认动作是abort,如果捕捉或忽略,write返回-1,errno设置为EPIPE。

 

管道的缓存大小由 PIPE_BUF 决定,使用 pathconf 和 fpathconf 函数可以确定 PIPE_BUF 的值。

如果对管道 write,并且写的字节数小于 PIPE_BUF,则此操作不会与其他进程对同一管道的write操作穿插。

如果有多个进程对管道进行write,并且写的字节书大于PIPE_BUF,则写操作的数据可能穿插进行。

 

2.应用

(1)父子进程普通数据通信

#include <unistd.h>
#include <stdio.h>

int main()
{
        int pid = -1;
        int fd[2];
        char buf[BUFSIZ] = {0};
        int n;

        pipe(fd);
        if (pipe(fd) < 0)
                perror("pipe");
        pid = fork();
        if (pid < 0) {
                perror("fork");
                goto __end__;
        } else if (pid > 0) {
                close(fd[0]);
                fd[0] = -1;
                write(fd[1], "hello world\n", 12);
        } else {
                close(fd[1]);
                fd[1] = -1;
                n = read(fd[0], buf, sizeof(buf));
                write(STDOUT_FILENO, buf, n);
        }

__end__:
        if (fd[0] != -1)
                close(fd[0]);
        if (fd[1] != -1)
                close(fd[1]);

        return 0;
}

 (2)与exec连用

 

 (3)父子进程同步

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>



struct pipe_sync {
        int pfd1[2];
        int pfd2[2];

        void (*wait_child)(struct pipe_sync *);
        void (*wait_parent)(struct pipe_sync *);
        void (*tell_child)(struct pipe_sync *);
        void (*tell_parent)(struct pipe_sync *);
        void (*init_child)(struct pipe_sync *);
        void (*init_parent)(struct pipe_sync *);
};

void wait_child(struct pipe_sync *);
void wait_parent(struct pipe_sync *);
void tell_child(struct pipe_sync *);
void tell_parent(struct pipe_sync *);
void init_child(struct pipe_sync *);
void init_parent(struct pipe_sync *);

struct pipe_sync *pipe_sync_new()
{
        struct pipe_sync * psync = (struct pipe_sync *)malloc(sizeof(struct pipe_sync));
        if (psync == NULL) {
                perror("malloc");
                goto __end__;
        }

        if (pipe(psync->pfd1) < 0) {
                perror("pipe pfd1");
                psync->pfd1[0] = -1;
                psync->pfd1[1] = -1;
        }
        if (pipe(psync->pfd2) < 0) {
                perror("pipe pfd2");
                psync->pfd2[0] = -1;
                psync->pfd2[1] = -1;
        }

        psync->wait_child = wait_child;
        psync->wait_parent = wait_parent;
        psync->tell_child = tell_child;
        psync->tell_parent = tell_parent;
        psync->init_child = init_child;
        psync->init_parent = init_parent;
__end__:
        return psync;
}

void pipe_sync_free(struct pipe_sync **psync)
{
        struct pipe_sync *tmp = *psync;

        if (tmp == NULL)
                return;
        if (tmp->pfd1[0] != -1)
                close(tmp->pfd1[0]);
        if (tmp->pfd1[1] != -1)
                close(tmp->pfd1[1]);
        if (tmp->pfd2[0] != -1)
                close(tmp->pfd2[0]);
        if (tmp->pfd2[1] != -1)
                close(tmp->pfd2[1]);
        free(tmp);
        *psync = NULL;
}

int main()
{
        struct pipe_sync *psync = NULL;
        int pid = -1;
        int ret = 0;

        psync = pipe_sync_new();
        if (psync == NULL) {
                printf("Failed to init psync\n");
                goto __end__;
        }

        pid = fork();
        if (pid < 0) {
                perror("fork");
                ret = -1;
                goto __end__;
        }
        else if (pid == 0) {
                psync->init_child(psync);
                printf("child wait\n");
                psync->wait_parent(psync);
                printf("child get ack\n");
                sleep(2);
                printf("child ok\n");
                printf("child tell\n");
                psync->tell_parent(psync);
        }
        else {
                psync->init_parent(psync);
                sleep(2);
                printf("parent ok\n");
                printf("parent tell\n");
                psync->tell_child(psync);
                psync->wait_child(psync);
                printf("parent get ack\n");
        }

__end__:
        pipe_sync_free(&psync);

        return ret;
}

void wait_child(struct pipe_sync *psync)
{
        char c;

        if (psync == NULL) {
                printf("wait_child : psync == NULL\n");
                return;
        }
        if (read(psync->pfd2[0], &c, 1) != 1)
                printf("wait_child : read err\n");
        if (c != 'c')
                printf("wait_child : incorrect data\n");
}
void wait_parent(struct pipe_sync *psync)
{
        char c;

        if (psync == NULL) {
                printf("wait_parent : psync == NULL\n");
                return;
        }
        if (read(psync->pfd1[0], &c, 1) != 1)
                printf("wait_parent : read err\n");
        if (c != 'p')
                printf("wait_parent : incorrent data\n");
}
void tell_child(struct pipe_sync *psync)
{
        if (psync == NULL) {
                printf("tell_child : psync == NULL\n");
                return;
        }
        if (write(psync->pfd1[1], "p", 1) != 1)
                printf("tell_child : write err\n");
}
void tell_parent(struct pipe_sync *psync)
{
        if (psync == NULL) {
                printf("tell_parent : psync == NULL\n");
                return;
        }
        if (write(psync->pfd2[1], "c", 1) != 1)
                printf("tell_parent : write err\n");
}
void init_parent(struct pipe_sync *psync)
{
        if (psync == NULL) {
                printf("init_parent : psync == NULL\n");
                return;
        }
        close(psync->pfd1[0]);
        close(psync->pfd2[1]);
}
void init_child(struct pipe_sync *psync)
{
        if (psync == NULL) {
                printf("init_child : psync == NULL\n");
                return;
        }
        close(psync->pfd1[1]);
        close(psync->pfd2[0]);
}

 

转载于:https://www.cnblogs.com/yangxinrui/p/11331785.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值