glibc手册(linux手册翻译——epoll_wait(2))

linux手册翻译——epoll_wait(2)

epoll_wait, epoll_pwait, epoll_pwait2 – 在epoll fd上等待I/O事件

events指向了事件缓冲区,每当interest list中fd触发事件加入到ready list后,会将其返回到事件缓冲区中。最大返回maxevents个,因此maxevents至少大于0。返回的event顺序写入缓冲区。timeout参数指定epoll_wait将阻塞的毫秒数。

epoll_wait()将会一直阻塞直到:fd产生事件 / 被信号处理函数打断 / 超时。

时间测量将使用CLOCK_MONOTONIC(系统启动后到现在的时间,记录的是tick的总次数)时钟,超时时间将向上舍入到系统时钟粒度,内核调度延迟可能让阻塞时间稍微超出。指定为-1时将无限期阻塞,指定为0时若没有可用事件则立即返回。

返回的epoll_event中,data字段与使用event_ctl(2)(EPOLL_CTL_ADD,EPOLL_CTL_MOD)传入的data一致。(所以一般来说用fd足矣),而events字段是此fd触发的事件。

与epoll_wait自比,后者允许应用程序安全的等待(在调用epoll_wait(),设置自定义的信号掩码,并在epoll_wait()结束后恢复),直到文件描述等就绪或信号被捕获。

等价于:

sigmask指定为NULL时,epoll _pwait与epoll_wait相同。epoll_pwait2与epoll_pwait除timeout参数外完全相同,它指定timespec结构来执行纳秒级的等待。设为NULL时将一直等。

错误将返回-1,并设定errno;
超时将返回0;
成功将返回触发I0事件的fd个数。

epoll_wait() 在 2.6 版中被添加到内核中。 从版本 2.3.2 开始,glibc 中提供了库支持。
epoll_pwait() 在内核 2.6.19 中被添加到 Linux。 从版本 2.6 开始,glibc 中提供了库支持。
epoll_pwait2() 在内核 5.11 中被添加到 Linux。

epoll_wait(), epoll_pwait(), and epoll_pwait2() are Linux-specific.

虽然一个线程在调用 epoll_wait() 时被阻塞,但另一个线程可能会向等待的 epoll 实例添加文件描述符。 如果新的文件描述符准备好,它将导致 epoll_wait() 调用解除阻塞。

如果在调用 epoll_wait() 时有超过 maxevents 个文件描述符准备就绪,那么连续的 epoll_wait() 调用将循环遍历准备好的文件描述符集。 此行为有助于避免饥饿情况,即进程未能注意到其他文件描述符已准备就绪,因为它专注于一组已知已准备就绪的文件描述符。循环遍历的意义就在于避免只访问固定位置的事件。

请注意,可以在 interest-list 当前为空的 epoll 实例上调用 epoll_wait() (或者其interest-list因为文件描述符被关闭或从另一个线程中的兴趣中删除而变为空)。 该调用将阻塞,直到在另一个线程中将某个文件描述符添加到interest-list并且该文件描述符准备就绪。
C library/kernel differences
原始的 epoll_pwait() 和 epoll_pwait2() 系统调用有第六个参数 size_t sigsetsize,它指定了 sigmask 参数的字节大小。 glibc epoll_pwait() 包装函数将此参数指定为固定值(等于 sizeof(sigset_t))。

在 2.6.37 之前的内核中,大于大约 LONG_MAX / HZ 毫秒的超时值被视为 -1(即无穷大)。 因此,例如,在 sizeof(long) 为 4 且内核 HZ 值为 1000 的系统上,这意味着大于 35.79 分钟的超时被视为无穷大

linux手册翻译——sendfile(2)

sendfile – transfer data between file descriptors

sendfile() 在一个文件描述符和另一个文件描述符之间复制数据。 因为这种复制是在内核中完成的,所以 sendfile() 比 read(2) 和 write(2) 的组合更有效,后者需要将数据传入和传出用户空间。

in_fd 是一个为读取而打开的文件描述符, out_fd 是一个为写入而打开的描述符。

如果 offset 不为NULL,则sendfile()将以其为偏移量从 in_fd 中读取数据。当 sendfile() 返回时,此变量将设置为读取的最后一个字节之后的偏移量。 如果 offset 为 NULL,则将从 in_fd 中的文件偏移量开始读取数据。

需要注意!如果指定了 offset ,那么读取 in_fd 中的数据是不会修改其打开文件自身的偏移量的。

count 是要在文件描述符之间复制的字节数。

in_fd 参数必须是支持类似 mmap(2) 等操作的文件(即它不能是套接字)。

