2 * Use vmsplice to fill some user memory into a pipe. vmsplice writes
3 * to stdout, so that must be a pipe.
13 #include <sys/types.h>
17 #define ALIGN(buf) (void *) (((unsigned long) (buf) + align_mask) & ~align_mask)
20 static int align_mask = 65535;
22 int do_vmsplice(int fd, void *b1, void *b2, int len)
24 struct pollfd pfd = { .fd = fd, .events = POLLOUT, };
25 struct iovec iov[] = {
39 * in a real app you'd be more clever with poll of course,
40 * here we are basically just blocking on output room and
41 * not using the free time for anything interesting.
43 if (poll(&pfd, 1, -1) < 0)
46 written = vmsplice(fd, &iov[idx], 2 - idx, 0);
49 return error("vmsplice");
52 if (written >= iov[idx].iov_len) {
53 int extra = written - iov[idx].iov_len;
56 iov[idx].iov_len -= extra;
57 iov[idx].iov_base += extra;
59 iov[idx].iov_len -= written;
60 iov[idx].iov_base += written;
67 static int usage(char *name)
69 fprintf(stderr, "%s: [-c(lear)] [-u(nalign)] | ...\n", name);
73 static int parse_options(int argc, char *argv[])
77 while ((c = getopt(argc, argv, "cu")) != -1) {
95 int main(int argc, char *argv[])
97 unsigned char *b1, *b2;
100 if (parse_options(argc, argv) < 0)
101 return usage(argv[0]);
103 if (fstat(STDOUT_FILENO, &sb) < 0)
104 return error("stat");
105 if (!S_ISFIFO(sb.st_mode)) {
106 fprintf(stderr, "stdout must be a pipe\n");
107 return usage(argv[0]);
110 b1 = ALIGN(malloc(SPLICE_SIZE + align_mask));
111 b2 = ALIGN(malloc(SPLICE_SIZE + align_mask));
113 memset(b1, 0xaa, SPLICE_SIZE);
114 memset(b2, 0xbb, SPLICE_SIZE);
117 int half = SPLICE_SIZE / 2;
120 * vmsplice the first half of the buffer into the pipe
122 if (do_vmsplice(STDOUT_FILENO, b1, b2, SPLICE_SIZE))
126 * first half is now in pipe, but we don't quite know when
131 * vmsplice second half
133 if (do_vmsplice(STDOUT_FILENO, b1 + half, b2 + half, SPLICE_SIZE))
137 * We still don't know when we can reuse the second half of
138 * the buffer, but we do now know that all parts of the first
139 * half have been consumed from the pipe - so we can reuse that.
143 * Test option - clear the first half of the buffer, should
147 memset(b1, 0x00, SPLICE_SIZE);
148 memset(b2, 0x00, SPLICE_SIZE);