如何使用管道在两个程序之间发送简单的字符串?

发布于 2024-08-31 18:50:04 字数 99 浏览 4 评论 0原文

我尝试在网上搜索,但几乎没有任何资源。一个小例子就足够了。

编辑 我的意思是,两个不同的 C 程序相互通信。一个程序应该发送“Hi”,另一个程序应该接收它。类似的事情。

I tried searching on the net, but there are hardly any resources. A small example would suffice.

EDIT
I mean, two different C programs communicating with each other. One program should send "Hi" and the other should receive it. Something like that.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

°如果伤别离去 2024-09-07 18:50:04

常规管道只能连接两个相关的进程。它是由一个进程创建的,当最后一个进程关闭它时就会消失。

命名管道,因其行为也称为 FIFO,可以是用于连接两个不相关的进程,独立于进程而存在;这意味着即使没有人使用它,它也可以存在。 FIFO 是使用 mkfifo() 库函数。

示例

writer.c

#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

int main()
{
    int fd;
    char * myfifo = "/tmp/myfifo";

    /* create the FIFO (named pipe) */
    mkfifo(myfifo, 0666);

    /* write "Hi" to the FIFO */
    fd = open(myfifo, O_WRONLY);
    write(fd, "Hi", sizeof("Hi"));
    close(fd);

    /* remove the FIFO */
    unlink(myfifo);

    return 0;
}

reader.c

#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>

#define MAX_BUF 1024

int main()
{
    int fd;
    char * myfifo = "/tmp/myfifo";
    char buf[MAX_BUF];

    /* open, read, and display the message from the FIFO */
    fd = open(myfifo, O_RDONLY);
    read(fd, buf, MAX_BUF);
    printf("Received: %s\n", buf);
    close(fd);

    return 0;
}

注意:为简单起见,上述代码中省略了错误检查。

A regular pipe can only connect two related processes. It is created by a process and will vanish when the last process closes it.

A named pipe, also called a FIFO for its behavior, can be used to connect two unrelated processes and exists independently of the processes; meaning it can exist even if no one is using it. A FIFO is created using the mkfifo() library function.

Example

writer.c

#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

int main()
{
    int fd;
    char * myfifo = "/tmp/myfifo";

    /* create the FIFO (named pipe) */
    mkfifo(myfifo, 0666);

    /* write "Hi" to the FIFO */
    fd = open(myfifo, O_WRONLY);
    write(fd, "Hi", sizeof("Hi"));
    close(fd);

    /* remove the FIFO */
    unlink(myfifo);

    return 0;
}

reader.c

#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>

#define MAX_BUF 1024

int main()
{
    int fd;
    char * myfifo = "/tmp/myfifo";
    char buf[MAX_BUF];

    /* open, read, and display the message from the FIFO */
    fd = open(myfifo, O_RDONLY);
    read(fd, buf, MAX_BUF);
    printf("Received: %s\n", buf);
    close(fd);

    return 0;
}

Note: Error checking was omitted from the above code for simplicity.

禾厶谷欠 2024-09-07 18:50:04

在 C 中创建管道中,这向您展示了如何派生程序以使用管道。如果您不想 fork(),可以使用命名管道

另外还可以得到prog1 | 的效果prog2 通过将 prog1 的输出发送到 stdout 并从 prog2 中的 stdin 读取。您还可以通过打开名为 /dev/stdin 的文件来读取 stdin(但不确定其可移植性)。

/*****************************************************************************
 Excerpt from "Linux Programmer's Guide - Chapter 6"
 (C)opyright 1994-1995, Scott Burkett
 ***************************************************************************** 
 MODULE: pipe.c
 *****************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>

int main(void)
{
        int     fd[2], nbytes;
        pid_t   childpid;
        char    string[] = "Hello, world!\n";
        char    readbuffer[80];

        pipe(fd);

        if((childpid = fork()) == -1)
        {
                perror("fork");
                exit(1);
        }

        if(childpid == 0)
        {
                /* Child process closes up input side of pipe */
                close(fd[0]);

                /* Send "string" through the output side of pipe */
                write(fd[1], string, (strlen(string)+1));
                exit(0);
        }
        else
        {
                /* Parent process closes up output side of pipe */
                close(fd[1]);

                /* Read in a string from the pipe */
                nbytes = read(fd[0], readbuffer, sizeof(readbuffer));
                printf("Received string: %s", readbuffer);
        }

        return(0);
}