在 2.6.33 之前的 Linux 内核中, out_fd 必须引用套接字。 从 Linux 2.6.33 开始,它可以是任何文件。 如果它是一个常规文件,则 sendfile() 适当地更改 out_fd 的文件偏移量。

如果传输成功,则返回写入 out_fd 的字节数。 请注意,成功调用 sendfile() 可能会写入比请求更少的字节; 如果有未发送的字节,调用者应该准备重试调用。 另见NOTES。
出错时,返回 -1,并设置 errno 以指示错误。

sendfile() 首次出现在 Linux 2.2 中。 从 glibc 2.1 开始就存在包含文件 《sys/sendfile.h》。

Not specified in POSIX.1-2001, nor in other standards.

Other UNIX systems implement sendfile() with different semantics and prototypes. It should not be used in portable programs.

sendfile() 最多传输 0x7ffff000 (2,147,479,552) 个字节,返回的是实际传输的字节数。 (在 32 位和 64 位系统上都是如此。)

如果您计划使用 sendfile() 将文件发送到 TCP 套接字,但需要在文件内容之前发送一些标头数据,您会发现使用 TCP_CORK 选项很有用,在 tcp(7) 中描述,以最小化 数据包的数量并调整性能。

根据tcp(7),TCP_CORK的作用是:如果设置,则不发送部分帧。 当再次清除该选项时,将发送所有排队的部分帧。更方便的,可以在执行时send()时设置MSG_MORE标志,见 send(2)

在 Linux 2.4 及更早版本中,out_fd 也可以指普通文件; 这种可能性在 Linux 2.6.x 内核系列中消失了,但在 Linux 2.6.33 中恢复了。

最初的 Linux sendfile() 系统调用不是为了处理大文件偏移量而设计的。 因此,Linux 2.4 添加了 sendfile64(),偏移参数的类型更宽。 glibc sendfile() 包装函数透明地处理内核差异。

在 sendfile() 因 EINVAL 或 ENOSYS 失败的情况下,应用程序可以回退到 read(2)/write(2)。

如果 out_fd 引用了具有零拷贝支持的套接字或管道,则调用者必须确保 in_fd 引用的文件的传输部分保持不变,直到 out_fd 另一端的读取器消耗了传输的数据。

Linux 特定的 splice(2) 调用支持在任意文件描述符之间传输数据,前提是其中一个(或两个)是管道。

如何解决源码包安装时的依赖性问题

