创建 socket 使用 socket(int domain, int type, int protocol) 函数,三个参数决定了 socket 的类型和特性。
协议族(domain/address family)
主要协议族包括:
AF_INET / PF_INET:IPv4 协议
AF_INET6 / PF_INET6:IPv6 协议
AF_UNIX / PF_UNIX:Unix 域协议(本地通信)
AF_PACKET / PF_PACKET:底层数据包接口
AF_NETLINK:内核与用户空间通信
AF_X25:X.25 协议
AF_AX25:Amateur Radio AX.25 协议
AF_ATMPVC:ATM PVCs
AF_APPLETALK:AppleTalk
AF_BLUETOOTH:蓝牙协议
Socket 类型(type)
主要类型包括:
SOCK_STREAM:面向连接的字节流
SOCK_DGRAM:无连接的数据报
SOCK_SEQPACKET:有序、可靠、基于连接的双向数据报传输
SOCK_RAW:原始网络协议访问
SOCK_RDM:可靠的数据报层(不保证顺序)
SOCK_PACKET: 是旧版接口(已弃用)
常见协议组合
传输层协议
TCP 协议:
socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) - IPPROTO_TCP(6)
通常 protocol 参数可以设为 0,系统会自动选择 TCP
UDP 协议:
socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP) - IPPROTO_UDP(17)
同样,protocol 参数可以设为 0
SCTP 协议:
socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP)
socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP)
网络层协议
原始 IP 套接字:
socket(AF_INET, SOCK_RAW, IPPROTO_RAW) - 可以构造完整的 IP 包 IPPROTO_RAW(255)
socket(AF_INET, SOCK_RAW, IPPROTO_ICMP) - 接收 ICMP 包 IPPROTO_ICMP(1)
socket(AF_INET, SOCK_RAW, IPPROTO_IGMP) - 接收 IGMP 包 IPPROTO_IGMP(2)
socket(AF_INET, SOCK_RAW, IPPROTO_IPIP) - IPIP(网络层) IPPROTO_IPIP(4)
socket(AF_INET, SOCK_RAW, IPPROTO_GRE) - GRE(网络层) IPPROTO_GRE(47)
接收的数据包含完成的IP包头;默认发送无需自行拼接IP包头,如果设置了setsockopt(sock, IPPROTO_IP, IP_HDRINCL, &optval, sizeof(int)) 则发包时需要自行拼接包头;
网络层数据不存在沾包情况,因为网络数据有明确的大小,每个数据包有编号,当数据超过MTU时,内核自动分包;接收端自行重组,应用程序收到的是原始IP头和数据
IPv6 原始套接字:
socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)
数据链路层协议
原始以太网帧:
socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)) - 接收所有协议 ETH_P_ALL(0x0003)
socket(AF_PACKET, SOCK_RAW, htons(ETH_P_IP)) - 仅接收 IP 包 ETH_P_IP(0x0800)
socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ARP)) - 接收 ARP 包 ETH_P_ARP(0x0806)
socket(AF_PACKET, SOCK_PACKET, htons(ETH_P_ALL)) - 旧版链路层套接字(已弃用)
接收数据时包含完整的以太网头+对应协议包头和数据;发送时需要自行拼接以太网包头;使用时注意需要用htons(ETH_P_*)
数据链路层数据报:
socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_IP))
其他协议
Unix 域套接字:
socket(AF_UNIX, SOCK_STREAM, 0) - 流式 Unix 域套接字
socket(AF_UNIX, SOCK_DGRAM, 0) - 数据报 Unix 域套接字
Netlink 套接字:
socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE) - 路由信息
socket(AF_NETLINK, SOCK_RAW, NETLINK_USERSOCK) - 保留给用户程序
蓝牙协议:
socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM)
socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP)
SOCK_STREAM 和 SOCK_DGRAM 的使用范围
关于 SOCK_STREAM 和 SOCK_DGRAM 是否只能用于传输层套接字的问题:
主要用途:
SOCK_STREAM 和 SOCK_DGRAM 主要用于传输层协议(TCP/UDP/SCTP等)
其他用途:
它们也可以用于非传输层的套接字,例如:Unix 域套接字(AF_UNIX)支持这两种类型
某些特殊协议也可能支持这些类型
典型组合:
在 AF_INET/AF_INET6 域中:
SOCK_STREAM 几乎总是与 TCP 协议关联
SOCK_DGRAM 几乎总是与 UDP 协议关联
在 AF_UNIX 域中:
SOCK_STREAM 提供可靠的字节流
SOCK_DGRAM 提供保留消息边界的数据报服务
例外情况:
某些非传输层协议可能使用这些类型,但这是特例而非惯例
例如,AF_PACKET 理论上可以使用 SOCK_DGRAM,但实际中更常用 SOCK_RAW
因此,虽然 SOCK_STREAM 和 SOCK_DGRAM 主要用于传输层套接字,但它们并非只能用于传输层,在某些其他协议族中也有应用。
Socket 选项通过 setsockopt 和 getsockopt 系统调用控制,参数结构为:
int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);
int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen);
其中:
level:选项级别(协议层)
optname:具体选项名称
optval:选项值指针
optlen:选项值长度
level的值:
通用套接字选项 (SOL_SOCKET)
IP协议选项 (IPPROTO_IP)
TCP协议选项 (IPPROTO_TCP)
IPv6协议选项 (IPPROTO_IPV6)
数据链路层选项 (SOL_PACKET)
以下按协议层级分类说明常用选项:
🔧 一、通用套接字选项 (SOL_SOCKET)
适用于所有套接字类型的通用选项
📌 setsockopt 选项
选项名 值类型 含义 使用场景
SO_REUSEADDR int 允许重用本地地址(TIME_WAIT状态) 服务器快速重启
SO_REUSEPORT int 允许多个进程绑定相同IP+端口 多进程服务器负载均衡
SO_KEEPALIVE int 开启TCP保活机制 检测死连接(需结合TCP_KEEP*选项)
SO_LINGER struct linger 关闭时处理未发送数据 控制关闭行为:{ l_onoff=1, l_linger=超时秒数 }
SO_SNDBUF int 设置发送缓冲区大小 高吞吐量传输优化
SO_RCVBUF int 设置接收缓冲区大小 高吞吐量传输优化
SO_BINDTODEVICE char[] 绑定到指定网络接口 多网卡服务器流量隔离
SO_BROADCAST int 允许发送广播数据 UDP广播应用 需设置 SO_BROADCAST 才能发送广播数据
SO_DONTROUTE int 不经过路由表直接发送 局域网调试
SO_OOBINLINE int 将带外数据放入普通数据流 处理紧急数据
SO_TIMESTAMP int 接收数据时添加时间戳 网络延迟测量
SO_ERROR int 获取并清除套接字错误状态 异步I/O错误处理
SO_RCVTIMEO struct timeval 接收超时时间 阻塞式套接字的接收超时 设置 recv() 的最大等待时间
SO_SNDTIMEO struct timeval 发送超时时间 阻塞式套接字的发送超时 设置 send() 的最大等待时间
SO_ATTACH_FILTER 绑定 BPF 过滤器 过滤网络数据包 struct sock_fprog 用于 AF_PACKET 套接字过滤数据包
SO_ATTACH_BPF 绑定 BPF 程序 高级数据包处理 struct bpf_program 用于 eBPF 程序绑定
SO_ATTACH_REUSEPORT_CB 绑定到 SO_REUSEPORT 多进程共享端口 int 仅用于 SO_REUSEPORT 的扩展
SO_DETACH_REUSEPORT_CB 解除 SO_REUSEPORT绑定 多进程共享端口 int 与 SO_ATTACH_REUSEPORT_CB 配合使用
SO_PASSCRED 获取进程凭证 传递进程信息 int 用于 AF_UNIX 套接字获取发送方的 UID、PID 等信息
SO_PEERNAME 获取对端地址 获取连接的对端地址 struct sockaddr 仅用于已连接的套接字(如 TCP)
SO_PEERSEC 获取对端安全上下文 获取对端的安全信息 char* 用于 SELinux 等安全模块
SO_RCVBUFFORCE 强制设置接收缓冲区 超过系统限制的缓冲区 int 需 CAP_NET_ADMIN 权限
SO_SNDBUFFORCE 强制设置发送缓冲区 超过系统限制的缓冲区 int 需 CAP_NET_ADMIN 权限
SO_RCVNORUSH 接收时不触发 SIGIO 控制信号触发 int 用于 SOCK_DGRAM 套接字
SO_SNDNORUSH 发送时不触发 SIGIO 控制信号触发 int 用于 SOCK_DGRAM 套接字
SO_NO_CHECK 禁用校验和 用于原始套接字 int 仅用于 SOCK_RAW 套接字,禁用 IP 校验和
🔍 getsockopt 选项
选项名 值类型 含义
SO_TYPE int 获取套接字类型 (e.g. SOCK_STREAM)
SO_ERROR int 获取套接字错误码
SO_ACCEPTCONN int 检测是否监听套接字
SO_SNDBUF int 获取发送缓冲区大小
SO_RCVBUF int 获取接收缓冲区大小
SO_SNDLOWAT int 获取发送低水位标记
SO_RCVLOWAT int 获取接收低水位标记
SO_DOMAIN int 获取协议域 (e.g. AF_INET)
🌐 二、IP协议选项 (IPPROTO_IP)
适用于IPv4套接字
📌 setsockopt 选项
选项名 值类型 含义 使用场景
IP_TOS int 设置服务类型字段 (DSCP/ECN) QoS流量控制
IP_TTL int 设置生存时间 (TTL) 控制数据包传播范围
IP_HDRINCL int 包含IP头部(原始套接字) 手动构造IP包
IP_OPTIONS uint8_t[] 设置IP选项 源路由等高级功能
IP_PKTINFO int 启用报文信息辅助数据 获取目的IP和接口信息
IP_RECVERR int 接收详细的ICMP错误信息 精准诊断网络问题
IP_MTU_DISCOVER int 路径MTU发现策略 1:禁用 2:始终分片 3:启用发现(默认)
IP_RECVTTL int 接收IP头部的TTL字段 网络拓扑分析
IP_MULTICAST_IF in_addr 设置多播输出接口 多网卡环境选择多播网卡
IP_MULTICAST_TTL u_char 设置多播TTL 控制多播传播范围
IP_MULTICAST_LOOP u_char 多播数据回环控制 0:禁用 1:启用(默认)
IP_ADD_MEMBERSHIP struct ip_mreq 加入多播组 多播接收
IP_DROP_MEMBERSHIP struct ip_mreq 离开多播组 多播组管理
🔍 getsockopt 选项
选项名 值类型 含义
IP_TOS int 获取服务类型字段
IP_TTL int 获取生存时间
IP_RECVTTL int 检查TTL接收功能是否开启
IP_PKTINFO int 检查报文信息功能是否开启
IP_MTU int 获取路径MTU
IP_MULTICAST_IF in_addr 获取多播输出接口
IP_MULTICAST_TTL u_char 获取多播TTL
IP_MULTICAST_LOOP u_char 获取多播回环设置
⚡ 三、TCP协议选项 (IPPROTO_TCP)
仅适用于TCP流套接字
📌 setsockopt 选项
选项名 值类型 含义 使用场景
TCP_NODELAY int 禁用Nagle算法 (1=禁用) 实时性要求高的应用
TCP_MAXSEG int 设置最大分段大小 (MSS) 优化传输效率
TCP_KEEPIDLE int 首次保活探测前的空闲时间(秒) 自定义保活检测频率
TCP_KEEPINTVL int 保活探测间隔(秒) 自定义保活检测频率
TCP_KEEPCNT int 保活探测次数 自定义保活检测次数
TCP_QUICKACK int 启用快速ACK模式 (1=启用) 减少延迟
TCP_CORK int 开启TCP_CORK (1=开启) 合并小包提高吞吐量
TCP_FASTOPEN int 启用TCP快速打开 (队列大小) 减少TLS握手延迟
TCP_DEFER_ACCEPT int 推迟accept直到数据到达(秒) 避免空连接浪费资源
TCP_INFO struct tcp_info 设置TCP信息参数 高级TCP诊断和控制
🔍 getsockopt 选项
选项名 值类型 含义
TCP_NODELAY int 获取Nagle算法状态
TCP_MAXSEG int 获取当前MSS值
TCP_INFO struct tcp_info 获取详细TCP连接信息
TCP_KEEPIDLE int 获取保活空闲时间
TCP_KEEPINTVL int 获取保活探测间隔
TCP_KEEPCNT int 获取保活探测次数
TCP_SYNCNT int 获取SYN重试次数
🌍 四、IPv6协议选项 (IPPROTO_IPV6)
适用于IPv6套接字
📌 setsockopt 选项
选项名 值类型 含义 使用场景
IPV6_V6ONLY int 限制只处理IPv6数据 (1=启用) 避免IPv4映射地址问题
IPV6_RECVPKTINFO int 接收目的IPv6和接口索引 高级路由选择
IPV6_RECVHOPLIMIT int 接收跳数限制字段 网络拓扑分析
IPV6_RECVRTHDR int 接收路由头 源路由支持
IPV6_UNICAST_HOPS int 设置单播跳数限制 控制数据包传播范围
IPV6_MULTICAST_IF int 设置多播输出接口索引 多网卡环境选择多播网卡
IPV6_MULTICAST_HOPS int 设置多播跳数限制 控制多播传播范围
IPV6_MULTICAST_LOOP int 设置多播回环 (1=启用) 本地接收自己发送的多播包
IPV6_JOIN_GROUP struct ipv6_mreq 加入IPv6多播组 多播接收
IPV6_LEAVE_GROUP struct ipv6_mreq 离开IPv6多播组 多播组管理
IPV6_CHECKSUM int 设置原始套接字的校验和偏移 高级网络编程
IPV6_RTHDRDSTOPTS int 接收目标选项头 IPv6扩展支持
🔍 getsockopt 选项
选项名 值类型 含义
IPV6_V6ONLY int 获取IPv6-only状态
IPV6_RECVPKTINFO int 检查PKTINFO接收功能是否开启
IPV6_RECVHOPLIMIT int 检查HOPLIMIT接收功能是否开启
IPV6_UNICAST_HOPS int 获取单播跳数限制
IPV6_MULTICAST_IF int 获取多播输出接口索引
IPV6_MULTICAST_HOPS int 获取多播跳数限制
IPV6_MULTICAST_LOOP int 获取多播回环设置
📡 五、数据链路层选项 (SOL_PACKET)
适用于原始数据包套接字 (AF_PACKET)
📌 setsockopt 选项
选项名 值类型 含义 使用场景
PACKET_ADD_MEMBERSHIP struct packet_mreq 加入数据链路层组 接收特定MAC组播或混杂模式
PACKET_DROP_MEMBERSHIP struct packet_mreq 离开数据链路层组 停止接收特定MAC组播
PACKET_FANOUT int 设置数据包分发策略 多线程/多进程数据包处理负载均衡
PACKET_LOSS int 设置接受丢包报告 (1=启用) 网络监控工具
PACKET_RECV_OUTPUT int 控制输出方向数据包处理 流量控制
PACKET_TIMESTAMP int 设置时间戳精度 1=软件时间戳 2=硬件原始时间戳 3=硬件转换时间戳
PACKET_VERSION int 设置数据包版本 兼容不同内核版本
PACKET_QDISC_BYPASS int 绕过内核队列规则 (1=启用) 高性能网络应用
🔍 getsockopt 选项
选项名 值类型 含义
PACKET_HDRLEN int 获取数据包头部长度
PACKET_STATISTICS struct tpacket_stats 获取数据包统计信息
PACKET_VERSION int 获取当前数据包版本
PACKET_FANOUT struct fanout_args 获取分发策略配置
💡 六、高级选项组合策略
🚀 性能优化组合
// 高吞吐量TCP服务器
int yes = 1;
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes));
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes));
int bufsize = 1024 * 1024; // 1MB
setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize));
setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(bufsize));
📶 网络诊断组合
// 网络路径诊断
int true = 1;
setsockopt(sock, IPPROTO_IP, IP_RECVERR, &true, sizeof(true));
setsockopt(sock, IPPROTO_IP, IP_RECVTTL, &true, sizeof(true));
setsockopt(sock, SOL_SOCKET, SO_TIMESTAMP, &true, sizeof(true));
// 获取连接信息
struct tcp_info info;
socklen_t len = sizeof(info);
getsockopt(sock, IPPROTO_TCP, TCP_INFO, &info, &len);
🛡️ 安全增强组合
// IPv6服务器安全加固
int v6only = 1;
setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &v6only, sizeof(v6only));
// 限制服务器只接受完整连接
int defer_accept = 3; // 等待数据3秒
setsockopt(sock, IPPROTO_TCP, TCP_DEFER_ACCEPT, &defer_accept, sizeof(defer_accept));
// 绑定特定网络接口
char ifname[] = "eth0";
setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, ifname, sizeof(ifname));
⚠️ 七、关键注意事项
缓冲区大小限制:
设置值可能被内核调整为系统限制范围内
使用getsockopt验证实际设置值
选项继承:
accept()返回的套接字继承监听套接字选项
TCP_NODELAY等选项需单独设置
平台差异:
#if defined(__linux__)
// Linux特有选项
setsockopt(sock, IPPROTO_TCP, TCP_FASTOPEN, ...);
#elif defined(__APPLE__)
// macOS特有选项
setsockopt(sock, IPPROTO_TCP, TCP_KEEPALIVE, ...);
#endif
权限要求:
原始套接字选项(PACKET_*)需要CAP_NET_RAW能力
网络接口绑定需要特权
生效时机:
部分选项需在特定状态前设置(如bind/listen前)
fcntl 函数基础:
fcntl 的调用格式为:
int fcntl(int fd, int cmd, ...);
cmd 是操作码,arg 是参数(根据 cmd 类型不同,参数类型可能为 int、struct flock、struct sigevent 等)。
二、常用参数组合及含义
1. F_GETFL / F_SETFL:获取/设置文件状态标志
F_GETFL 返回的标志是 O_RDONLY、O_WRONLY、O_RDWR、O_APPEND、O_ASYNC、O_NONBLOCK 等。
F_SETFL 可以设置 O_APPEND、O_ASYNC、O_NONBLOCK,但不能设置 O_RDONLY、O_WRONLY、O_RDWR(这些标志只能在 open 时设置)。
使用场景:
设置非阻塞模式(O_NONBLOCK):用于异步 I/O。
设置异步信号(O_ASYNC):用于 SIGIO 信号通知。
设置追加模式(O_APPEND):用于文件写入时自动追加数据。
注意:O_APPEND 仅对文件有效,套接字通常不使用此标志。
示例:
// 设置非阻塞模式
int flags = fcntl(fd, F_GETFL, 0);
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
// 获取当前标志
int flags = fcntl(fd, F_GETFL);
2. F_GETFD / F_SETFD:获取/设置文件描述符标志
F_GETFD 返回的标志包括:
FD_CLOEXEC:设置后,exec() 调用时关闭文件描述符。
使用场景:
在多进程编程中,避免子进程继承父进程的文件描述符。
注意:FD_CLOEXEC 是 fcntl 的 F_SETFD 操作码的参数,需与 F_SETFD 配合使用。
示例:
// 设置 FD_CLOEXEC
fcntl(fd, F_SETFD, FD_CLOEXEC);
// 获取 FD_CLOEXEC 标志
int flags = fcntl(fd, F_GETFD);
3. F_GETOWN / F_SETOWN:获取/设置套接字的信号接收者
用于设置套接字的信号接收者,通常与 O_ASYNC 配合使用。
使用场景:
在异步 I/O 中,指定哪个进程接收 SIGIO 信号。
注意:F_SETOWN 设置的是进程 ID,而 F_SETOWN_EX 可设置进程组或线程组。
示例:
// 设置 SIGIO 信号接收者为当前进程
fcntl(fd, F_SETOWN, getpid());
// 获取当前信号接收者
int pid = fcntl(fd, F_GETOWN);
4. F_GETOWN_EX / F_SETOWN_EX:获取/设置套接字的信号接收者(进程组/线程组)
F_SETOWN_EX 支持更细粒度的信号接收者设置(进程组、线程组)。
参数结构体:
struct f_owner_ex {
int type; // F_OWNER_PID(进程 ID)、F_OWNER_PGRP(进程组)、F_OWNER_TGID(线程组)
pid_t pid; // 进程 ID
};
使用场景:
在多线程环境中,设置线程组接收 SIGIO 信号。
注意:需 CAP_SYS_ADMIN 权限。
示例:
struct f_owner_ex owner = {F_OWNER_TGID, gettid()};
fcntl(fd, F_SETOWN_EX, &owner);
5. F_GETLK / F_SETLK / F_SETLKW:文件锁操作
cmd 参数类型 含义 使用场景 说明
F_GETLK struct flock 获取文件锁状态 获取文件锁信息 用于检查文件是否被锁定
F_SETLK struct flock 设置文件锁(非阻塞) 非阻塞加锁 无法等待,立即返回
F_SETLKW struct flock 设置文件锁(阻塞) 阻塞加锁 会等待直到锁释放
F_GETLK struct flock 获取文件锁状态 获取文件锁信息 用于检查文件是否被锁定
套接字通常不使用文件锁,但某些系统(如 Linux)支持对文件描述符加锁。
使用场景:
多进程共享文件描述符时,避免并发访问。
注意:套接字的 fcntl 操作可能不支持文件锁,需确认系统支持。
示例:
struct flock fl;
fl.l_type = F_WRLCK;
fcntl(fd, F_SETLK, &fl); // 非阻塞加锁
6. F_GETLEASE / F_SETLEASE:文件租约(Lease)
cmd 参数类型 含义 使用场景 说明
F_GETLEASE int 获取文件租约类型 获取租约状态 用于文件租约管理
F_SETLEASE int 设置文件租约 设置租约类型 仅在支持租约的文件系统中有效
F_GETLEASE int 获取租约类型 获取租约状态 用于文件租约管理
F_SETLEASE int 设置租约 设置租约类型 仅在支持租约的文件系统中有效
套接字通常不使用租约,但某些系统(如 Linux)支持。
使用场景:
文件租约管理(如 F_SETLEASE 设置租约类型)。
注意:套接字的 fcntl 通常不涉及租约。
示例:
int lease = fcntl(fd, F_GETLEASE);
7. F_GETSIG / F_SETSIG:获取/设置信号
cmd 参数类型 含义 使用场景 说明
F_GETSIG int 获取当前信号 获取 SIGIO 信号 用于查询当前信号
F_SETSIG int 设置信号 设置 SIGIO 信号 用于指定信号类型(如 SIGIO、SIGURG)
F_GETSIG int 获取当前信号 获取 SIGIO 信号 用于查询当前信号
F_SETSIG int 设置信号 设置 SIGIO 信号 用于指定信号类型(如 SIGIO、SIGURG)
用于设置套接字的信号类型(如 SIGIO、SIGURG)。
使用场景:
配合 F_SETFL 的 O_ASYNC 标志,指定信号类型。
注意:F_SETSIG 仅在 Linux 中支持,其他系统可能不兼容。
示例:
// 设置 SIGIO 信号
fcntl(fd, F_SETSIG, SIGIO);
// 获取当前信号
int sig = fcntl(fd, F_GETSIG);
8. F_GETOWN / F_SETOWN:获取/设置套接字的信号接收者
cmd 参数类型 含义 使用场景 示例
F_GETOWN int 获取当前信号接收者(进程 ID) 获取 SIGIO 信号的接收者 int pid = fcntl(fd, F_GETOWN);
F_SETOWN int 设置信号接收者(进程 ID) 设置 SIGIO 信号的接收者 fcntl(fd, F_SETOWN, pid);
说明:
与 F_GETOWN_EX 的区别:
F_SETOWN 仅支持进程 ID。
F_SETOWN_EX 支持进程组、线程组。
使用场景:
在多进程环境中,指定哪个进程接收 SIGIO 信号。
示例:
// 设置 SIGIO 信号接收者为当前进程
fcntl(fd, F_SETOWN, getpid());
// 获取当前信号接收者
int pid = fcntl(fd, F_GETOWN);
9. F_GETFD / F_SETFD:获取/设置文件描述符标志
cmd 参数类型 含义 使用场景 示例
F_GETFD int 获取文件描述符标志 获取 FD_CLOEXEC int flags = fcntl(fd, F_GETFD);
F_SETFD int 设置文件描述符标志 设置 FD_CLOEXEC fcntl(fd, F_SETFD, FD_CLOEXEC);
FD_CLOEXEC:设置后,exec() 调用时关闭文件描述符。
使用场景:
在多进程编程中,避免子进程继承父进程的文件描述符。
示例:
// 设置 FD_CLOEXEC
fcntl(fd, F_SETFD, FD_CLOEXEC);
// 获取 FD_CLOEXEC 标志
int flags = fcntl(fd, F_GETFD);
10. F_GETOWN / F_SETOWN:获取/设置套接字的信号接收者
cmd 参数类型 含义 使用场景 示例
F_GETOWN int 获取当前信号接收者(进程 ID) 获取 SIGIO 信号的接收者 int pid = fcntl(fd, F_GETOWN);
F_SETOWN int 设置信号接收者(进程 ID) 设置 SIGIO 信号的接收者 fcntl(fd, F_SETOWN, pid);
说明:
与 F_GETOWN_EX 的区别:
F_SETOWN 仅支持进程 ID。
F_SETOWN_EX 支持进程组、线程组。
使用场景:
在多进程环境中,指定哪个进程接收 SIGIO 信号。
示例:
// 设置 SIGIO 信号接收者为当前进程
fcntl(fd, F_SETOWN, getpid());
// 获取当前信号接收者
int pid = fcntl(fd, F_GETOWN);