进程间管道双向传输

为了符合新的架构,需要实现进程间的双向传输数据模型,今天下午做了一些研究,并把研究成果记录下来。
很简单,有两个进程,P1进程调用P2进程,并且P1和P2进程进行双向数据的传输。

P1代码如下:

#include <errno.h>
#include 
<fcntl.h>
#include 
<stdio.h>
#include 
<stdlib.h>
#include 
<unistd.h>
#include 
<sys/types.h>
#include 
<sys/socket.h>
#include 
<sys/wait.h>
#include 
<string.h>

/* return how many char have got, if 0 fail to execute, else success */
int sendDev(const char *exec_full_path, const char *str_req, int len_req, char *str_resp, int size_resp)
{
    
int fd[2], parent, child;
    pid_t pid;

    
/* Create a duplex pipe using the BSD socketpair call */
    
if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd) < 0{
        
return 0;
    }


    
/* Fork the process and check whether it is successful */
    
if ( (pid = fork()) < 0{
        close(fd[
0]);
        close(fd[
1]);
        
return 0;
    }


    parent 
= fd[0];
    child  
= fd[1];

    
if (pid == 0/* child */
        
/* Close the other end */
        close(parent);

        
/* prepare child fd as string */
        
char str_child_fd[16];
        sprintf(str_child_fd, 
"%d", child);

        
/* execl bin file and set child fd as param */
        execl(exec_full_path, str_child_fd, NULL);

        close(child);
        
/* Exit the child process if execl fails */
        _exit(
127);
    }
 else /* parent */
        
/* Close the other end */
        close(child);
        
int n;

        
/* send request xml string */
        n 
= write(parent, str_req, len_req);
        shutdown(parent, SHUT_WR);

        
/* read response xml string */
        
// Here, we set timeout policy, if sub process timeout, we just return zero
        fd_set rdfds;
        FD_ZERO(
&rdfds);
        FD_SET(parent, 
&rdfds);
        
struct timeval tv;
        tv.tv_sec 
= 10;
        tv.tv_usec 
= 0;
        n 
= select(parent+1&rdfds, NULL, NULL, &tv);
        
if(n == 0{
            
/* timeout or not response */
            close(child);
        }

        
else {
            
/* get the response string successfully */
            n 
= read(parent, str_resp, size_resp);
            printf(
"read (%d) ", n);
        }

        close(parent);
        
return n;
    }

}


int main(void)
{
    
char exec[] = "/root/Desktop/p2";
    
char request[] = "<?xml version="1.0" encoding="utf-8"?><InputParam>P1 request...</InputParam>";
    
char response[1024];

    memset(response, 
01024);
    
int n = sendDev(exec, request, strlen(request), response, 1024);
    
    printf(
"P1 get (%d) -> %s ", n, response);

    
return 0;
}




P2代码如下:

#include <errno.h>
#include 
<fcntl.h>
#include 
<stdio.h>
#include 
<stdlib.h>
#include 
<unistd.h>
#include 
<sys/types.h>
#include 
<sys/socket.h>
#include 
<sys/wait.h>
#include 
<string.h>

int main(int argc, char *argv[])
{
    
int n;
    
int fd;

    sscanf(argv[
0], "%d"&fd);

    
/* read */
    
char buffer[1024];
    memset(buffer, 
01024);
    n 
= read(fd, buffer, 1024);
    printf(
"P2 get (%d) -> %s ", n, buffer);

    sleep(
5);

    
/* write */
    
char response[] = "<?xml version="1.0" encoding="utf-8"?><OutputParam>P2 response...</OutputParam>";

    n 
= write(fd, response, strlen(response));
    printf(
"p2 wrote %d bytes. ", n);
    shutdown(fd, SHUT_WR);

    exit(
0);
}


编译P1, P2
gcc p1.c -o p1
gcc p2.c -o p2

运行P1
./p1

运行结果如下:

P2 get (76) -> <?xml version="1.0" encoding="utf-8"?><InputParam>P1 request...</InputParam>
p2 wrote 79 bytes.
read (79)
P1 get (79) -> <?xml version="1.0" encoding="utf-8"?><OutputParam>P2 response...</OutputParam>

Good job.

注意:我们也可以把Child重定向到stdin和stdout

dup2 (child, STDIN_FILENO);          /* bind the pipe with STDIN */
dup2 (child, STDOUT_FILENO);      
/* bind the pipe with STDOUT */
这样,在子进程中就可以通过读stdin获取数据,写stdout发送数据
/**//* 获取数据 */
fgets(buf, 
1024, stdin);;

/**//* 写入数据 */
fputs(buf, stdout);
fflush(stdout);
/* ATT: We should use fflush in here */
使用SocketPair比使用两对Pipes更加方便实用,因为我们在读取数据的时候需要知道发送的接收端是否完成,往往这需要一些特殊字符来表示。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值