A mirror of Man pages
Go to file
Eric Wong 7b6a329977 sendfile.2: Caution against modifying sent pages
The following program illustrates the difference between TCP
and Unix stream sockets doing sendfile.  Since TCP implements
zero-copy, the new modifications to the file transferred is
seen upon reading despite the modifications happening after
sendfile was last called.

Unix stream sockets do not implement zero-copy (as of
Linux 3.15), so readers continue to see the contents of the
file at the time it was sent, not as they are at the time of
reading.

----------------- sendfile-mod.c ---------------
	#define _GNU_SOURCE
	#include <sys/ioctl.h>
	#include <sys/types.h>
	#include <sys/socket.h>
	#include <sys/sendfile.h>
	#include <arpa/inet.h>
	#include <stdio.h>
	#include <errno.h>
	#include <string.h>
	#include <unistd.h>
	#include <assert.h>
	#include <fcntl.h>

static void tcp_socketpair(int sv[2])
{
	struct sockaddr_in addr;
	socklen_t addrlen = sizeof(addr);
	int l = socket(PF_INET, SOCK_STREAM, 0);
	int c = socket(PF_INET, SOCK_STREAM, 0);
	int a;
	int val = 1;

	addr.sin_family = AF_INET;
	addr.sin_addr.s_addr = INADDR_ANY;
	addr.sin_port = 0;
	assert(0 == bind(l, (struct sockaddr*)&addr, addrlen));
	assert(0 == listen(l, 1024));
	assert(0 == getsockname(l, (struct sockaddr *)&addr, &addrlen));
	assert(0 == connect(c, (struct sockaddr *)&addr, addrlen));
	a = accept4(l, NULL, NULL, SOCK_NONBLOCK);
	assert(a >= 0);
	close(l);
	assert(0 == ioctl(c, FIONBIO, &val));
	sv[0] = a;
	sv[1] = c;
}

int main(int argc, char *argv[])
{
	int pair[2];
	FILE *tmp = tmpfile();
	int tfd;
	char buf[16384];
	ssize_t w, r;
	size_t i;
	const size_t n = 2048;
	off_t off = 0;
	char expect[4096];
	int flags = SOCK_STREAM|SOCK_NONBLOCK;

	tfd = fileno(tmp);
	assert(tfd >= 0);

	/* prepare the tempfile */
	memset(buf, 'a', sizeof(buf));
	for (i = 0; i < n; i++)
		assert(sizeof(buf) == write(tfd, buf, sizeof(buf)));

	if (argc == 2 && strcmp(argv[1], "unix") == 0)
		assert(0 == socketpair(AF_UNIX, flags, 0, pair));
	else if (argc == 2 && strcmp(argv[1], "pipe") == 0)
		assert(0 == pipe2(pair, O_NONBLOCK));
	else
		tcp_socketpair(pair);

	/* fill up the socket buffer */
	for (;;) {
		w = sendfile(pair[1], tfd, &off, n);
		if (w > 0)
			continue;
		if (w < 0 && errno == EAGAIN)
			break;
		assert(0 && "unhandled error" && w && errno);
	}
	printf("wrote off=%lld\n", (long long)off);

	/* rewrite the tempfile */
	memset(buf, 'A', sizeof(buf));
	assert(0 == lseek(tfd, 0, SEEK_SET));
	for (i = 0; i < n; i++)
		assert(sizeof(buf) == write(tfd, buf, sizeof(buf)));

	/* we should be reading 'a's, not 'A's */
	memset(expect, 'a', sizeof(expect));
	do {
		r = read(pair[0], buf, sizeof(expect));

		/* TCP fails here since it is zero copy (on Linux 3.15.5) */
		if (r > 0)
			assert(memcmp(buf, expect, r) == 0);
	} while (r > 0);

	return 0;
}

