udp sendto() 할 때, iovec 의 구조를 모르겠습니다.

trymp의 이미지

아래 함수는 udp sendto() 할 때 kernel 단에서 호출되는 함수인데요.

왜 iov를 iov++ 하면서 사용하는지 모르겠습니다. iov 가 배열형태로 계속 연결이 되어 있는 것인가요??
iovec 가 어떤 구조로 이루어져서 이런식으로 ++ 해서 사용하는지 모르겠습니다.
고수님들의 조언 부탁드립니다.

 
int memcpy_fromiovecend(unsigned char *kdata, struct iovec *iov, int offset,
			int len)
{
	/* Skip over the finished iovecs */
	while (offset >= iov->iov_len) {
		offset -= iov->iov_len;
		iov++;
	}
 
	while (len > 0) {
		u8 __user *base = iov->iov_base + offset;
		int copy = min_t(unsigned int, len, iov->iov_len - offset);
 
		offset = 0;
		if (copy_from_user(kdata, base, copy))
			return -EFAULT;
		len -= copy;
		kdata += copy;
		iov++;
	}
 
	return 0;
}

익명 사용자의 이미지

일단 offset이 중요합니다.

offset이 있으면 iov 배열을 돌면서 offset이 더 크면 iov 구조체를 skip 합니다.
그리고 offset 을 skip 한 크기만큼 줄이구요, 이게 첫 while 문이 의미하는 바입니다.

두번째는 offset 이 어느정도 남을 겁니다. 위에서 다 쳐내고 남은 그러니깐 최대 iov->iov_len이 갖는 크기 -1 정도 되겠죠? 그 iov_len 의 크기는 가변적이니깐 저렇게 해놨을 거고,

그럼 그 정보를 + 해서 base를 구하구요 base에서 복사할 크기를 구하는데, 역시 주어진 len 과 iov 의 크기에서 offset 을 뺀 크기 중 작은 걸로 복사할 양을 구합니다.

그리고 user land 에서 그 크기만큼 복사하구요,

복사한 양 만큼 실제 len 을 빼 줍니다.
kdata 의 offset은 그 만큼 추가하구요. offset은 이미 앞에서 다 썼으니 0 으로 주고.
그리고 len이 남으면 iov를 계속해서 읽습니다. len 0 이 될 때 까지요.

저도 이 코드 보면서 궁금한 점은 iov 가 무한 배열인가 ? 인데, 커널에서 그럴리는 없고..
iov 갯수를 체크하는 건 없네요. 혹시나 len 이 많이 들어와서 iov 보다 많다면 뻑날 코드 같기도 한데..

trymp의 이미지

..