10

I have a socket I'm doing select() on it, waiting for other process to write. Once it write, I read the data, and write it to another file descriptor. My question is, if there's a way to bridge the socket to the file descriptor, so when there's data ready, it will be automatically written to the other file descriptor ?

This way, I could throw a way the buffer I'm using, and omit a thread in the system.

stdcall
  • 27,613
  • 18
  • 81
  • 125
  • 1
    Why do you need a thread now? – hyde Mar 12 '13 at 08:00
  • Could you describe what problem you're trying to solve? Pipes do exactly what you want, only from specific streams. Is your issue network-specific? – Michael Foukarakis Mar 12 '13 at 09:29
  • @MichaelFoukarakis I'm developing a logging environment for a daemon with legacy code. I can't change the implementation, anyway, pipes work only in the same process context, which doesn't work for me. – stdcall Mar 12 '13 at 11:41
  • @hyde doing select() blocks, so instead of blocking my entire process, I can block a thread. – stdcall Mar 12 '13 at 11:42
  • @Mellowcandle Ah. Well, `sendfile` would not allow you to get rid of the select or a thread anyway, as it will not return until everything is copied. But you could write your own "sendfile" function, which launches the thread, transfers everything, and closes the thread. Or make that `select` to be core of your main loop, and have worker threads for background calculations etc, which is quite common design. – hyde Mar 12 '13 at 11:59

2 Answers2

6

On linux, using splice() might be more suitable, when the direction is from socket to file. Using splice() is a bit more complicated, but you get both directions. Also, I think sendfile uses splice internally these days.

There are many questions on SO already discussing the differences between splice() and sendfile(). Searching the web also reveals conflicting statements on what (sources and destinations) splice works for. The best way to know if it is suitable for your case, is to test it.

SO about compatible filesystems: Which file systems support splicing via Linux's splice(2)?

SO about old kernels not supporting splice for TCP sockets: Does Linux's splice(2) work when splicing from a TCP socket?

Splice explained: http://kerneltrap.org/node/6505

Splice source: http://lxr.linux.no/#linux+v3.8.2/fs/splice.c

Community
  • 1
  • 1
thuovila
  • 1,960
  • 13
  • 21
4

Sorry if I misunderstood your situation, but do you mean something like sendfile?

sendfile - transfer data between file descriptors

#include <sys/sendfile.h>
ssize_t sendfile(int out_fd, int in_fd, off_t * offset ", size_t" " count" );

sendfile() copies data between one file descriptor and another. Because this copying is done within the kernel, sendfile() is more efficient than the combination of read(2) and write(2), which would require transferring data to and from user space.

Community
  • 1
  • 1
Jorge Israel Peña
  • 36,800
  • 16
  • 93
  • 123
  • 4
    Snippet from linked man page: *The in_fd argument must correspond to a file which supports mmap(2)-like operations (i.e., it cannot be a socket).* – hyde Mar 12 '13 at 07:55
  • From what I understand, sendfile() only work on file descriptors that represent files, so it can't work with a network socket and file descriptor. :( – stdcall Mar 12 '13 at 11:38
  • @Mellowcandle I think the modern `sendfile()` is a bit more relaxed about the underlying types of the fds, as the man-page linked to by Jorge also states. Additionally, for the name _sendfile_ to make any sense, at least one of the descriptors has to reprsent something besides a file. Also, see my nice answer about `splice()` :) – thuovila Mar 12 '13 at 13:22