首先了解什么是“值-结果”参数,假设有如下代码:
struct sockaddr_un cli;
int len;
len = sizeof(cli);
// unixfd 和 SA 在此不需要注意
getpeername(unixfd, (SA *)&cli, &len);
本例中 getpeername 函数的入参 len 本身有值,即结构体变量 cli 的大小,用于告诉内核待会写 cli 的值时别写越界了,它只有 len 的大小;
当内核写完 cli 的值时,它需要告诉应用进程到底写了多大的值,此时通过 len 传达,从某种程度上可以理解为,“值-结果”参数即充当了入参又充当了出参两个角色。(思考:那么应用进程知道了实际的套接字地址大小时有什么作用呢?)
“值-结果”参数的概念:
当函数参数是从 内核 到 进程 时:
函数被调用时,参数大小是一个值,进程告诉内核该参数的结构大小避免内核写操作越界;
函数返回时,参数的结构大小又是一个结果,应用进程可以知道内核所写数据的大小。
往往涉及到两个参数:存储数据的结构体指针 和 存储结构体大小的整数指针
在网络编程中,“值-结果”参数的在许多函数中会用到。
从内核到进程传递套接字地址结构的有4个函数:
- int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
- ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen); - int getsockname(int sockfd, struct sockaddr *localaddr, socklen_t *addrlen);
- int getpeername(int sockfd, struct sockaddr *peeraddr, socklen_t *addrlen);