赞
踩
fcntl(fd, F_SETFL, fcntl(fd, F_GETFD, 0) | O_NONBLOCK);
代码解释:
上面这句代码,先查询文件描述符 fd 当前的标志,然后将 O_NONBLOCK 标志加入,并通过 F_SETFL 更新文件描述符,最终实现将该文件描述符切换为非阻塞模式。
O_NONBLOCK 设置在文件描述符上时,后续对该文件描述符的 I/O 操作(读写等)会变为非阻塞模式。
在非阻塞模式下,如果 I/O 操作不能立即完成(例如,因为没有数据可读 或 写缓冲区满),系统不会让调用进程阻塞等待,而是立即返回一个错误(通常为 EAGAIN 或 EWOULDBLOCK)。
这样,进程可以避免因等待 I/O 完成而被长时间阻塞,实现更高的响应性和并发性。
非阻塞模式—应用场景举例:
int accept(int sockfd, struct sockaddr* addr, socklen_t* len)
accept()函数,用于接受客户端的连接请求。默认情况下,accept() 是阻塞的。这意味着,如果没有待处理的连接请求(即没有客户端尝试连接到服务器),accept() 会一直阻塞,直到有新的连接请求到达或发生其他特定条件(如超时)为止。
当 accept() 处于阻塞状态时,它所在的线程是不能去做其他事情的。
若要改变这种行为,可以采用以下方法:
非阻塞模式:如前所述,可以使用 fcntl()
函数将套接字设置为非阻塞模式(使用 O_NONBLOCK
标志)。在这种模式下,accept()
调用将不会阻塞,而是立即返回。如果此时没有待处理的连接请求,accept()
将返回一个错误(通常为 EAGAIN
或 EWOULDBLOCK
)。这样,线程可以在没有可用连接时执行其他任务,然后在适当的时候再次尝试 accept()
。
异步 I/O:如 Linux 中的 io_uring
或 Windows 中的 overlapped I/O,可以异步地执行 accept()
,使得线程在发起 accept()
请求后可以继续执行其他任务,然后通过回调、事件通知等方式获知 accept()
的结果。
mmap() 和 munmap() 是用于内存映射操作的系统调用函数。
mmap() 允许将文件或其他对象直接映射到进程的虚拟地址空间中,从而实现高效的数据访问。
void* mmap(void* addr, size_t length, int prot, int flags, int fd, off_t offset);
void* addr
:
NULL
,内核将自动选择一个合适的地址。size_t length
:
int prot
:
PROT_READ
:允许读取。PROT_WRITE
:允许写入。PROT_NONE
:禁止访问。int flags
:
MAP_SHARED
:创建一个可共享的映射,对映射区域的修改会影响到所有映射此区域的进程,并且可能会同步回文件。MAP_PRIVATE
:创建一个私有映射,对映射区域的修改仅影响当前进程,不会改变底层文件。int fd
:
-1
或者一个未打开的文件描述符。off_t offset
:
返回值:
MAP_FAILED
(通常是一个负值,如 (void*) -1
)。int munmap(void* addr, size_t length);
void* addr
:
mmap()
调用返回的地址。size_t length
:
mmap()
调用中的 length
参数一致。返回值: 成功时返回 0
。出现错误时返回 -1
。
mmap()
常用于以下场景:
例如,映射一个已打开文件的部分内容到内存中:
#include <fcntl.h> #include <sys/mman.h> #include <unistd.h> #include <cerrno> int main() { const char* filename = "/path/to/file"; int fd = open(filename, O_RDONLY); if (fd == -1) { perror("open"); return 1; } struct stat sb; if (fstat(fd, &sb) == -1) { perror("fstat"); close(fd); return 1; } // 映射整个文件 void* mapped_region = mmap(nullptr, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0); if (mapped_region == MAP_FAILED) { perror("mmap"); close(fd); return 1; } // 使用映射区域... // ... // 解除映射 if (munmap(mapped_region, sb.st_size) == -1) { perror("munmap"); close(fd); return 1; } close(fd); return 0; }
在WebServer中,使用方法也类似;下面对上面的代码做简单的分析:
int stat(const char *path, struct stat *buf);
stat() 是一个标准C库函数,通常在 <sys/stat.h> 头文件中声明,用于获取文件或目录的状态信息。
const char *path
: 一个指向包含文件路径的指针。可以是绝对路径,也可以是相对于当前工作目录的相对路径。struct stat *buf
: 一个指向 struct stat
结构体的指针,用于接收由 stat()
函数填充的关于指定路径对象的信息,例如:st_size
)st_atime
, st_mtime
, st_ctime
)st_mode
)函数返回值:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。