From Creating Pipes in C, this shows you how to fork a program to use a pipe. If you don't want to fork(), you can use named pipes.

In addition, you can get the effect of prog1 | prog2 by sending output of prog1 to stdout and reading from stdin in prog2. You can also read stdin by opening a file named /dev/stdin (but not sure of the portability of that).

/*****************************************************************************
 Excerpt from "Linux Programmer's Guide - Chapter 6"
 (C)opyright 1994-1995, Scott Burkett
 ***************************************************************************** 
 MODULE: pipe.c
 *****************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>

int main(void)
{
        int     fd[2], nbytes;
        pid_t   childpid;
        char    string[] = "Hello, world!\n";
        char    readbuffer[80];

        pipe(fd);

        if((childpid = fork()) == -1)
        {
                perror("fork");
                exit(1);
        }

        if(childpid == 0)
        {
                /* Child process closes up input side of pipe */
                close(fd[0]);

                /* Send "string" through the output side of pipe */
                write(fd[1], string, (strlen(string)+1));
                exit(0);
        }
        else
        {
                /* Parent process closes up output side of pipe */
                close(fd[1]);

                /* Read in a string from the pipe */
                nbytes = read(fd[0], readbuffer, sizeof(readbuffer));
                printf("Received string: %s", readbuffer);
        }

        return(0);
}
转瞬即逝 2024-09-07 18:50:04
dup2( STDIN_FILENO, newfd )

并阅读:

char reading[ 1025 ];
int fdin = 0, r_control;
if( dup2( STDIN_FILENO, fdin ) < 0 ){
    perror( "dup2(  )" );
    exit( errno );
}
memset( reading, '\0', 1025 );
while( ( r_control = read( fdin, reading, 1024 ) ) > 0 ){
    printf( "<%s>", reading );
    memset( reading, '\0', 1025 );
}
if( r_control < 0 )
    perror( "read(  )" );    
close( fdin );    

但是,我认为 fcntl 可以是更好的解决方案

echo "salut" | code
dup2( STDIN_FILENO, newfd )

And read:

char reading[ 1025 ];
int fdin = 0, r_control;
if( dup2( STDIN_FILENO, fdin ) < 0 ){
    perror( "dup2(  )" );
    exit( errno );
}
memset( reading, '\0', 1025 );
while( ( r_control = read( fdin, reading, 1024 ) ) > 0 ){
    printf( "<%s>", reading );
    memset( reading, '\0', 1025 );
}
if( r_control < 0 )
    perror( "read(  )" );    
close( fdin );    

But, I think that fcntl can be a better solution

echo "salut" | code
心是晴朗的。 2024-09-07 18:50:04

一个程序写入 stdout 的内容可以由另一个程序通过 stdin 读取。简单来说,使用 c 编写 prog1 使用 printf() 打印某些内容,使用 prog2 使用 scanf() 读取某些内容代码>.然后运行

./prog1 | ./prog2

What one program writes to stdout can be read by another via stdin. So simply, using c, write prog1 to print something using printf() and prog2 to read something using scanf(). Then just run

./prog1 | ./prog2
这样的小城市 2024-09-07 18:50:04

这是一个示例

int main()
{
    char buff[1024] = {0};
    FILE* cvt;
    int status;
    /* Launch converter and open a pipe through which the parent will write to it */
    cvt = popen("converter", "w");
    if (!cvt)
    {
        printf("couldn't open a pipe; quitting\n");
        exit(1)
    }
    printf("enter Fahrenheit degrees: " );
    fgets(buff, sizeof (buff), stdin); /*read user's input */
    /* Send expression to converter for evaluation */
    fprintf(cvt, "%s\n", buff);
    fflush(cvt);
    /* Close pipe to converter and wait for it to exit */
    status=pclose(cvt);
    /* Check the exit status of pclose() */
    if (!WIFEXITED(status))
        printf("error on closing the pipe\n");
    return 0;
}