不管是初步跨入Linux殿堂的新手,还是具有多年经验的专家,在安装或编译软件包的过程中或多或少的都会遇到包的依赖问题,从而导致安装过程无法继续,比如管理员在安装LAMP时,包需要libgd.so文件,而这个文件属于GD软件包。但是在安装GD软件包时,可能这个软件包跟其他软件包又具有依赖关系,又需要安装其他软件包才行。这时有的管理员便失去耐心。在遇到这种Linux软件包依赖关系问题时,该如何解决呢?在谈这个具体的措施之前,先跟大家聊聊Linux系统里的软件依赖性问题。
  一、什么是依赖性
  程序依赖于程序代码的共享库,以便它们可以发出系统调用将输出发送到设备或打开文件等(共享库存在于许多方面,而不只局限于系统调用)。没有共享库,每次程序员开发一个新的程序,每个程序员都需要从头开始重写这些基本的系统操作。当编译程序时,程序员将他的代码链接到这些库。如果链接是静态的,编译后的共享库对象代码就添加到程序执行文件中;如果是动态的,编译后的共享库对象代码只在运行时需要它时由程序员加载。动态可执行文件依赖于正确的共享库或共享对象来进行操作。rpm依赖性尝试在安装时强制实施动态可执行文件的共享对象需求,以便在以后当程序运行时不会有与动态链接过程有关的任何问题。
  注意:还有一种类型的依赖性,它基于显式的条目,rpm通过程序员将该依赖性强加到rpm配置文件中,但目前我们不关心这种类型的依赖性,这种依赖性比较容易解决。这里将重点放在rpm强制实施的更加复杂的共享对象依赖性。
  二、动态可执行文件和共享对象
  动态可执行文件使用最初编译和链接程序时使用的库文件的共享对象名称来查找共享对象。它们在少数的几个标准位置查找,比如在/lib和/usr/lib目录及在LD_LIBRARY_PATH环境变量(主要用于指定查找共享库,比如我们在安装Oracle时指定路径,exportLD_LIBRARY_PATH=$ORACLE_HOME/lib:/lib:/usr/lib:/usr/local/lib)指定的目录中。顺便提一下,在这些库目录中找到的共享对象可能不是真正的文件;它们可能是指向位于其他位置的真实库文件的符号链接(但通常仍旧在标准库目录的一个目录中)。至少从系统管理员的观点是在用于创建共享库文件的共享库软件包的名称和共享库文件的名称之间通常没有什么关系。例如,GLIBC2.3软件包用于创建libc.so.6共享库文件。也从本示例中注意到,添加到共享库文件名结束的版本号(.6)跟用于创建它的版本号(2.3)没有关系。这是由共享库软件包开发人员有意完成的,以便GLIBC的新版本可以重用相同的共享库文件名libc.so.6。这允许您在系统上加载新版本的GLIBC,而不用中断动态链接到lib.so.6共享库文件的所有程序,当然假定新版本的GLIBC向后与动态可执行文件最初所链接的老版本GLIBC兼容。因此,即使库文件或共享对象文件有与它们相关的版本号,这些版本号也不能帮助你确定他们来自哪个版本的共享软件包。
  注意:当将whatprovides选项用于rpm查询命令时,可以获得有关使用rpm软件包加载到系统的现有共享对象的信息。这种混乱是由下面的事实造成的:单个共享库文件可能支持某个范围的共享库软件包版本。例如,要检查soname库文件/lib/libc.so.6支持的GLIBC共享库软件包,运行下面的命令:
  #objdump–all-headers/lib/libc.so.6|less
  向下滚动此报告,直到到达Versiondefinitions:部分,以便查看libc.so.6共享库文件支持哪些GLIBC版本:
  Versiondefinitions:
  10x010x0865f4e6libc.so.6
  20x000x0d696910GLIBC_2.0
  30x000x0d696911GLIBC_2.1
  GLIBC_2.0
  40x000x09691f71GLIBC_2.1.1
  GLIBC_2.1
  50x000x09691f72GLIBC_2.1.2
  GLIBC_2.1.1
  60x000x09691f73GLIBC_2.1.3
  GLIBC_2.1.2
  70x000x0d696912GLIBC_2.2
  GLIBC_2.1.3
  80x000x09691a71GLIBC_2.2.1
  GLIBC_2.2
  90x000x09691a72GLIBC_2.2.2
  GLIBC_2.2.1
  100x000x09691a73GLIBC_2.2.3
  GLIBC_2.2.2
  110x000x09691a74GLIBC_2.2.4
  GLIBC_2.2.3
  120x000x09691a76GLIBC_2.2.6
  GLIBC_2.2.4
  130x000x0d696913GLIBC_2.3
  GLIBC_2.2.6
  140x000x09691972GLIBC_2.3.2
  GLIBC_2.3
  150x000x09691973GLIBC_2.3.3
  GLIBC_2.3.2
  160x000x09691974GLIBC_2.3.4
  GLIBC_2.3.3
  170x000x0d696914GLIBC_2.4
  GLIBC_2.3.4
  180x000x0d696915GLIBC_2.5
  GLIBC_2.4
  190x000x0963cf85GLIBC_PRIVATE
  GLIBC_2.5
  200x000x0b792650GCC_3.0
  在本示例中,1ibc.so.6共享库文件支持原先为GLIBC版本2.0到2.5而开发的所有动态执行文件。注意:也可以使用objdump命令来从共享库文件中提取soname,命令如下所示:
  #objdump–all-headers/lib/libcrypto.so.0.9.8b|grepSONAME
  SONAMElibcrypto.so.6
  objdump:/lib/libcrypto.so.0.9.8b:norecognizeddebugginginformation
  接下来,将讨论rpm软件包是如何生成的,以便在新系统上安装rpm软件包时,这些共库依赖性是己知的。
