進程間管道雙向傳輸

爲了符合新的架構,需要實現進程間的雙向傳輸數據模型,今天下午做了一些研究,並把研究成果記錄下來。
很簡單,有兩個進程,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更加方便實用,因爲我們在讀取數據的時候需要知道發送的接收端是否完成,往往這需要一些特殊字符來表示。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章