此程序中的重要步骤是:

  1. popen () 调用,它在子进程和父进程中的管道之间建立关联。
  2. fprintf() 调用将管道用作普通文件来写入子进程的 stdin 或从其 stdout 读取。
  3. pclose() 调用关闭管道并导致子进程终止。

Here's a sample:

int main()
{
    char buff[1024] = {0};
    FILE* cvt;
    int status;
    /* Launch converter and open a pipe through which the parent will write to it */
    cvt = popen("converter", "w");
    if (!cvt)
    {
        printf("couldn't open a pipe; quitting\n");
        exit(1)
    }
    printf("enter Fahrenheit degrees: " );
    fgets(buff, sizeof (buff), stdin); /*read user's input */
    /* Send expression to converter for evaluation */
    fprintf(cvt, "%s\n", buff);
    fflush(cvt);
    /* Close pipe to converter and wait for it to exit */
    status=pclose(cvt);
    /* Check the exit status of pclose() */
    if (!WIFEXITED(status))
        printf("error on closing the pipe\n");
    return 0;
}

The important steps in this program are:

  1. The popen() call which establishes the association between a child process and a pipe in the parent.
  2. The fprintf() call that uses the pipe as an ordinary file to write to the child process's stdin or read from its stdout.
  3. The pclose() call that closes the pipe and causes the child process to terminate.
蘑菇王子 2024-09-07 18:50:04

这个答案可能对未来的 Google 员工有所帮助。

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

int main(){     
     int p, f;  
     int rw_setup[2];   
     char message[20];      
     p = pipe(rw_setup);    
     if(p < 0){         
        printf("An error occured. Could not create the pipe.");  
        _exit(1);   
     }      
     f = fork();    
     if(f > 0){
        write(rw_setup[1], "Hi from Parent", 15);    
     }  
     else if(f == 0){       
        read(rw_setup[0],message,15);       
        printf("%s %d\n", message, r_return);   
     }  
     else{      
        printf("Could not create the child process");   
     }      
     return 0;

}

您可以在此处。

This answer might be helpful for a future Googler.

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

int main(){     
     int p, f;  
     int rw_setup[2];   
     char message[20];      
     p = pipe(rw_setup);    
     if(p < 0){         
        printf("An error occured. Could not create the pipe.");  
        _exit(1);   
     }      
     f = fork();    
     if(f > 0){
        write(rw_setup[1], "Hi from Parent", 15);    
     }  
     else if(f == 0){       
        read(rw_setup[0],message,15);       
        printf("%s %d\n", message, r_return);   
     }  
     else{      
        printf("Could not create the child process");   
     }      
     return 0;

}

You can find an advanced two-way pipe call example here.

肤浅与狂妄 2024-09-07 18:50:04

首先,让程序 1 将字符串写入 stdout (就好像您希望它出现在屏幕上一样)。然后第二个程序应该从 stdin 读取字符串,就像用户从键盘输入一样。然后你运行:

$ program_1 | program_2