三、Rpm软件包和共享库依赖性
  当程序员生成rpm软件包时,ldd命令用于报告动态可执行文件软件包中所有动态可执行文件使用的所有共享库。另一个混乱是由下面的事实带来的:相同软件包中的不同动态可执行文件可能与相同的共享库软件包的不同版本进行链接。例如,Heartbeat软件包中的不同程序可能已经进行了开发,并动态链接到libc.so.6sonmae共享库文件的不同GLIBC版本。对rpm命令使用-q和–requires参数,可以看到rpm软件包需要的共享库的完整清单。例如,要看到Heartbeatrpm软件包所有的所需依赖性,请使用命令:
  #rpm-q–requires-pheartbeat-1.x.x.i386.rpm
  这产生了下面的报告:
  sysklogd
  /bin/sh
  /bin/sh
  /usr/bin/python
  ld-linux.so.2
  libapphb.so.0
  libc.so.6
  libc.so.6(GLIBC_2.0)
  libc.so.6(GLIBC_2.1)
  libc.so.6(GLIBC_2.1.3)
  libc.so.6(GLIBC_2.2)
  libc.so.6(GLIBC_2.3)
  libccmclient.so.0
  libdl.so.2
  libglib-1.2.so.0
  libhbclient.so.0
  libpils.so.0
  libplumb.so.0
  libpthread.so.0
  librt.so.1
  libstonith.so.0
  注意,在此报告中,libc.so.6soname是所需要的,此共享库必须支持使用GLIBC共享软件包版本号2.0、2.1、2.1.3、2.2和2.3进行链接的动态可执行文件。这是由下面的事实决定的:Heartbeat软件包中的不同动态可执行文件是针对不同版本的libc.so.6库的每个版本进行链接的。在了解了动态可执行文件、共享对象、soname和共享库软件包彼此是如何相关的后,下面准备来看这样的一个例子:当尝试安装rpm软件包,并且它由于依赖性错误而失败时,会发生什么。yum能够从指定的服务器自动下载RPM包并且安装,可以自动处理依赖性关系,并且一次安装所有依赖的软体包,无须繁琐地一次次下载、安装。
  四、手工解决依赖性问题
  通常,当尝试安装发行版中没有包括的软件包(及不能由像up2date、apt-get或Yum一样的更新工具自动解决其依赖性的软件包)时,将碰到rpm依赖性错误。例如,如果尝试在老的Linux发行版上使用rpm–ivh*rpm命令,例如所有的Heartbeatrpm包,那么在安装过程中就可能碰到下面的错误:
  error:faileddependencies:
  libc.so.6(GLIBC_2.3)isneededbyheartbeat-1.x.x
  libc.so.6(GLIBC_2.3)isneededbyheartbeat-pils-1.x.x
  libcrypto.so.0.9.6isneededbyheartbeat-stonith-1.x.x
  libsnmp-0.4.2.6.soisneededbyheartbeat-stonith-1.x.x
  注意,rpm命令没有干扰报告所需的每个GLIBC共享库软件包版本号——它只报告所需的最高编号的版本号(GLIBC_2.3)。(假定原来的软件包开发人员不会将相同软件包中的可执行文件链接到不兼容版本的共享库软件包)所有的这些故障都报告所需的共享库名称或soname(而不是文件名称,soname始终以“lib”开始)。但可以删除添加到rpm报告的soname结束的版本号,并快速检查以查看是否在系统中使用locate命令安装这些共享库(假设您的locate数据库是最新的,有关更多信息,请参阅locate或slocate的手册页)。例如,要查找libcrypto享库文件,要输入:
  #locatelibcrypto
  #locatelibcrypto
  /lib/libcrypto.so.0.9.8b
  /lib/libcrypto.so.6
  /root/.Trash/vmware-tools-distrib/lib/lib32/libcrypto.so.0.9.8
  /root/.Trash/vmware-tools-distrib/lib/lib32/libcrypto.so.0.9.8/libcrypto.so.0.9.8
  /root/.Trash/vmware-tools-distrib/lib/lib64/libcrypto.so.0.9.8
  /root/.Trash/vmware-tools-distrib/lib/lib64/libcrypto.so.0.9.8/libcrypto.so.0.9.8
  /usr/lib/libcrypto.a
  /usr/lib/libcrypto.so
  /usr/lib/pkgconfig/libcrypto.pc
  /usr/lib/vmware-tools/lib32/libcrypto.so.0.9.8
  /usr/lib/vmware-tools/lib32/libcrypto.so.0.9.8/libcrypto.so.0.9.8
  /usr/lib/vmware-tools/lib64/libcrypto.so.0.9.8
  /usr/lib/vmware-tools/lib64/libcrypto.so.0.9.8/libcrypto.so.0.9.8
  如果此命令没有在系统上找到一个libcrypto共享库文件,将需要转到Internet并找出哪个共享库软件包包含此共享库文件。完成此项工具的一个快速和简便方式是只要在

linux手册翻译——send(2)

send, sendto, sendmsg – send a message on a socket

系统调用 send()、sendto() 和 sendmsg() 用于将消息传输到另一个套接字。

仅当套接字处于连接状态时才可以使用 send() 调用(以便知道预期的接收者, 也就是说send()仅仅用于数据流类型的数据发送 ,对于TCP,服务端和客户端都可以使用send/recv;但是对于UDP,只能是客户端使用send/recv,服务端只能使用sendto/recvfrom,因为客户端是进行了connect操作知道要发送和接受的地址)。send() 和 write(2) 之间的唯一区别是存在 flags 参数。此外,
send(sockfd, buf, len, flags);
等价于
sendto(sockfd, buf, len, flags, NULL, 0);