Signed-off-by: Eric Wong <normalperson@yhbt.net>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
2015-02-21 08:32:11 +01:00
man1 localedef.1: tfix 2015-02-01 16:25:17 +01:00
man2 sendfile.2: Caution against modifying sent pages 2015-02-21 08:32:11 +01:00
man3 encrypt.3: Improve code example 2015-02-21 08:32:11 +01:00
man4 random.4: Note maximum number of bytes returned by read(2) on /dev/random 2015-02-21 07:58:28 +01:00
man5 proc.5: (Briefly) document /proc/PID/attr/socketcreate 2015-02-21 07:58:28 +01:00
man6 getent.1, _syscall.2, acct.2, adjtimex.2, bdflush.2, brk.2, cacheflush.2, getsid.2, getxattr.2, inotify_add_watch.2, inotify_init.2, inotify_rm_watch.2, ioperm.2, ipc.2, listxattr.2, mlock.2, modify_ldt.2, mremap.2, nanosleep.2, outb.2, perf_event_open.2, ptrace.2, removexattr.2, s390_runtime_instr.2, sched_get_priority_max.2, sched_rr_get_interval.2, sched_setaffinity.2, sched_setparam.2, sched_setscheduler.2, sched_yield.2, setsid.2, setxattr.2, socketcall.2, unimplemented.2, aio_cancel.3, aio_error.3, aio_fsync.3, aio_read.3, aio_return.3, aio_suspend.3, aio_write.3, cfree.3, crypt.3, dlopen.3, encrypt.3, errno.3, fenv.3, ftime.3, ftw.3, getgrent_r.3, getpass.3, getpwent_r.3, getutent.3, hsearch.3, lio_listio.3, lockf.3, login.3, longjmp.3, perror.3, printf.3, scandirat.3, setjmp.3, strfmon.3, strtoimax.3, termios.3, ttyname.3, ualarm.3, updwtmp.3, wcstoimax.3, wordexp.3, console_ioctl.4, dsp56k.4, fd.4, hd.4, intro.4, lp.4, mem.4, null.4, ram.4, rtc.4, sk98lin.4, tty.4, ttyS.4, vcs.4, filesystems.5, group.5, host.conf.5, hosts.5, intro.5, issue.5, motd.5, networks.5, nologin.5, nsswitch.conf.5, passwd.5, proc.5, protocols.5, securetty.5, shells.5, termcap.5, ttytype.5, utmp.5, intro.6, armscii-8.7, ascii.7, bootparam.7, cp1251.7, environ.7, glob.7, intro.7, iso_8859-1.7, iso_8859-10.7, iso_8859-11.7, iso_8859-13.7, iso_8859-14.7, iso_8859-15.7, iso_8859-16.7, iso_8859-2.7, iso_8859-3.7, iso_8859-4.7, iso_8859-5.7, iso_8859-6.7, iso_8859-7.7, iso_8859-8.7, iso_8859-9.7, koi8-r.7, koi8-u.7, posixoptions.7, standards.7, unicode.7, utf-8.7, intro.8: s/GPLv2+_doc_full/GPLv2+_DOC_FULL/ 2013-03-10 10:57:11 +01:00
man7 unix.7: Mention SOCK_STREAM socket for ioctl_type of ioctl() 2015-02-21 07:58:28 +01:00
man8 iconvconfig.8: wfix 2015-01-28 11:03:31 +01:00
scripts Update usage message 2014-08-21 16:47:28 -05:00
Changes Start of man-pages-3.80: updating Changes and Changes.old 2015-02-01 17:18:34 +01:00
Changes.old Changes.old: tfix in 3.79 changelog 2015-02-02 09:58:34 +01:00
Makefile Makefile: Add 'check-groff-warnings' target 2012-10-24 14:53:48 +02:00
README README: Explain usage of prefix when installing 2014-05-26 10:16:11 +02:00
man-pages-3.80.Announce Start of man-pages-3.80: updating .Announce and .lsm files 2015-02-01 17:18:34 +01:00
man-pages-3.80.lsm Start of man-pages-3.80: updating .Announce and .lsm files 2015-02-01 17:18:34 +01:00

README

This package contains Linux man pages for sections
2, 3, 4, 5, and 7. Some more information is given in the
`Announce' file.

Install by copying to your favourite location.
"make install" will just copy them to /usr/share/man/man[1-8].
To install to a path different from /usr use
"make install prefix=/install/path".
"make" will move the pages from this package that are older than
the already installed ones to a subdirectory `not_installed',
then remove old versions (compressed or not),
compress the pages, and copy them to /usr/share/man/man[1-8].


Note that you may have to remove preformatted pages.

Note that sometimes these pages are duplicates of pages
also distributed in other packages. This has been reported
about dlclose.3, dlerror.3, dlopen.3, dlsym.3 (found in ld.so),
about resolver.3, resolv.conf.5 (found in bind-utils),
and about passwd.5, and mailaddr.7. Be careful not to
overwrite more up-to-date versions.
Reports on further duplicates are welcome.
Formerly present and now removed duplicates:
 exports.5 (found in nfs-server-2.2*),
 fstab.5, nfs.5 (found in util-linux-2.12*),
 lilo.8, lilo.conf.5 (found in lilo-21.6*).

Copyrights: These man pages come under various copyrights.
All pages are freely distributable when the nroff source is included.

If you have corrections and additions to suggest, see
http://www.kernel.org/doc/man-pages/contributing.html