ipc_pipe

Posted ilove-haha

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ipc_pipe相关的知识,希望对你有一定的参考价值。

管道是最早的用来实现进程间通信的技术,有管道和FIFO(有名管道)之分,前者只能用于有继承关系的进程间通信,后者用于无继承(无fork() )关系进程间通信。

管道的内容存在于内核中,一个管道就是一个字节流。

使用管道注意的事项:

1)如果从空的管道中读取数据会被阻塞直到至少余一个字节被写入管道中为止。如果管道写入端关闭,读完管道中的数据后read()返回0.

2)管道是单向的。

3)当写入管道的数据不超过PIPE_BUF(Linux上4096)字节的操作是原子的!在多进程中要注意,否则数据不同步。

4)管道的容量是有限的,当写入管道的数据达到一定限度后在往该管道写入数据会被阻塞直到从该管道中移除部分数据。

两个进程要进行通信,一般都是要先使用pipe()创建管道后调用fork()生成子进程。

以下使用两个管道在两个进程间进行双向数据传送。

要注意的是父进程和子进程关闭管道的一些出口或入口是因为使用fork()后父子进程共享相同的打开文件。

#include<unistd.h>
#include<sys/wait.h>  //waitpid()
#include<string.h>  
#include<stdio.h>

#include<sys/stat.h>
#include<fcntl.h>
#include<stdlib.h>  //exit(0)

#include<errno.h> //errno
#define     MAXLINE  4096

void client(int, int );
void server(int, int);

// 辅助函数
int  Read(int   fd, char *buf,  int len)
{
    int n = read(fd, buf, len);
    if(-1 == n)
        printf("read error
");
    
    return n;
}

void  Write(int  fd,  char * buf, int len)
{
    int     n = write(fd, buf, len);
    if(-1 == n)
        printf("client write error
");
}

void    Close(int fd)
{
    if(-1 == close(fd))
        printf("close error
");
}

int     main()
{
    int     pipe1[2], pipe2[2];
    pid_t   childpit;

    int     state;

    state = pipe(pipe1);
    if(state == -1)
        printf("create pipe 1 error
");
    
    state = pipe(pipe2);
    if(state == -1)
        printf("create pipe 2 error
");

    //<unistd.h>
    childpit = fork();

    if(childpit == 0)
    {
        if(-1 == close(pipe1[1]))
            printf("close pipe 1 error
");
        if(-1 == close(pipe2[0]))
            printf("close pipe 2 error
");

            server(pipe1[0], pipe2[1]);
            exit(0);
    }
    
    Close(pipe1[0]);
    Close(pipe2[1]);
    
    client(pipe2[0], pipe1[1]);

    if(-1 == waitpid(childpit, NULL, 0)) //等待子进程执行完
        printf("waitpid error
");

    exit(0);
}

// 客户端
void    client(int  readfd, int writefd)
{
    size_t     len;
    ssize_t    n;
    char    buff[MAXLINE];

    if(NULL == fgets(buff, MAXLINE, stdin))
        printf("get pathname error
");

    len = strlen(buff);

    if(buff[len-1] == 
)
        len--;
    
    if(-1 == write(writefd, buff, len))
        printf("write  error
");

    while( (n = Read(readfd, buff, MAXLINE)) > 0)
        Write(STDOUT_FILENO, buff, n); //宏定义在unistd.h中
}

// 服务器
void    server(int  readfd, int  writefd)
{
    int     fd;
    ssize_t     n;
    char    buff[MAXLINE];

    if( (n = Read(readfd, buff, MAXLINE)) == 0)
    {
        printf("end-of-file while reading pathname");
        exit(0);
    }
    buff[n] = ;

    if( (fd = open(buff, O_RDONLY)) < 0)
    {
        snprintf(buff + n, sizeof(buff) - n, " : can‘t open, %s
", strerror(errno));

        n = strlen(buff);
        Write(writefd, buff, n);
    }else{
        while( (n = Read(fd, buff, MAXLINE)) > 0)
            Write(writefd, buff, n);
        Close(fd);
    }
}


以上是关于ipc_pipe的主要内容,如果未能解决你的问题,请参考以下文章

VSCode自定义代码片段——CSS选择器

谷歌浏览器调试jsp 引入代码片段,如何调试代码片段中的js

片段和活动之间的核心区别是啥?哪些代码可以写成片段?

VSCode自定义代码片段——.vue文件的模板

VSCode自定义代码片段6——CSS选择器

VSCode自定义代码片段——声明函数