参数 sockfd 是发送者套接字的文件描述符。

如果在连接模式的套接字(即套接字类型为SOCK_STREAM、SOCK_SEQPACKET)上使用 sendto(),则参数 dest_addr 和 addrlen 将被忽略(当它们不是NULL和0时可能返回错误EISCONN),若套接字没有实际连接(还没有三次握手建立连接)将返回错误ENOTCONN。 否则,目标地址由 dest_addr 给出, addrlen 指定其大小。 对于 sendmsg(),目标地址由 msg.msg_name 给出, msg.msg_namelen 指定其大小。

对于 send() 和 sendto(),消息位于 buf 中,长度为 len 。 对于sendmsg(),消息存放于 msg.msg_iov 元素指向数组数据区(见下)中。sendmsg() 调用还允许发送辅助数据(也称为控制信息)

如果消息太长而无法通过底层协议原子传递( too long to pass atomically through the underlying protocol ),则返回错误 EMSGSIZE,并且不会传输消息。

No indication of failure to deliver is implicit in a send(). Locally detected errors are indicated by a return value of -1.

当消息不适合套接字的发送缓冲区时,send() 通常会阻塞,除非套接字已置于非阻塞 I/O 模式。 在这种情况下,在非阻塞模式下它会失败并显示错误 EAGAIN 或 EWOULDBLOCK。select(2) 调用可用于确定何时可以发送更多数据

上面的的描述还是很笼统的,以TCP为例,按我的理解,我认为只要发送缓冲区有空闲位置,且此时协议栈没有向网络发送数据,那么就可以写入,对于阻塞模式,直到所有数据写入到缓冲区,就会返回,否则一直阻塞,对于非阻塞模式,是有一个超时时间的,这个由 SO_SNDTIMEO 选项控制,详细见 socket(7) ,如果当前有空闲位置可以发即当前可写入,那么就写入到缓冲区,知道超时之前写入多少算多少,然后返回成功写入的字节数,如果超时时任何数据都没写出去,或者当前就是不可写入,那么返回-1 ,并设置errno为 EAGAIN 或 EWOULDBLOCK。

The flags argument is the bitwise OR of zero or more of the following flags.

sendmsg() 使用的 msghdr 结构的定义如下:

对于未连接的套接字 msg_name 指定数据报的目标地址,它指向一个包含地址的缓冲区; msg_namelen 字段应设置为地址的大小。 对于连接的套接字,这些字段应分别指定为 NULL 和 0。这里的未连接指的是数据报协议,连接指的是数据流协议

The msg_iov and msg_iovlen fields specify scatter-gather locations, as for writev(2).
msg_iov是一个buffer数组:

使用 msg_control 和 msg_controllen 成员发送控制信息(辅助数据)。 内核可以处理的每个套接字最大控制缓冲区长度由 /proc/sys/net/core/optmem_max 中的值限制; 见 socket(7) 。 有关在各种套接字域中使用辅助数据的更多信息,请参阅 unix(7) 和 ip(7)。

msg_flags 字段被忽略。

成功时,返回成功发送的字节数,这个字节数并不一定和我们的缓冲区大小相同。 出错时,返回 -1,并设置 errno 以指示错误。

这些是套接字层生成的一些标准错误。 底层协议模块可能会产生和返回额外的错误; 请参阅它们各自的手册页。

4.4BSD, SVr4, POSIX.1-2001. These interfaces first appeared in 4.2BSD.

POSIX.1-2001 describes only the MSG_OOB and MSG_EOR flags. POSIX.1-2008 adds a specification of MSG_NOSIGNAL. The MSG_CONFIRM flag is a Linux extension.

根据 POSIX.1-2001,msghdr 结构的 msg_controllen 字段应该是 socklen_t 类型,而 msg_iovlen 字段应该是 int 类型,但是 glibc 目前将两者都视为 size_t。

有关可用于在单个调用中传输多个数据报的 Linux 特定系统调用的信息,请参阅 sendmmsg(2)。

Linux may return EPIPE instead of ENOTCONN.

getaddrinfo(3) 中显示了使用 send() 的示例。

linux手册翻译——recv(2)

recv, recvfrom, recvmsg – receive a message from a socket

recv()、recvfrom() 和 recvmsg() 调用用于从套接字接收消息。 它们可用于在UDP和TCP的套接字上接收数据。 本页首先介绍了所有三个系统调用的共同特点,然后介绍了调用之间的区别。

