LINUX.ORG.RU

Про преобразования сокетов

 , ,


0

1

Копаюсь в ядре Linux и частенько натыкаюсь, например, на такое:

struct inet_connection_sock *icsk = build_icsk(test);
KUNIT_ASSERT_EQ(test, 0,
                       mptcp_token_new_connect((struct sock *)icsk));

Вопрос: как работает вот это выражение:

(struct sock *)

Это, я так понимаю, преобразование из одной структуры в другую? Но как это происходит? Где посмотреть?


Может быть, struct inet_connection_sock является «подклассом» struct sock? В сишном смысле: т.е. содержит те же поля, что и sock (или же всю структуру sock первым полем), плюс под ними ещё что-то.

pr849
()
Последнее исправление: pr849 (всего исправлений: 1)

преобразование из одной структуры в другую? Но как это происходит?

По-байтово. Если на пальцах struct A * ссылается на какой-то кусок памяти. Этот же кусок памяти можно прочесть и как будто это struct B *.

Смотри ещё в частности тут для классики struct sockaddr_in * и struct sockaddr * (обе стурктуры одинаковые по размеру и поэтому этот финт ушами проходит безнаказанно): https://www.gta.ufrj.br/ensino/eel878/sockets/sockaddr_inman.html

beastie ★★★★★
()
Последнее исправление: beastie (всего исправлений: 1)
Ответ на: комментарий от pr849

Я попытался вставить определения struct inet_connection_sock и struct sock, но сообщение получилось слишком большое. Поэтому приведу ссылки на первое и второе.

czan
() автор топика
Ответ на: комментарий от beastie

По-байтово.

Да, вот это больше похоже на правду. Решил проверить. Набросал такое:

#include <stdio.h>

struct foo {
  int k ;
} ;

struct bar {
  int ch ;
} ;

int main () {
  struct foo first ;
  first.k = 42 ;
  struct bar *second = (struct bar *)&first ;
  printf ("first.k = %d\n", first.k) ;
  printf ("second->ch = %d\n", second->ch) ;
  return (0) ;
}

И действительно выдало:

$ ./a.out
first.k = 42
second->ch = 42

Спасибо! Теперь попробую сравнить по размерам.

czan
() автор топика

В данном случае мы имеем некое подобие «наследования». Смотрим на первые поля в цепочке:

struct inet_connection_sock {
	/* inet_sock has to be the first member! */
	struct inet_sock	  icsk_inet;
	// ...
};

struct inet_sock {
	/* sk and pinet6 has to be the first two members of inet_sock */
	struct sock		sk;
	// ...
};

Тем самым преобразование struct inet_connection_sock в struct sock * является «законным» с точки зрения стандарта Си.

AlexVR ★★★★★
()
Ответ на: комментарий от pr849

Почему пытались? Вроде же включили патчи в ядрышко?

Ну и не стоит путать рядового питониста с Гвидо.

pon4ik ★★★★★
()

Блин, я прошу прощения за оффтоп, но как же меня бесит твоя аватарка. Думаешь, раз молодая и красивая, то всегда такой будешь? Ничего, и тебя жизнь поломает.

pr849
()
Ответ на: комментарий от AlexVR

Вот это было действительно круто! Спасибо! Решил провести эксперимент. Набросал такое:

#include <stdio.h>

struct layer1 {
  int k ;
} ;

struct layer2 {
  struct layer1 lr ;
  int ch ;
} ;

struct layer3 {
  struct layer2 t ;
  int vb ;
} ;

int main () {
  struct layer3 w ;
  w.vb = 12 ;
  w.t.ch = 13 ;
  w.t.lr.k = 14 ;

  struct layer1 *x = (struct layer1 *) &w;
  printf ("k = %d\n", x->k) ;
  return (0) ;
}

И действительно, выдало:

$ ./a.out
k = 14
czan
() автор топика
Ответ на: комментарий от pr849

Прошу прощения за раздражение, но эта аватарка от thispersondoesnotexist. Можете не агриться.

czan
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.