First, have program 1 write the string to stdout (as if you'd like it to appear in screen). Then the second program should read a string from stdin, as if a user was typing from a keyboard. then you run:

$ program_1 | program_2
一片旧的回忆 2024-09-07 18:50:04

如果要启用两个进程之间的通信,则必须确定是否要分叉这些进程。如果您要分叉它们,则可以使用匿名管道。否则,您可以使用命名管道

匿名管道

假设您在fork()之前声明了管道,那么子进程将继承父进程的管道,两者都指向管道的同一端。您可以利用这一事实在进程之间发送数据。

例如,在以下程序中,父进程将字符串 Hello World! 发送到子进程,然后子进程显示它。

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

int main(int argc, char* argv[]) {
    int pipefd[2];
    pipe(pipefd);

    int pid =  fork();
    if (pid < 0) {
        fprintf(stderr, "failed to fork process");
    }
    else if (pid == 0) {
        // the child process doesn't use the pipe's write and thus it closes it.
        close(pipefd[1]);

        // read data from the pipe's read end and store into buffer.
        char buffer[80];
        read(pipefd[0], buffer, sizeof(buffer));
        printf("Received string: %s", buffer);

        exit(0);
    }
    else {
        // the parent process doesn't use the pipe's read end and thus it closes it.
        close(pipefd[0]);

        // write string to pipe's write end.
        char string[] = "Hello, world!\n";
        write(pipefd[1], string, (strlen(string)+1));

        exit(0);
    }

    return(0);
}

命名管道

通过命名管道,您可以使用文件在不相关的进程之间传输数据。

您可以使用 mkfifo 在 shell 中创建命名管道。或者,您可以使用库函数 mkfifo() 在 C 程序中创建它;您必须首先包含 库。

交互式创建命名管道

我们在 shell 中创建命名管道 pipefd

$ mkfifo pipefd

我们按如下方式实现发送方进程:

// sender.c
#include <string.h>
#include <unistd.h>
#include <fcntl.h>

int main(int argc, char* argv[]) {
    int pipefd = open("mypipe", O_WRONLY);

    // write string to pipe.
    char string[] = "Hello, world!\n";
    write(pipefd, string, (strlen(string)+1));

    close(pipefd);

    return(0);
}

我们按如下方式实现接收方进程:

// receiver.c
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>

int main(int argc, char* argv[]) {
    int pipefd = open("mypipe", O_RDONLY);

    char buffer[80];
    read(pipefd, buffer, sizeof(buffer));
    printf("Received string: %s", buffer);

    close(pipefd);

    return(0);
}

我们编译两个程序:

$ gcc sender.c -o sender
$ gcc receiver.c -o receiver

并运行它们:

$ ./sender &
[1] 97687
$ ./receiver
Received string: Hello, world!

如输出所示,父进程将字符串发送给子进程,然后子进程显示它。

If you want to enable communication between two processes, you must determine if you're forking those processes or not. If you're forking them, then you can make use of anonymous pipes. Otherwise, you can use named pipes.

Anonymous Pipes

Assuming you've declared the pipe before fork(), then a child process will inherit the parent process's pipe, both of which points to the same ends of the pipe. You can use this fact to send data between the processes.

For example, in the following program the parent process sends the string Hello World! to the child process, which then displays it.

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

int main(int argc, char* argv[]) {
    int pipefd[2];
    pipe(pipefd);

    int pid =  fork();
    if (pid < 0) {
        fprintf(stderr, "failed to fork process");
    }
    else if (pid == 0) {
        // the child process doesn't use the pipe's write and thus it closes it.
        close(pipefd[1]);

        // read data from the pipe's read end and store into buffer.
        char buffer[80];
        read(pipefd[0], buffer, sizeof(buffer));
        printf("Received string: %s", buffer);

        exit(0);
    }
    else {
        // the parent process doesn't use the pipe's read end and thus it closes it.
        close(pipefd[0]);

        // write string to pipe's write end.
        char string[] = "Hello, world!\n";
        write(pipefd[1], string, (strlen(string)+1));

        exit(0);
    }

    return(0);
}

Named Pipes

With a named pipe, you're using a file to transfer data between unrelated processes.

You can create a named pipe in the shell using mkfifo. Alternatively you can create it within a C program using the library function mkfifo(); you must include the <sys/types.h> and <sys/stat.h> libraries first.

Named pipe created interactively

We create the named pipe pipefd in the shell:

$ mkfifo pipefd

We implement the sender process as follows:

// sender.c
#include <string.h>
#include <unistd.h>
#include <fcntl.h>

int main(int argc, char* argv[]) {
    int pipefd = open("mypipe", O_WRONLY);

    // write string to pipe.
    char string[] = "Hello, world!\n";
    write(pipefd, string, (strlen(string)+1));

    close(pipefd);

    return(0);
}

We implement the receiver process as follows:

// receiver.c
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>

int main(int argc, char* argv[]) {
    int pipefd = open("mypipe", O_RDONLY);

    char buffer[80];
    read(pipefd, buffer, sizeof(buffer));
    printf("Received string: %s", buffer);

    close(pipefd);

    return(0);
}

We compile both programs:

$ gcc sender.c -o sender
$ gcc receiver.c -o receiver

and run them:

$ ./sender &
[1] 97687
$ ./receiver
Received string: Hello, world!

As the output shows, the parent process sent the string to the child process which then displayed it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文