recv() 和 read(2) 之间的唯一区别是 flags 的存在。 使用零标志参数,recv() 通常等效于 read(2) (但请参阅 NOTES),且
recv(sockfd, buf, len, flags);
等价于
recvfrom(sockfd, buf, len, flags, NULL, NULL);

所有三个调用都在成功完成时返回消息的长度。 如果消息太长而无法放入提供的缓冲区,则可能会丢弃多余的字节,具体取决于接收消息的套接字类型,显然TCP是不可能丢弃的。

如果套接字上没有可用消息,则接收调用将等待消息到达,除非套接字是非阻塞的(请参阅 fcntl(2)),在这种情况下,将返回值 -1 并将 errno 设置为 EAGAIN 或 EWOULDBLOCK。recv_()调用通常会返回任何可用的数据,只要拿到数据就会立马返回,最多返回指定缓冲区大小的数据,但是并不会等待到让缓冲区满,除非设置了MSG_WAITALL标志,见下。

应用程序可以使用 select(2)、poll(2) 或 epoll(7) 来确定更多数据何时到达。

The flags argument is formed by ORing one or more of the following values:

ee_errno contains the errno number of the queued error. ee_origin is the origin code of where the error originated. The other fields are protocol-specific. The macroSOCK_EE_OFFENDERreturns a pointer to the address of the network object where the error originated from given a pointer to the ancillary message. If this address is not known, the sa_family member of the sockaddr containsAF_UNSPECand the other fields of the sockaddr are undefined. The payload of the packet that caused the error is passed as normal data.
For local errors, no address is passed (this can be checked with the cmsg_len member of the cmsghdr ). For error receives, theMSG_ERRQUEUEflag is set in the msghdr . After an error has been passed, the pending socket error is regenerated based on the next queued error and will be passed on the next socket operation.

recvfrom() 将接收到的消息放入缓冲区 buf 。 调用者必须在 len 中指定缓冲区的大小。

如果调用者希望拿到消息的原地址, 并且底层协议可以提供消息的源地址时,应将 src_addr 设置为指向用于接收消息原地址的缓冲区。 在这种情况下, addrlen 是一个value-result参数。 在调用之前,它应该被初始化为与 src_addr 关联的缓冲区的大小。 返回时,addrlen 被更新以包含源地址的实际大小。 如果提供的缓冲区太小,则截断返回的地址; 在这种情况下, addrlen 将返回一个大于提供给调用的值。

如果调用者对源地址不感兴趣,则应将 src_addr 和 addrlen 指定为 NULL。

ssize_t recv(int sockfd, void* buf, size_t len, int flags);
recv() 调用通常仅用于已连接的套接字(请参阅 connect(2))。 相当于调用:
recvfrom(fd, buf, len, flags, NULL, 0);

ssize_t recvmsg(int sockfd, struct msghdr* msg, int flags);
recvmsg() 调用使用 msghdr 结构来最小化直接提供的参数数量。 这个结构在 《sys/socket.h》 中定义如下:

msg_name 字段指向调用者分配的缓冲区,如果套接字未连接(特指UDP的服务端),则该缓冲区用于返回源地址。 调用者应在此调用之前将 msg_namelen 设置为此缓冲区的大小; 从成功调用返回后,msg_namelen 将包含返回地址的长度。 如果应用程序不需要知道源地址,可以将 msg_name 指定为 NULL。

The fields msg_iov and msg_iovlen describe scatter-gather locations, as discussed in readv(2).
需要注意的是 msg_iov 和 msg_iovlen 描述了一个 struct iovec 类型的数组, msg_iovlen 表示数组的元素个数,而struct iovec则是描述了一个缓冲区

字段 msg_control 指向用于其他协议控制相关消息或杂项辅助数据的缓冲区。 当recvmsg()被调用时, msg_controllen 为 msg_contro l中可用缓冲区的长度; 从成功调用返回时,它将被设置为控制消息序列的长度。

控制消息的格式为:

只能通过 cmsg(3) 中定义的宏访问辅助数据。

例如,Linux 使用这种辅助数据机制通过 UNIX 域套接字传递扩展错误、IP 选项或文件描述符。 有关在各种套接字域中使用辅助数据的更多信息,请参阅 unix(7) 和 ip(7)。

msghdr 中的 msg_flags 字段在 recvmsg()返回时设置。 它可以包含几个标志:

这些调用返回接收到的字节数,如果发生错误,则返回 -1。 如果发生错误,则设置 errno 以指示错误。

当流套接字对等端执行有序关闭(orderly shutdown)时,返回值将为 0(传统的“文件结束”返回)。

各种域(例如 UNIX 和 Internet 域)中的数据报套接字允许零长度数据报。 当收到这样的数据报时,返回值为 0。

如果从流套接字接收的请求字节数为 0,则也可能返回值 0。

这些是套接字层生成的一些标准错误。 底层协议模块可能会产生和返回额外的错误; 查看他们的手册页。

POSIX.1-2001, POSIX.1-2008, 4.4BSD (these interfaces first appeared in 4.2BSD).

POSIX.1 describes only the MSG_OOB, MSG_PEEK, and MSG_WAITALL flags.

如果零长度数据报未决,则带有零标志参数的 read(2) 和 recv() 提供不同的行为。 在这种情况下, read(2) 不起作用(数据报保持挂起),而 recv() 消耗挂起的数据报。

socklen_t 类型是由 POSIX 发明的。 另见 accept(2) 。

根据 POSIX.1,msghdr 结构的 msg_controllen 字段类型为 socklen_t,而 msg_iovlen 字段类型为 int,但 glibc 目前将两者设置为 size_t。

有关可用于在单个调用中接收多个数据报的 Linux 特定系统调用的信息,请参阅 recvmmsg(2)。

getaddrinfo(3) 中显示了使用 recv() 的示例。

linux手册翻译——fallocate(2)

fallocate – manipulate file space
这是一个不可移植的、特定于 Linux 的系统调用。 For the portable, POSIX.1-specified method of ensuring that space is allocated for a file, see posix_fallocate(3).

fallocate() 允许调用者直接操作 fd 引用的文件所分配的磁盘空间,操作的字节范围为。

mode 参数确定要在给定范围上执行的操作。 支持的操作的详细信息在下面的小节中给出。

fallocate()的默认操作(即 mode =0)是在参数 offset 和 len 指定的范围内分配磁盘空间。如果 offset + len 大于文件的大小,则文件大小将被修改。超过原范围的区域将会被初始化为0。此默认行为与 posix_fallocate(3) 库函数的行为非常相似,是实现 posix_fallocate(3) 的最佳实现方法。
调用成功后,后续写入 offset 和 len 指定的范围不会因为磁盘空间不足而失败。

注:这样做的有什么用呢?根据博客 用fallocate进行“文件预留“或“文件打洞“ ,可以有以下好处:
(1)可以让文件尽可能的占用连续的磁盘扇区,减少后续写入和读取文件时的磁盘寻道开销;
(2)迅速占用磁盘空间,防止使用过程中所需空间不足。
(3)后面再追加数据的话,不会需要改变文件大小,所以后面将不涉及metadata的修改

如果在mode中指定了 FALLOC_FL_KEEP_SIZE 标志,调用的行为类似,即依然会为文件分配磁盘空间,但是不会修改文件大小。这种预分配的方式可以用来优化文件的append操作,也就是在执行append的时候不需要再额外申请磁盘空间了。

如果在 mode 中指定了 FALLOC_FL_UNSHARE_RANGE 标志,则共享文件数据范围将成为文件私有的,以保证后续写入不会因空间不足而失败。 通常,这将通过对文件中的所有共享数据执行写时复制操作来完成。 并非所有文件系统都支持此标志。

由于分配是以块大小的块完成的,fallocate() 可能会分配比指定范围更大的磁盘空间。

当mode指定为 FALLOC_FL_PUNCH_HOLE 时,会释放指定范围内的空间,即创建一个空洞。在指定的范围内,部分的文件块(即文件块部分属于该范围)将会被置为0,全部的在范围内的文件块,将会被从文件系统中删除。成功调用后,后续的读取将会返回0。

FALLOC_FL_PUNCH_HOLE 必须和 FALLOC_FL_KEEP_SIZE 通过或运算一起使用,换句话说, FALLOC_FL_PUNCH_HOLE 是不能修改文件的大小的。

并非所有文件系统都支持 FALLOC_FL_PUNCH_HOLE; 如果文件系统不支持该操作,则返回错误。 至少以下文件系统支持该操作:

当mode指定为 FALLOC_FL_COLLAPSE_RANGE 标志时,将从文件中删除指定的字节范围,而不会留下空洞。操作完成后,从 offset + len 开始位置的文件内容将会被追加到 offset 处。文件大小会减少 len

文件系统可能会限制操作的粒度,以确保有效实施。 通常,offset 和 len 必须是文件系统逻辑块大小的倍数,这取决于文件系统类型和配置。 如果文件系统有这样的要求,如果违反了该要求,fallocate() 将失败并显示错误 EINVAL。

If the region specified by offset plus len reaches or passes the end of file, an error is returned; instead, use ftruncate(2) to truncate a file.

FALLOC_FL_COLLAPSE_RANGE 标志和其他标志不兼容。

在 Linux 3.15 中,ext4(only for extent-based files)和 XFS 支持 FALLOC_FL_COLLAPSE_RANGE 标志。

当mode指定为 FALLOC_FL_COLLAPSE_RANGE 标志时,将会指定范围内分配磁盘空间,填补空洞。成功调用后后续读取将会返回0。

Zeroing is done within the filesystem preferably by converting the range into unwritten extents. This approach means that the specified range will not be physically zeroed out on the device (except for partial blocks at the either end of the range), and I/O is (otherwise) required only to update metadata.可能的意思是,最好不要将物理磁盘清零,而是配置一个为写入的状态,这样读取上来的pagecache就是0。这种情况下,仅仅需要修改文件元数据就可有了。

如果在mode中额外指定了FALLOC_FL_KEEP_SIZE标志,调用的行为类似,但即使offset+len大于文件大小,文件大小也不会改变。 此行为与在指定 FALLOC_FL_KEEP_SIZE 的情况下预分配空间时相同。

并非所有文件系统都支持 FALLOC_FL_ZERO_RANGE; 如果文件系统不支持该操作,则返回错误。 至少以下文件系统支持该操作:

如果在mode中额外指定了 FALLOC_FL_INSERT_RANGE 标志,那么将会在offset开始的位置插入一个大小为len的空洞,在不覆盖文件内容的前提下增加文件的空间。

此模式在操作粒度方面与 FALLOC_FL_COLLAPSE_RANGE 具有相同的限制。 如果不满足粒度要求,fallocate() 将失败并显示错误 EINVAL。 如果偏移量等于或大于文件末尾,则返回错误。 对于此类操作(即在文件末尾插入一个洞),应使用 ftruncate(2)。

FALLOC_FL_INSERT_RANGE 标志与其他标志不兼容。

目前只有XFS (since Linux 4.1) 和 ext4 (since Linux 4.2)支持此标志。
n success, fallocate() returns zero. On error, -1 is returned and errno is set to indicate the error.
fallocate() is available on Linux since kernel 2.6.23. Support is provided by glibc since version 2.10. The FALLOC_FL_* flags are defined in glibc headers only since version 2.18.
fallocate() is Linux-specific.

如何更新ubuntu的man手册

一般会在有更新的时候自动提示你进行更新。 如果想自己更新 1、系统设置里有个更新管理器 2、打开终端输入下面的命令 sudo apt-get update sudo apt-get upgrade 更新系统版本 sudo apt-get upgrade-dist

linux手册翻译——epoll_ctl(2)

epoll_ctl 一 epll 文件描述符的控制接口

此操作用于要在epoll的interest list中增、改、删entry(entry包括了fd和设定的事件),具体的操作由op参数指定:

epoll- event结构:

epoll_event的data成员指定内核应该保存的数据,并在epoll_wait准备好时返回,可用于标识触发event的fd是那个,这个很重要
epoll_event的events成员是位掩码,由以下0个或多个可用事件类型组合到一起:

成功时,epoll_ctl() 返回零。 发生错误时,epoll_ctl() 返回 -1 并设置 errno 以指示错误。

epoll_ctl() 在 2.6 版中被添加到内核中。 从版本 2.3.2 开始,glibc 中提供了库支持。

epoll_ctl() is Linux-specific.

The epoll interface supports all file descriptors that support poll(2).

In kernel versions before 2.6.9, the EPOLL_CTL_DEL operation required a non-null pointer in event, even though this argument is ignored. Since Linux 2.6.9, event can be specified as NULL when using EPOLL_CTL_DEL. Applications that need to be portable to kernels before 2.6.9 should specify a non-null pointer in event.

If EPOLLWAKEUP is specified in flags, but the caller does not have the CAP_BLOCK_SUSPEND capability, then the EPOLLWAKEUP flag is silently ignored. This unfortunate behavior is necessary because no validity checks were performed on the flags argument in the original implementation, and the addition of the EPOLLWAKEUP with a check that caused the call to fail if the caller did not have the CAP_BLOCK_SUSPEND capability caused a breakage in at least one existing user-space application that happened to randomly (and uselessly) specify this bit. A robust application should therefore double check that it has the CAP_BLOCK_SUSPEND capability if attempting to use the EPOLLWAKEUP flag.

linux有API手册吗

有命令行中输入man XXX
XXX是包的名称或是命令名称或是程序库名称
如:man glibc就是glibc(GCC c lib)库中的函数介绍
要看有什么程序包用新立得打开可以搜索,点击下面就有描述
有些程序有开发包就会有dev包。如openoffice-dev就是开发openoffice插件的开发包,包含有相关函数库