from:http://blog.csdn.net/jasonliuvip/article/details/22600569
Linux Network Programming IX: Splice function, efficient 0 copies
Recently looking at "Linux High Performance Server Programming", here to do a diary to motivate themselves, while sharing in need of friends.
1. Splice function
[CPP]View PlainCopy
- #include <fcntl.h>
- ssize_t Splice (int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t len, unsigned int flags);
Splice is used to move data between two file descriptors, which is also a 0 copy.
The fd_in parameter is the descriptor to be entered. If it is a pipe file descriptor, the off_in must be set to NULL, otherwise the off_in indicates where to start reading from the input data stream and, if NULL, is read from the current offset of the input data stream.
The fd_out/off_out is the same as above, but for output.
The len parameter specifies the length of the moving data.
The flags parameter controls how the data is moved:
- The splice_f_nonblock:splice operation is not blocked. However, if the file descriptor is not set to an I/O that is not blocked, then the call splice may still be blocked.
- Splice_f_more: Tells the OS kernel that the next SPLICE system call will have more data coming.
- Splice_f_move: If the output is a file, this value causes the operating system kernel to attempt to read the data directly from the input pipeline buffer into the output address space, and this data transfer process does not occur without any data copy operations.
2. When using splice, at least one of the fd_in and fd_out must be a pipe file descriptor.
Returns the number of bytes moved when the call succeeds; it may return 0, indicating that no data needs to be moved, which usually happens when the pipe is read from the pipeline and the pipeline is not written.
Return-1 On failure, and set errno
3. Code: Through splice the contents of the client into the pipeline, and then read from the pipeline to the client, so as to achieve efficient and simple echo service. The entire process does not perform recv/send, and therefore does not involve user-space-to-kernel-space data copies.
[CPP]View PlainCopy
- echo Server implemented with splice
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <assert.h>
- #include <errno.h>
- #include <string.h>
- #include <fcntl.h>
- int main (int argc, char **argv)
- {
- if (argc <= 2) {
- printf ("Usage:%s IP port\n", basename (Argv[0]));
- return 1;
- }
- const Char *ip = argv[1];
- int port = atoi (argv[2]);
- struct sockaddr_in address;
- Bzero (&address, sizeof (address));
- address.sin_family = af_inet;
- Address.sin_port = htons (port);
- Inet_pton (Af_inet, IP, &address.sin_addr);
- int sock = socket (pf_inet, sock_stream, 0);
- ASSERT (sock >= 0);
- int reuse = 1;
- setsockopt (sock, Sol_socket, SO_REUSEADDR, &reuse, sizeof (reuse));
- int ret = bind (sock, (struct sockaddr*) &address, sizeof (address));
- ASSERT (Ret! =-1);
- RET = Listen (sock, 5);
- ASSERT (Ret! =-1);
- struct SOCKADDR_IN client;
- socklen_t client_addrlength = sizeof (client);
- int connfd = Accept (sock, (struct sockaddr*) &client, &client_addrlength);
- if (CONNFD < 0) {
- printf ("errno is:%s\n", Strerror (errno));
- }
- else {
- int pipefd[2];
- RET = pipe (PIPEFD); //Create Pipelines
- ASSERT (Ret! =-1);
- //Direct client data on CONNFD to the pipeline
- ret = Splice (CONNFD, NULL, pipefd[1], NULL,
- 32768, Splice_f_more | Splice_f_move);
- ASSERT (Ret! =-1);
- //directs the output of the pipe to the CONNFD
- ret = Splice (pipefd[0], NULL, CONNFD, NULL,
- 32768, Splice_f_more | Splice_f_move);
- ASSERT (Ret! =-1);
- Close (CONNFD);
- }
- Close (sock);
- return 0;
- }
Linux Network Programming IX: Splice function, efficient 0 copies