简体   繁体   English

创建替换stdin的文件描述符(在select()中)

[英]Create file descriptor that replaces stdin (in select())

Having in mind to communicate with a multi-client Unix domain socket without keyboard input, I want to create a file descriptor that replaces stdin. 考虑到无需键盘输入即可与多客户端Unix域套接字通信,我想创建一个替换stdin的文件描述符。

With a multi-client socket, you have to add the stdin's file descriptor (which is 0, with FD_SET(0, &readfds) ) to readfds in order to send the keyboard input ( FD_ISSET(0, &readfds) ) to the server. 使用多客户端套接字时,必须将stdin的文件描述符(为FD_SET(0, &readfds) )添加到readfds ,以便将键盘输入( FD_ISSET(0, &readfds) )发送到服务器。 Since I don't want to write everytime I launch my client, I want to replace this file descriptor by a custom one (by writing to this file from another program). 由于我不想在每次启动客户端时都编写文件,因此我想用自定义文件替换该文件描述符(通过从另一个程序写入该文件)。

I checked out Create a file descriptor to create two programs: 我签出了创建文件描述符以创建两个程序:

One that writes to the file descriptor: 写入文件描述符的一个:

int main() {
    char buffer[] = "test";
    int fd = open("sample.dat", O_WRONLY | O_CREAT, 0666);
    dup2(fd, 5);

    if(write(5, buffer, 4) < 0)
        fprintf(stderr, "write %s\n", strerror(errno));

    close(5);    
    return 0;
}

And another one that reads from it: 另一个从中读取:

int main() {
    char buffer[4];
    int fd = open("sample.dat", O_RDONLY);
    dup2(fd, 5);

    for(;;) {
        if(read(5, buffer, 4) < 0)
            fprintf(stderr, "read %s\n", strerror(errno));

        printf("%s\n", buffer);
        sleep(1);
    }

    return 0;
}

My question is : is it possible to make this file descriptor as stdin-like ? 我的问题是 :是否可以使此文件描述符像stdin一样? I mean actually my second program read "test" endlessly because (of course) sample.dat still contains "test" but I want to delete it once it has been read. 我的意思是实际上我的第二个程序不断读取“ test”,因为(当然)sample.dat仍然包含“ test”,但是一旦读取,我想将其删除。

Yes. 是。 You can use pipes for this: https://linux.die.net/man/2/pipe 您可以为此使用管道: https : //linux.die.net/man/2/pipe

Or FIFOs: https://linux.die.net/man/3/mkfifo Using FIFOs will create a file in the filesystem which can be opened by the client and server process to communicate through. 或FIFO: https : //linux.die.net/man/3/mkfifo使用FIFO将在文件系统中创建一个文件,客户端和服务器进程可以打开该文件进行通信。

If I understood correctly, you want to communicate to a program who can only read on the stdin. 如果我理解正确,您想与只能在标准输入上阅读的程序进行通讯。 You have two ways to write in the stdin : the first way is to use your keyboard, and the second way is to use write() . 您可以使用两种方法在stdin中进行编写:第一种方法是使用键盘,第二种方法是使用write()

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

int         main(void)
{
    char    *s = "what you want to write";
    write(STDIN_FILENO, s, strlen(s));
    return (0);
}

This program will write on the stdin, in the same way you would write with your keyboard. 该程序将以与用键盘编写相同的方式在stdin上编写。 Besides, you will see the string printed on your command-line interface. 此外,您还将看到在命令行界面上打印的字符串。

The problem isn't that you're reading in "test" constantly, it's that you're not handling the call to read() properly. 问题不在于您不断读取“测试”,而是您没有正确处理对read()的调用。 Whilst you're checking that it's not returning an error, you're not seeing how many bytes have been read in. read() doesn't null-terminate the string read in, so you should actually store the return value and use that to put the NUL in your buffer. 在检查它没有返回错误的同时,也没有看到已读入多少字节read()不会对读入的字符串进行空终止,因此您实际上应该存储返回值并使用它将NUL放入缓冲区。 Otherwise, since nothing in the buffer is changing, it'll appear as if you're re-reading the same text over and over. 否则,由于缓冲区中的任何内容都没有变化,因此好像您要一遍又一遍地重新读取相同的文本。

    int err=read(fd, buffer, 4);
    if(err < 0)
        {
        fprintf(stderr, "read %s\n", strerror(errno));
        }
    else
        {
        buffer[err]='\0';
        }

If you make this change, you'll find that you only ever read in "test" once and after that you're not reading anything more in. 如果进行此更改,您会发现您只阅读过一次“测试”,此后您将不再阅读任何内容。

Note: You don't need the calls to dup2() - that's just for copying a file descriptor to known value. 注意:您不需要调用dup2() -仅用于将文件描述符复制到已知值。 You can just use fd as is in your calls to read/write data. 您可以直接在呼叫中使用fd来读取/写入数据。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM