[Linux Programming] I/O

低级I/O接口

#include <unistd.h>
size_t write(int fildes, const void *buf, size_t nbytes);
size_t read(int fildes, void *buf, size_t nbytes);

高级I/O接口

readv/writev: 允许指定多个缓冲区, 分散读, 集中写

#include <sys/uio.h>
struct iovec {
    void *iov_base; // starting address of buffer
    size_t iov_len; // size of buffer
};
ssize_t readv(int filedes, const struct iovec *iov, int iovcnt);
ssize_t writev(int filedes, const struct iovec *iov, int iovcnt); // atomic operation
// @iovcnt: iov length. limit in IOV_MAX

send/recv: 与write和read比较, 它能够传递一些标识到内核.

#include <sys/socket.h>
ssize_t send(int sockfd, const void *buff, size_t nbytes, int flags);
ssize_t recv(int sockfd, void *buff, size_t nbytes, int flags);
// @flags: OR
// - NULL | MSG_DONTWAIT | MSG_PEEK | MSG_WAITALL | ...
// MSG_DONTWAIT: specifies nonblocking for a single I/O
// ...

#include <sys/socket.h>
ssize_t recvfrom(int sockfd, void *buff, size_t nbytes, int flags, struct sockaddr *
from, socklen_t *addrlen);
ssize_t sendto(int sockfd, const void *buff, size_t nbytes, int flags, const struct
sockaddr *to, socklen_t addrlen);
// @flags: same with send/recv

recvmsg/sendmsg: 拥有其他I/O的所有特性, 并且具备发送和接收辅助数据的能力

#include <sys/socket.h>
struct msghdr {
    void *msg_name; // protocol address (scokaddr_in struct or ...)
    socklen_t msg_namelen; // size of protocol address
    struct iovec *msg_iov; // scatter/gather array
    int msg_iovlen; // # elements in msg_iov
    void *msg_control; // ancillary data (cmsghdr struct)
    socklen_t msg_controllen; // length of ancillary data
    int msg_flags; // flags returned by recvmsg()
};
// @msg_control: must be suitably aligned for a cmsghdr structure
// @msg_falgs: return flags
// - MSG_MCAST | MSG_TRUNC | ...

struct cmsghdr { // ancillary data
    socklen_t cmsg_len; // length in bytes, including this structure
    int cmsg_level; // originating protocol
    int cmsg_type; // protocol-specific type
    // followed by unsigned char cmsg_data[]
};
// about ancillary data you should learn more.

ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
// @flags: copy to msg->msg_flags and return msg->masg_falgs
ssize_t sendmsg(int sockfd, struct msghdr *msg, int flags);
// @flags: use flags ignore msg->msg_falgs

设置I/O超时

  1. alarm -> SIGALRM: 简单粗暴, 但多线程下使用复杂
  2. select: 局限于非阻塞模式下
  3. SO_RCVTIMEO/SO_SNDTIMEO: 局限于套接字
struct timeval tv;
tv.tv_sec = 5;
tv.tv_usec = 0;
setsockppt(sockfd, SOL_SOCKET, SO_RECVTIMEO, &tv, sizeof(tv));

// time out, recv return -1 and errno == EWOULDBLOCK

发表评论

电子邮件地址不会被公开。必填项已用 * 标注